获取请求 body

    我们先来构造最简单的一个请求,POST 一个名字给服务端,服务端应答一个 “Hello ****”。

    测试结果:

    1. hello nil

    大家可以看到 data 部分获取为空,如果你熟悉其他 Web 开发框架,估计立刻就觉得 OpenResty 弱爆了。查阅一下官方 wiki 我们很快知道,原来我们还需要添加指令 lua_need_request_body

    究其原因,在于 Nginx 诞生之初主要是为了解决负载均衡问题,而这种情况,是不需要读取 body 就可以决定负载策略的,所以这个点对于 API Server 和 Web Application 开发的同学来说有点怪。

    再次测试,符合我们预期:

    1. ~ curl 127.0.0.1/test -d jack
    2. hello jack

    如果你只是某个接口需要读取 body(并非全局行为),那么这时候也可以显式调用 ngx.req.read_body() 接口,参看下面示例:

    body 偶尔读取不到?

    ngx.req.get_body_data() 读请求体,会偶尔出现读取不到直接返回 nil 的情况。

    • 如果请求体 尚未被读取,请先调用 ngx.req.read_body (或打开 选项强制本模块读取请求体,此方法不推荐)。

    • 如需要 强制在内存中保存请求体,请设置 client_body_buffer_size 和 为 同样大小

    参考下面代码:

    1. http {
    2. server {
    3. listen 80;
    4. # 强制请求 body 到临时文件中(仅仅为了演示)
    5. location /test {
    6. content_by_lua_block {
    7. function getFile(file_name)
    8. local f = assert(io.open(file_name, 'r'))
    9. local string = f:read("*all")
    10. f:close()
    11. return string
    12. end
    13. local data = ngx.req.get_body_data()
    14. local file_name = ngx.req.get_body_file()
    15. ngx.say(">> temp file: ", file_name)
    16. if file_name then
    17. data = getFile(file_name)
    18. end
    19. end
    20. ngx.say("hello ", data)
    21. }
    22. }
    23. }

    测试结果:

    由于 Nginx 是为了应对负载均衡场景诞生的,所以它默认不读取 body 的行为,会对 API Server 和 Web Application 场景造成一些影响。 根据需要 正确读取、丢弃 body 对 OpenResty 开发是 至关重要 的。