前言

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语言的配置、开发与架构详解》

[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. 原来Spring能注入集合和Map的computeIfAbsent是这么好用!

    大家好,我是3y,今天继续来聊我的开源项目austin啊,但实际内容更新不多.这文章主是想吹下水,主要聊聊我在更新项目中学到的小技巧. 今天所说的小技巧可能有很多人都会,但肯定也会有跟我一样之前没用过 ...

  2. Navicat Premium 16 安装教程

    使用数据库时经常会使用到Navicat,码一个教程 转载自https://www.bilibili.com/read/cv21586676?spm_id_from=444.41.list.card_a ...

  3. 2022-03-10:限制:0 <= start <= end,0 <= target <= 64。 [start,end]范围上的数字,有多少数字二进制中1的个数等于target。 真实面试题,被问

    2022-03-10:限制:0 <= start <= end,0 <= target <= 64. [start,end]范围上的数字,有多少数字二进制中1的个数等于targ ...

  4. simplejwt配置大全

    # simplejwt配置大全SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5), # 设置token有效时间 'REFRESH_ ...

  5. Django date

    date根据给定格式对一个日期变量进行格式化. 可用的格式字符串: 格式化字符 描述 示例输出a 'a.m.'或'p.m.' 'a.m.'A 'AM'或'PM' 'AM'b 月份,文字形式,3个字母, ...

  6. JS 数组常用操作全集

    文章目录 1.push()方法 2.unshift()方法 3.pop() 方法 4.shift() 方法 5.filter() 方法 6.join()方法 7. indexOf() 方法 8.rev ...

  7. NeoVim 学习笔记

    NeoVim 学习笔记 这篇学习笔记将用于记录本人在学习使用 NeoVim 编辑器过程中所编写的学习心得与代码.该笔记将会存放在https://github.com/owlman/study_note ...

  8. iOS中容易用错的常用知识点

    坐标系转换 ios中的坐标系有三种 视图坐标系:原点(0,0)视图的左上角 窗口坐标系:原点(0,0)窗口的左上角 世界坐标系:原点(0,0)游戏中世界的原点 平时开发中经常会遇到转UIWindow坐 ...

  9. Java的运算符和表达式(基础语法学习)

    一.运算符 ​ 在Java中用于程序计算的操作符统称为运算符,运算符分为如下几类 1.算数运算符 运算符 说明 + 加号两边是数值,可以运算,如果一边存在字符串,则当作连接符 a+b - 两个数相加, ...

  10. Linux 服务器更换主板后,网卡识别失败的处理方法

    上周日,由于断电,公司所在的集群服务器在关机断电重启后,发现唯一的一个登陆节点主板出现了故障,以致于 log 登陆节点的 Red Hat Enterprise 6 系统无法启动. 由于集群是生信所有分 ...