直接在Nginx的content阶段用content_by_lua_file或content_by_lua_block执行Lua,通过ngx.say()输出JSON,需正确获取参数、设置响应头并避免阻塞静态服务。

直接用 content_by_lua_file 或 content_by_lua_block 指令,在 Nginx 的 content 阶段执行 Lua 代码,调用 ngx.say() 输出 JSON 字符串即可。关键是要让 Lua 正确拿到参数、设好响应头,并避免阻塞原生文件服务逻辑。
配置 nginx.conf 启用 Lua 并绑定 location
在 http 块中声明 Lua 路径,并为 API 接口定义专用 location:
- 确保已安装 OpenResty 或编译了
ngx_http_lua_module - 在
http块添加:lua_package_path "/usr/local/openresty/lualib/?.lua;/path/to/your/lua/?.lua;;";lua_package_cpath "/usr/local/openresty/lualib/?.so;;"; - 为接口路径(如
/api/item/123)配置正则 location,捕获 ID:location ~ ^/api/item/(?\d+)$ { default_type application/json;content_by_lua_file /path/to/lua/item.lua;}
编写 item.lua 提取参数并输出 JSON
脚本需读取捕获的 ID、校验合法性、拼接或构造 JSON 响应:
- 用
ngx.var.id获取正则捕获值(前提是 location 用了命名捕获(?)\d+) - 检查是否为空或非法:
if not ngx.var.id or tonumber(ngx.var.id) == nil then ... ngx.exit(400) end - 用单引号包裹 JSON 字符串,避免双引号转义问题:
ngx.say('{"id":' .. ngx.var.id .. ',"name":"Product A","ts":' .. ngx.time() .. '}') - 如需更规范的 JSON 序列化,提前安装
lua-cjson,再local cjson = require "cjson",最后ngx.say(cjson.encode(data))
注意 content 阶段的边界与限制
这个阶段完全接管响应生成,不适用于静态资源服务,但非常适合纯 API 场景:
-
content_by_lua_*会绕过 Nginx 原生的alias、try_files和sendfile,所以只用于动态内容,不要混用于图片、JS 等静态文件 - 若需在返回 JSON 前做鉴权,应在
access_by_lua_*阶段完成,失败直接ngx.exit(403),避免进入 content 阶段 - 避免在脚本中做耗时操作(如同步 HTTP 请求、文件读写),否则会阻塞 worker;必须调用远程服务时,优先使用
lua-resty-http异步方式
调试与错误处理建议
初期容易因语法、路径或变量为空导致 500 错误,建议主动加日志和兜底:
- 在 Lua 脚本开头加
ngx.log(ngx.INFO, "item.lua running, id=", ngx.var.id or "nil") - 所有
ngx.say()前设置状态码:ngx.status = 200;出错时显式设ngx.status = 400并输出结构化错误 JSON - Nginx 错误日志(
error_log logs/error.log notice;)是主要排查依据,注意开启notice或更高级别











