Lua functions are most commonly used to implement new conditions,
that can be used to select the Service section to use. Such
conditions are applied using LuaMatch statements in
Service sections. The LuaMatch statement takes at least
one argument: the name of Lua function to call. It can be followed by
any number of string values, which will be passed to the function as
its arguments. Before being passed to the function, these values
undergo backreference expansion and request accessor interpretation
(see Request modifications).
The first argument can be either an unqualified name, as ‘mycond’, or a fully qualified one, as ‘modname.mycond’. Use the latter form to call functions defined in modules.
Information about HTTP request is provided to Lua functions via
the built-in variable http.req, described in Lua API.
To illustrate the concept, here’s the definition of a Lua test that
returns true if the value of a header named in its first argument
matches any of its remaining arguments, treated as anchored Lua patterns:
function isheader(name, ...)
local args = { ... }
for _, pat in ipairs(args) do
if string.find(http.req.headers[name], "^"..pat.."$") then
return true
end
end
return false
end
Supposing that this function is defined in file isheader.lua, it can be used as follows:
Lua
Load "isheader.lua"
End
ListenHTTP
...
Service
LuaMatch "host" "foo[.]bar" "www[.]fo+[.]bar"
Backend
...
End
End
End
As a more practical example, the function below implements Bearer authorization scheme.
local bearer = {}
local jwt = require 'jwt'
function bearer.ok(secret)
-- Read in the Authorization header.
local bh = http.req.headers['Authorization']
if bh == nil then
return false
end
-- Check if it starts with "Bearer".
local n, k = bh:find('%s+')
if n == nil or bh:sub(1,n-1):lower() ~= 'bearer' then
return false
end
-- Extract the token and parse it.
local j, err = jwt.parse(bh:sub(k+1))
if err ~= nil then
return false
end
-- Verify the token.
if not j:verify(secret) then
return false
end
-- Check expiration time.
if j.payload.exp ~= nil then
local exp = tonumber(j.payload.exp)
if exp == nil then
return false
elseif os.time() < j.payload.exp then
return false
end
end
return true
end
return bearer
See jwt.lua, for the implementation of the jwt module.
The following configuration fragment uses bearer.ok function
as a condition, to reject requests without a valid bearer token:
Service
Not LuaMatch "bearer.ok" "secret"
Rewrite response
SetHeader "WWW-Authenticate: Bearer realm=\"Restricted access\""
End
Error 401
End