LUA applet stop working after updating to 2.0.22

After updating from 2.0.17 to 2.0.22 my LUA function stops working with error (see below).
I could find only this (maybe related to my issue) :

    - BUG/MEDIUM: lua: Always init the lua stack before referencing the context

Is this a bug, or this is a feature?

error:

Jun 16 07:32:41 a-ha-inf1 haproxy[5543]: [ALERT] 166/073241 (5749) : Lua applet http '<lua.http_redirects>': runtime error: /etc/haproxy/scripts/http_redirects.lua:5: 'new': map: cannot load map at runtime. from [C]: in field 'new', /etc/haproxy/scripts/http_redirects.lua:5: in function line 1.

config:

global
  ...
  # load lua scripts
  lua-load /etc/haproxy/scripts/http_redirects.lua
  ...
frontend
  ...  
  ### HTTP Redirect Rules
  acl host_redirect_found req.hdr(host),lower,map_str(/etc/haproxy/scripts/http_redirects.map) -m found
  http-request use-service lua.http_redirects if host_redirect_found
  ...

script:

local function http_redirects(applet)

  local res = ""
  local hdr = applet.headers["host"][0]:lower()
  local map = Map.new("/etc/haproxy/scripts/http_redirects.map", Map._str)

  applet:set_status(302)

  applet:add_header("content-security-policy","default-src 'none'; form-action 'none'; frame-ancestors 'none'; report-uri https://example.com")
  applet:add_header("report-to","{\"group\":\"default\",\"max_age\":31536000,\"endpoints\":[{\"url\":\"https://example.com\"}],\"include_subdomains\":true}")
  applet:add_header("strict-transport-security", "max-age=63113904; includeSubDomains; preload")
  applet:add_header("x-content-type-options", "nosniff")
  applet:add_header("x-frame-options", "DENY")
  applet:add_header("x-xss-protection", "1; mode=block")
  applet:add_header("location", map:lookup(hdr))
  applet:add_header("content-length", string.len(res))

  applet:start_response()
  applet:send(res)

end

core.register_service("http_redirects", "http", http_redirects)

map:

old.example.com        https://new.example.com

It is a bug fix (BUG/MEDIUM: map/lua: Return an error if a map is loaded during runtime). Maps must be loaded during the init stage. So from a lua script, the maps must be loaded in the global part.

2 Likes

@capflam, thank you very much! You saved my day!

Here is working script:

local map = Map.new("/etc/haproxy/scripts/http_redirects.map", Map._str)

local function http_redirects(applet)

  local res = ""
  local hdr = applet.headers["host"][0]:lower()

  applet:set_status(302)

  applet:add_header("content-security-policy","default-src 'none'; form-action 'none'; frame-ancestors 'none'; report-uri https://example.com")
  applet:add_header("report-to","{\"group\":\"default\",\"max_age\":31536000,\"endpoints\":[{\"url\":\"https://example.com\"}],\"include_subdomains\":true}")
  applet:add_header("strict-transport-security", "max-age=63113904; includeSubDomains; preload")
  applet:add_header("x-content-type-options", "nosniff")
  applet:add_header("x-frame-options", "DENY")
  applet:add_header("x-xss-protection", "1; mode=block")
  applet:add_header("location", map:lookup(hdr))
  applet:add_header("content-length", string.len(res))

  applet:start_response()
  applet:send(res)

end

core.register_service("http_redirects", "http", http_redirects)