Custom reply
These functions only can be used in HTTP client side event (only HTTP_REQUEST now).
HTTP:redirect (“fmt”, …)
Reply to client with redirect response.
Example
when HTTP_REQUEST {
HTTP:redirect(“https://%s”, HTTP:host())
}
HTTP:reply (response)
Reply to client with custom response.
Argument response is a lua array. It includes:
-
status: Integer. Default is 200.
-
reason: String. If not set, the system will use the default value of status code. For example, if the status code is 200, the default value of reason is “OK”.
-
headers: Lua table. Each value of the table is a lua array. It contains all headers except “content-length”. “content-length” will be automatically set with the body size.
-
Body: String.
To be specific:
HTTP:reply{
status = 400,
reason = “test reason”,
headers = {
["content-type"] = { "text/html" },
["cache-control"] = { "no-cache", "no-store" },
},
body = "<html><body><h1>invalid request<h1></body></html>",
}
Example
function reply_invalid(HTTP)
HTTP:reply{
status = 400,
headers = {
["content-type"] = { "text/html" },
["cache-control"] = { "no-cache", "no-store" },
},
body = "<html><body><h1>Invalid API Request<h1></body></html>",
}
end
function check_ip_reputation(HTTP)
local v = HTTP:arg("ip")
if v then v = ip.addr(v) end -- convert string to ip
if not v then return reply_invalid(HTTP) end
local r = ip.reputation(v)
local body = string.format("<html><body><h1>Reputation of IP %s: %s<h1></body></html>",
v, #r > 0 and table.concat(r, ', ') or "No Found")
HTTP:reply{
status = 200,
headers = {
["content-type"] = { "text/html" },
["cache-control"] = { "no-cache", "no-store" },
},
body = body,
}
end
function check_ip_geo(HTTP)
local v = HTTP:arg("ip")
if v then v = ip.addr(v) end -- convert string to ip
if not v then return reply_invalid(HTTP) end
local geo = ip.geo(v)
local geo_code = ip.geo_code(v)
local body = string.format("<html><body><h1>GEO of IP %s: %s, code: %s<h1></body></html>",
v, geo, geo_code)
HTTP:reply{
status = 200,
headers = {
["content-type"] = { "text/html" },
["cache-control"] = { "no-cache", "no-store" },
},
body = body,
}
end
when RULE_INIT {
actions = {}
actions["reputation"] = check_ip_reputation
actions["geo"] = check_ip_geo
convert = {}
convert["testing"] = "test"
convert["debugging"] = "debug"
whitelist = {}
whitelist["test"] = true
whitelist["debug"] = true
whitelist["others"] = true
}
when HTTP_REQUEST {
local path = HTTP:path()
path = path:gsub("^/api/", "/api2/") -- convert /api/ to /api2/
local api = path:match("^/api2/(.+)") -- get api string that is after /api2/
-- check api
if api then
if actions[api] then -- if api is in table "actions", run function
return actions[api](HTTP)
end
if convert[api] then -- if api is in table "convert", convert api
api = convert[api] -- change to new api
end
if not whitelist[api] then -- if api is not in whitelist, reply invalid
return reply_invalid(HTTP)
end
HTTP:set_path("/api2/" .. api) -- pass the api to server
return
end
-- if path doesn't starts with /api or /api2, do nothing
}