前言

nginx默认不读取请求体的数据,但可以通过$request_body内置变量来获取。$request_body存在内存中,如果它的字节大小超过nginx配置的client_body_buffer_size的值,nginx就会把请求体存放到临时文件中。此时数据就不在内存中了,这会导致$request_body为空。

同步非阻塞方式获取请求体

ngx.req.read_body

含义:同步读取客户端请求体,且不会阻塞nginx的事件循环。使用此指令后,就可以通过ngx.req.get_body_data来获取请求体的数据了。但如果使用临时文件来存放请求体,就需要先使用函数ngx.req.get_body_file来获取临时文件名,再读取临时文件中的请求体数据。

环境:rewrite_by_lua*access_by_lua*content_by_lua*

ngx.req.get_body_data

含义:执行ngx.req.read_body指令后,可以使用本指令在内存中获取请求体数据,结果会返回一个lua的字符串类型的数据。如果要获取table类型的数据,则需要使用ngx.req.get_post_args

环境:rewrite_by_lua*access_by_lua*content_by_lua*log_by_lua*

ngx.req.get_post_args

含义:读取包含当前请求在内的所有post请求的查询参数,返回一个table类型的数据

环境:rewrite_by_lua*access_by_lua*content_by_lua*log_by_lua*header_filter_by_lua*body_filter_by_lua*

ngx.req.get_body_file

含义:获取存放请求体的临时文件名。如果请求体被存放在内存中,获取的值就是nil。

示例

获取string类型的请求体

  1. location /testlua {
  2. client_max_body_size 10k;
  3. client_body_buffer_size 1k;
  4. content_by_lua_block {
  5. local ngx = require "ngx";
  6. ngx.req.read_body() -- 开启读取请求体模式
  7. local data = ngx.req.get_body_data() -- 获取内存中的请求体
  8. if data then
  9. ngx.print(string.format("data: %s, type: %s",data,type(data)))
  10. return
  11. else
  12. local file = ngx.req.get_body_file() -- 如果内存中没有, 则到临时文件中读取
  13. if file then
  14. ngx.say("body is in file ", file)
  15. else
  16. ngx.say("no body found")
  17. end
  18. end
  19. }
  20. }

请求测试

  1. curl -i http://192.168.1.111/testlua -d 'test=123&a=qwe&b=zxc'
  2. HTTP/1.1 200 OK
  3. Server: openresty
  4. Date: Sun, 28 May 2023 10:05:51 GMT
  5. Content-Type: application/octet-stream
  6. Transfer-Encoding: chunked
  7. Connection: keep-alive
  8. data: test=123&a=qwe&b=zxc, type: string

获取table类型的请求体

  1. location /testlua {
  2. client_max_body_size 10k;
  3. client_body_buffer_size 1k;
  4. content_by_lua_block {
  5. local ngx = require "ngx";
  6. ngx.req.read_body() -- 开启读取请求体模式
  7. local args, err = ngx.req.get_post_args() -- 获取内存中的请求体
  8. if args then
  9. for k,v in pairs(args) do
  10. if type(v) == "table" then
  11. ngx.say(k, ": ", table.concat(v, ", "))
  12. else
  13. ngx.say(k, ": ", v)
  14. end
  15. end
  16. else
  17. local file = ngx.req.get_body_file() -- 如果内存中没有, 则到临时文件中读取
  18. if file then
  19. ngx.say("body is in file ", file)
  20. else
  21. ngx.say("no body found")
  22. end
  23. end
  24. }
  25. }

请求测试

  1. curl -i http://192.168.1.111/testlua -d 'test=123&a=qwe&b=zxc'
  2. HTTP/1.1 200 OK
  3. Server: openresty
  4. Date: Sun, 28 May 2023 10:37:48 GMT
  5. Content-Type: application/octet-stream
  6. Transfer-Encoding: chunked
  7. Connection: keep-alive
  8. a: qwe
  9. b: zxc
  10. test: 123

参考

  • 《Nginx实战:基于lua语言的配置、开发与架构详解》

[nginx]lua读取请求体的更多相关文章

  1. nginx读取请求体

    请求体的读取一般发生在nginx的content handler中,一些nginx内置的模块,比如proxy模块,fastcgi模块,uwsgi模块等,这些模块的行为必须将客户端过来的请求体(如果有的 ...

  2. nginx请求体读取

    上节说到nginx核心本身不会主动读取请求体,这个工作是交给请求处理阶段的模块来做,但是nginx核心提供了ngx_http_read_client_request_body()接口来读取请求体,另外 ...

  3. 【精选】Nginx模块Lua-Nginx-Module学习笔记(一)Nginx Lua API 接口详解

    源码地址:https://github.com/Tinywan/Lua-Nginx-Redis 一.介绍 各种* _by_lua,* _by_lua_block和* _by_lua_file配置指令用 ...

  4. post请求体过大导致ngx.req.get_post_args()取不到参数体的问题

    http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_buffer_size 该地址对于client_body_buf ...

  5. Nginx模块Lua-Nginx-Module学习笔记(一)Nginx Lua API 接口详解

    源码地址:https://github.com/Tinywan/Lua-Nginx-Redis 一.介绍 各种* _by_lua,* _by_lua_block和* _by_lua_file配置指令用 ...

  6. openresty(nginx+lua)初识

    1.新增项目配置文件: vim /usr/example/example1.conf --将以下内容加入example1.conf server { listen 80; server_name _; ...

  7. http 请求体数据--ngx

    HTTP包体的长度有可能非常大,不同业务可能对包体读取 处理不相同, 比如waf, 也许会读取body内容或者只是读取很少的前几十字节.所以根据不同业务特性,对http body 数据包处理方式不同, ...

  8. 从Excel获取请求体

    Excel文件 .py文件---------------------- import xlrdimport re def fetch_body(path,sheet,name,adict):     ...

  9. Spring Cloud Gateway 之获取请求体(Request Body)的几种方式

    Spring Cloud Gateway 获取请求体 一.直接在全局拦截器中获取,伪代码如下 private String resolveBodyFromRequest(ServerHttpReque ...

  10. Asp.Net Core上传大文件请求体限制设置

    IIS进程内部署时 1. Web.Config的<system.webServer>节点下增加 <security> <requestFiltering> < ...

随机推荐

  1. 关于 Bash 脚本中 Shebang 的趣事

    哈喽大家好,我是咸鱼 不知道小伙伴们在写 Bash 脚本或者说看别人的 Bash 脚本的时候有没有注意过脚本的第一行 #!/bin/bash Bash 脚本的第一行往往以 #! 开头,这一行称作 sh ...

  2. PostgreSQL-HA 高可用集群在 Rainbond 上的部署方案

    PostgreSQL 是一种流行的开源关系型数据库管理系统.它提供了标准的SQL语言接口用于操作数据库. repmgr 是一个用于 PostgreSQL 数据库复制管理的开源工具.它提供了自动化的复制 ...

  3. ReactHub:我用 ChatGPT 搞了一个 React 的资源导航网站,谁有我用心啊!

    大家好,我是DOM哥. 图谱年年有,今年我来盘! 之前已经盘完了 Vue 的技术图谱,今天来盘 React 的. 我用 ChatGPT 开发了一个 React 的资源导航网站. 不管你是资深 Reac ...

  4. 微信小程序客服、支付、定位、下拉加载功能

    一.客服功能 1.只要你微信小程序,后台添加了客服,引用以下button,就可以进入聊天(在小程序官网如何添加客服用户,请自行百度,谢谢) 2.通过按钮方式 <button open-type= ...

  5. 2022-07-24:以下go语言代码输出什么?A:[]int{};B:[]int(nil);C:panic;D:编译错误。 package main import ( “fmt“ ) f

    2022-07-24:以下go语言代码输出什么?A:[]int{}:B:[]int(nil):C:panic:D:编译错误. package main import ( "fmt" ...

  6. 2020-12-05:go中,map的扩容流程是什么?

    福哥答案2020-12-05:[答案来自此链接:](https://www.bilibili.com/video/BV1Nr4y1w7aa?p=13) 源码位于runtime/map.go文件中的ha ...

  7. 2021-11-13:至少有 K 个重复字符的最长子串。给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k 。返回这一子串的长度。提示:1

    2021-11-13:至少有 K 个重复字符的最长子串.给你一个字符串 s 和一个整数 k ,请你找出 s 中的最长子串, 要求该子串中的每一字符出现次数都不少于 k .返回这一子串的长度.提示:1 ...

  8. @GrpcServise 注解的作用和使用

    转载请注明出处: 1. @GrpcServise 的作用和优势 在没有使用 @GrpcServise 注解编写服务端时,我们通常需要自定义 Server 以及端口,包括 start,stop ,注册s ...

  9. flex弹性布局模式下文字超出显示省略号

    都知道flex弹性布局非常好用,会随分辨率不同,宽高自适,那怎么来设置在一定范围内的文字超出隐藏,显示省略号呢?其实也不难 看如下就是使用flex布局的 其实如上效果也同样离不开如下三句,只是用法不大 ...

  10. 系统MySQL服务无法启动报错1067的四种解决方法win7系统MySQL服务无法启动报错1067的四种解决方法

        有些win7系统用户在登陆mysql或者重装mysql时出现"无法启动MYSQL服务,错误1067",而且重启.修复注册表都没办法解决问题.那么遇到MySQL服务无法启动问 ...