[nginx]lua读取请求体

简介: [nginx]lua读取请求体

前言

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类型的请求体

location /testlua {
  client_max_body_size 10k;
  client_body_buffer_size 1k;
  content_by_lua_block {
    local ngx = require "ngx";
    ngx.req.read_body()  -- 开启读取请求体模式
    local data = ngx.req.get_body_data()  -- 获取内存中的请求体
    if data then
      ngx.print(string.format("data: %s, type: %s",data,type(data)))
      return
    else
      local file = ngx.req.get_body_file() -- 如果内存中没有, 则到临时文件中读取
      if file then
        ngx.say("body is in file ", file)
      else
        ngx.say("no body found")
      end
    end
  }
}

请求测试

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

获取table类型的请求体

location /testlua {
  client_max_body_size 10k;
  client_body_buffer_size 1k;
  content_by_lua_block {
    local ngx = require "ngx";
    ngx.req.read_body()  -- 开启读取请求体模式
    local args, err = ngx.req.get_post_args()  -- 获取内存中的请求体
    if args then
             for k,v in pairs(args) do
        if type(v) == "table" then
          ngx.say(k, ": ", table.concat(v, ", "))
        else
          ngx.say(k, ": ", v)
        end
             end
    else
      local file = ngx.req.get_body_file() -- 如果内存中没有, 则到临时文件中读取
      if file then
        ngx.say("body is in file ", file)
      else
        ngx.say("no body found")
      end
    end
  }
}

请求测试

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

参考

  • 《Nginx实战:基于lua语言的配置、开发与架构详解》
相关文章
|
8月前
|
存储 缓存 Java
Openresty(lua+nginx)-Guava-Redis做多级缓存
Openresty(lua+nginx)-Guava-Redis做多级缓存
93 1
浅谈基于openresty(nginx+lua)开发轻量级,按流量控制的灰度模块(下)
浅谈基于openresty(nginx+lua)开发轻量级,按流量控制的灰度模块
156 0
|
5月前
|
缓存 应用服务中间件 nginx
[nginx]lua控制响应头
[nginx]lua控制响应头
134 0
|
5月前
|
应用服务中间件 API nginx
[nginx]lua控制请求头
[nginx]lua控制请求头
|
消息中间件 NoSQL 关系型数据库
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
189 0
|
8月前
|
NoSQL 关系型数据库 应用服务中间件
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
Linux安装 OpenResty、Nginx、PHP、Mysql、Redis、Lua、Node、Golang、MongoDB、Kafka等
202 0
分布式接口幂等性、分布式限流(Guava 、nginx和lua限流)
接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品后支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条,这就没有保证接口的幂等性。
|
缓存 NoSQL 应用服务中间件
基于Nginx+Lua优化多级缓存架构
基于Nginx+Lua优化多级缓存架构
184 0
|
负载均衡 应用服务中间件 测试技术
浅谈基于openresty(nginx+lua)开发轻量级,按流量控制的灰度模块(上)
浅谈基于openresty(nginx+lua)开发轻量级,按流量控制的灰度模块
464 0
|
缓存 算法 前端开发
网站流量日志埋点收集—后端脚本(nginx+lua)|学习笔记
快速学习网站流量日志埋点收集—后端脚本(nginx+lua)
599 0
网站流量日志埋点收集—后端脚本(nginx+lua)|学习笔记