1

For testing, I needed to create some fake data in an Nginx server with OpenResty. I needed to create an array where one IP address is replicated, for example:

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

In Ruby, an implementation could look like this:

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

I'm a beginner in Lua, and I struggled quite a lot to get it working in the OpenResty environment. This is what finally seems to work:

   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 .. "]"
        --- ...
   '

I had some problems with the string quoting. First, I tried '"1.2.3.4"', which did not work in the inline Lua section. That is understandable because the ' character is already the separator for the content_by_lua section.

Next, I tried "\"1.2.3.4\"", which I would have expected to work, but it resulted in this (confusing) error:

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

By trial and error, I found out that this error goes away if you use double quoting ("\\"1.2.3.4\\""). This works in OpenResty, although the same code is rejected if I try it out in the Lua REPL:

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

To help me understand and become a better Lua/OpenResty programmer, I have some questions about quoting:

  1. Why do you need double-quoting (in OpenResty)? (Why "\\"1.2.3.4\\"" instead of "\"1.2.3.4\""?)
  2. Why does OpenResty behave differently than the Lua REPL?
  3. Is it possible to use single quotes in content_by_lua sections? (To simplify it to '"1.2.3.4"')

(Also, an unrelated question that bothers me. Is there there a simpler way to express the code? When I compare it with my Ruby snippet, I'm quite sure that it can also be expressed much more elegantly in Lua.)

2
  • Probably, OpenResty applies its own backslash-deescaping phase before feeding your Lua block to Lua VM. In other words, you need to do one more backslash-escaping compared to Lua REPL Commented May 22, 2017 at 18:16
  • In Lua block, you can use string.char() to make ' or " without using backslash: ips[i] = string.char(34).."1.2.3.4"..string.char(34) Commented May 22, 2017 at 18:20

1 Answer 1

1

As Egor says, this is because the backslash character \ is stripped out by the nginx config file parser before it is parsed by Lua. In your case, "\\"1.2.3.4\\"" is correct, because it is parsed to "\"1.2.3.4\"" by the nginx config parser, and then to the string "1.2.3.4" by Lua.

If you don't want to worry about how many backslashes to use, there are a couple of alternatives. The easiest is to use content_by_lua_block, which is available from OpenResty v0.9.17 onwards.

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 .. "]"
    --- ...
}

If you can't use Lua blocks in your version of OpenResty, instead you can use Lua's 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 .. "]"
    --- ...
'

For more detail, see the OpenResty docs.

Also, if you want to avoid working with tables at all, you can make the same test data by using string.rep.

content_by_lua '
    -- ... some code ...
    local ip = [["1.2.3.4"]]
    local fakeResponse = "[" .. string.rep(ip .. ", ", 4095) .. ip .. "]"
    --- ...
'
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.