OpenResty获取参数并返回

一、前言:为什么要在 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+(远高于后端应用)

九、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
Boop_wu8 小时前
[Java EE 进阶] Spring Boot 日志全面解析 : 配置与实战
junit·java-ee·单元测试
難釋懷3 天前
OpenResty快速入门
junit·openresty
FL4m3Y4n3 天前
Redis协议与异步方式
数据库·redis·junit
難釋懷4 天前
Lua语法入门-条件控制、函数
开发语言·junit·lua
難釋懷5 天前
Lua语法入门-变量和循环
开发语言·junit·lua
Java面试题总结5 天前
Junit到Springboot单元测试
spring boot·junit·单元测试
難釋懷5 天前
安装OpenResty
openresty
難釋懷6 天前
初识Lua
开发语言·junit·lua
難釋懷6 天前
Lua语法入门
junit·bootstrap·lua