理解在Nginx + OpenResty

时间:2017-05-22 17:41:49

标签: nginx lua quoting openresty

为了进行测试,我需要在OpenResty的Nginx服务器中创建一些虚假数据。我需要创建一个复制一个IP地址的数组,例如:

 ["1.2.3.4", "1.2.3.4", ...]

在Ruby中,实现可能如下所示:

 "[" + (["\"1.2.3.4\""] * 4096).join(", ") + "]"

我是Lua的初学者,为了让它在OpenResty环境中工作,我付出了很多努力。这最终似乎有效:

   content_by_lua '
        -- ... some code ...
        local ips = {}
        for i=1,4096 do ips[i] = "\\"1.2.3.4\\"" end
        local fakeData = table.concat(ips, ", ")
        local fakeResponse = "[" .. fakeData .. "]"
        --- ...
   '

我在字符串引用方面遇到了一些问题。首先,我尝试了'"1.2.3.4"',它在内联Lua部分不起作用。这是可以理解的,因为'字符已经是content_by_lua部分的分隔符。

接下来,我尝试了"\"1.2.3.4\"",我原本期望这样做,但这导致了这个(令人困惑的)错误:

failed to load inlined Lua code:
content_by_lua(nginx.conf:235):17: malformed number near '1.2.3.4'

通过反复试验,我发现如果您使用双引号("\\"1.2.3.4\\""),则此错误会消失。这适用于OpenResty,但如果我在Lua REPL中尝试使用相同的代码:

$ rep.lua 
Lua REPL 0.8
> "\\"1.2.3.4\\""
[string "REPL"]:1: unexpected symbol near '"\"'

为了帮助我理解并成为更好的Lua / OpenResty程序员,我对引用有一些疑问:

  1. 为什么需要双引号(在OpenResty中)? (为什么"\\"1.2.3.4\\""代替"\"1.2.3.4\""?)
  2. 为什么OpenResty的行为与Lua REPL不同?
  3. 是否可以在content_by_lua部分使用单引号? (将其简化为'"1.2.3.4"'
  4. (另外,一个令我困扰的无关问题。有没有更简单的方法来表达代码?当我将它与我的Ruby代码段进行比较时,我很确定它也可以在Lua中更优雅地表达。 )

1 个答案:

答案 0 :(得分:1)

正如Egor所说,这是因为在Lua解析之前,nginx配置文件解析器会删除反斜杠字符\。在您的情况下,"\\"1.2.3.4\\""是正确的,因为它由nginx配置解析器解析为"\"1.2.3.4\"",然后由Lua解析为字符串"1.2.3.4"

如果您不想担心使用多少反斜杠,可以选择其他几种。最简单的方法是使用content_by_lua_block,可以从OpenResty v0.9.17开始使用。

content_by_lua_block {
    -- ... some code ...
    local ips = {}
    for i=1,4096 do ips[i] = '"1.2.3.4"' end
    local fakeData = table.concat(ips, ", ")
    local fakeResponse = "[" .. fakeData .. "]"
    --- ...
}

如果你不能在你的OpenResty版本中使用Lua块,那么你可以使用Lua的multiline string syntax

content_by_lua '
    -- ... some code ...
    local ips = {}
    for i=1,4096 do ips[i] = [["1.2.3.4"]] end
    local fakeData = table.concat(ips, ", ")
    local fakeResponse = "[" .. fakeData .. "]"
    --- ...
'

有关详细信息,请参阅OpenResty docs

此外,如果您想避免使用表格,可以使用string.rep制作相同的测试数据。

content_by_lua '
    -- ... some code ...
    local ip = [["1.2.3.4"]]
    local fakeResponse = "[" .. string.rep(ip .. ", ", 4095) .. ip .. "]"
    --- ...
'