我将 nginx 设置为 Web 应用程序的负载平衡,在其中一个应用程序中,我们必须过滤文档字段的最后一个字符来决定将该请求发送到哪里。因此,我决定在 nginx 位置块上设置一个标志“target”,以在值为 1 或 2 的 lua 脚本块内加载/更改它,这样我就可以在位置块内使用 IF 来 proxy_pass 到不同的上游。
location /payload-test
{
set $target '0';
access_by_lua_block {
ngx.req.read_body()
local body = ngx.req.get_body_data()
if body then
local document = string.sub(body, string.find(body, "documentNumber") + 16, string.find(body, "documentNumber")+30)
ngx.print(document)
local documentNum = string.match(document, "%d+")
ngx.print(documentNum)
local lastDigit = string.sub(documentNum, string.len(documentNum))
if math.fmod(lastDigit, 2) == 0 then
ngx.var.target = "1"
else
ngx.var.target = "2"
end
ngx.print(ngx.var.target)
end
}
return 200 $target;
}
代码本身在 lua 上运行良好,当我打印数据时,它在 Postman 上显示正确的信息。问题是,当我尝试返回 $target 的值时,nginx 仅返回初始值“0”,而不是由 lua 块设置的 1 或 2。
我在这里做错了什么?
return
指令是ngx_http_rewrite_module
的一部分,这意味着它在访问阶段之前执行(见下图),并且根据nginx文档,它“停止处理并返回指定 code
给客户端”,即
access_by_lua_block
根本没有执行,参见这个问题。 也不起作用,因为“这个处理程序总是在标准ngx_http_rewrite_module之后运行”,也就是说,使用
return
它也没有机会被执行。在
return
之前运行,但 cosocket API 在此指令的上下文中被禁用,这意味着
ngx.req.read_body()
将无法工作 (
API disabled in the context of set_by_lua* [...] in function 'read_body'
)。我会摆脱
return
并使用
content_by_lua_block
来读取请求正文并生成响应。