openResty中获取请求 body

在 Nginx 的典型应用场景中,几乎都是只读取 HTTP 头即可,例如负载均衡、正反向代理等场景。但是对于 API Server 或者 Web Application ,对 body 可以说就比较敏感了。

由于 OpenResty 基于 Nginx ,所以天然的对请求 body 的读取细节与其他成熟 Web 框架有些不同。在lua代码中使用 ngx.req.read_body 函数 (或打开 lua_need_request_body 选项强制本模块读取请求体,此方法不推荐)才可以获取到请求 body。究其原因,主要是 Nginx 诞生之初主要是为了解决负载均衡情况,而这种情况,是不需要读取 body 就可以决定负载策略的。

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

body 偶尔读取不到?

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

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

如果请求体已经被存入临时文件,请使用 ngx.req.get_body_file 函数代替。

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

1、ngx.req.read_body

语法: ngx.req.read_body()
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*

开启获取请求中的body内容。

结论:

1、lua_need_request_body 开启后,该函数不执行。
2、如果在该函数前执行 ngx.req.discard_body(),该函数不执行。

2、ngx.req.discard_body

语法: ngx.req.discard_body()
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*

禁止获取请求中的body内容。

3、ngx.req.get_body_data

语法: data = ngx.req.get_body_data()
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*, log_by_lua*

获取请求body的内容,返回字符串。

注意:如果使用 ngx.req.get_post_args(),则返回一个lua table。

以下三种情况返回 nil

  1. 未使用 ngx.req.read_body 读取请求 body,或未打开lua_need_request_body
  2. 请求 body 的内容已经写入临时文件;此时使用 ngx.req.get_body_file 获取,或设置 client_body_buffer_size  client_max_body_size同等大小,来避免请求body写入临时文件。
  3. 请求体的内容为空。

4、ngx.req.get_body_file

语法: file_name = ngx.req.get_body_file()
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*

返回请求body写入的临时文件。例如:返回

/usr/local/openresty/nginx/client_body_temp/0000000019

注意以下2种情况会写入临时文件:

1、请求body的长度超过nginx.conf定义的 client_body_buffer_size 大小。
2、nginx.conf开启 client_body_in_file_only on (请求body始终写入临时文件)

5、ngx.req.set_body_data

语法: ngx.req.set_body_data(data)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*

设置请求body的内容,一般用于转发请求到子请求。

注意:

1、在使用该方法时,必需确保当前请求已经使用 ngx.req.read_body() 或者 lua_need_read_body on,否则,在使用该方法会报 500 错误。

例如:

ngx.req.read_body() --如果该行省略,将直接报错。
ngx.req.set_body_data("abc")
ngx.exec("/app/detail")

6、ngx.req.set_body_file

语法: ngx.req.set_body_file(file_name, auto_clean?)
作用域: rewrite_by_lua*, access_by_lua*, content_by_lua*

7、ngx.req.init_body

语法: ngx.req.init_body(buffer_size?)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*

8、ngx.req.append_body

语法: ngx.req.append_body(data_chunk)
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*

9、ngx.req.finish_body

语法: ngx.req.finish_body()
作用域: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*

openResty中获取请求 body》上有1条评论

  1. Pingback引用通告: openResty中ngx_lua模块提供的API | 精彩每一天

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>