一、前言:为什么要在 OpenResty 中"获取参数并返回"?
你是否遇到过这些需求?
- ✅ 快速搭建一个 mock 接口
- ✅ 在网关层直接返回配置信息(无需后端)
- ✅ 实现轻量级健康检查或探针接口
- ✅ 调试时打印当前请求参数
OpenResty 允许你在 Nginx 层直接读取请求参数,并生成响应返回给客户端------无需转发到后端服务!
这种能力非常适合轻量级 API、调试接口、动态配置下发等场景。
本文将通过 4 个典型示例 ,手把手教你如何在 OpenResty 中安全获取参数并返回结构化响应。
二、基础准备:设置响应格式
无论返回什么内容,都要先设置正确的 Content-Type:
Lua
location /echo {
default_type 'application/json'; # 关键!声明返回 JSON
content_by_lua_block {
-- Lua 逻辑
}
}
⚠️ 不设
default_type默认是text/plain,前端可能无法正确解析 JSON!
三、实战 1:回显 GET 参数(最简单)
需求
请求:GET /echo?name=Alice&age=25
返回:
Lua
{"name":"Alice","age":"25"}
配置
Lua
location /echo {
default_type 'application/json';
content_by_lua_block {
local cjson = require "cjson.safe"
local args = ngx.req.get_uri_args()
ngx.say(cjson.encode(args))
}
}
✅ 特点:自动处理 URL 解码、多值参数。
四、实战 2:回显 POST 表单数据
需求
请求头:Content-Type: application/x-www-form-urlencoded
Body:username=admin&role=guest
返回:
Lua
{"username":"admin","role":"guest"}
配置
Lua
location /echo-post {
default_type 'application/json';
content_by_lua_block {
-- 必须先读取 body!
ngx.req.read_body()
local cjson = require "cjson.safe"
local post_args = ngx.req.get_post_args() or {}
ngx.say(cjson.encode(post_args))
}
}
⚠️ 关键步骤 :
ngx.req.read_body()缺一不可!
五、实战 3:回显 JSON 请求体(现代 API 常见)
需求
请求头:Content-Type: application/json
Body:
Lua
{"userId":1001,"action":"login"}
返回原样 JSON(或加工后返回)。
配置
Lua
location /echo-json {
default_type 'application/json';
content_by_lua_block {
ngx.req.read_body()
local body = ngx.req.get_body_data()
if not body or body == "" then
ngx.status = 400
ngx.say('{"error":"empty body"}')
return
end
local cjson = require "cjson.safe"
local data, err = cjson.decode(body)
if not data then
ngx.status = 400
ngx.say('{"error":"invalid json"}')
return
end
-- 可在此加工数据,例如添加字段
data.timestamp = ngx.now()
data.echoed_by = "openresty"
ngx.say(cjson.encode(data))
}
}
✅ 优势 :可在网关层注入公共字段(如 trace_id、timestamp)。
六、实战 4:统一参数获取 + 动态响应(高级)
需求
- 支持 GET/POST/JSON
- 返回标准化响应结构
- 包含请求方法、路径、参数
配置
Lua
location /inspect {
default_type 'application/json';
content_by_lua_block {
local method = ngx.req.get_method()
local uri = ngx.var.uri
local params = {}
if method ~= "GET" then
ngx.req.read_body()
local headers = ngx.req.get_headers()
local ct = headers["content-type"] or ""
if ct:find("application/json", 1, true) then
local body = ngx.req.get_body_data()
if body then
local cjson = require "cjson.safe"
params = cjson.decode(body) or {}
end
else
params = ngx.req.get_post_args() or {}
end
else
params = ngx.req.get_uri_args()
end
local response = {
method = method,
uri = uri,
client_ip = ngx.var.remote_addr,
params = params
}
local cjson = require "cjson.safe"
ngx.say(cjson.encode(response))
}
}
测试示例
Lua
# GET
curl "http://localhost/inspect?test=1"
# POST 表单
curl -d "user=bob&action=click" http://localhost/inspect
# POST JSON
curl -H "Content-Type: application/json" \
-d '{"event":"page_view"}' \
http://localhost/inspect
🔍 输出统一结构,便于调试和监控!
七、错误处理与安全建议
7.1 设置状态码
Lua
ngx.status = 400 -- 在 ngx.say 前设置
ngx.say('{"error":"bad request"}')
7.2 限制 body 大小(防攻击)
在 nginx.conf 中配置:
Lua
client_max_body_size 1m; # 默认 1MB,防止 OOM
7.3 避免敏感信息泄露
- 不要直接返回原始参数(如密码)
- 生产环境关闭
/inspect类调试接口
八、性能提示
- ✅ 所有操作在 单个
content_by_lua_block中完成,无网络开销 - ✅ 使用
cjson.safe避免崩溃 - ✅ 小接口 QPS 可达 10w+(远高于后端应用)
九、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!