你的代码中 ngx.req.get_body_data()
返回 nil
的原因及解决方案如下:
问题原因
未正确配置
client_body_buffer_size
OpenResty 默认会将小请求体(<16KB)放在内存,大请求体会写入临时文件。如果请求体大小超过缓冲区但未正确配置,会导致数据无法读取。未设置
client_max_body_size
Nginx 默认限制请求体大小为 1MB,超过会直接丢弃数据。重复调用
ngx.req.read_body()
多次调用可能导致状态异常(但你的代码中没有这个问题)。请求头缺失或错误
如缺少Content-Length
或Transfer-Encoding: chunked
。
修正后的代码
-- 1. 必须优先读取body
ngx.req.read_body()
-- 2. 获取内存中的数据
local body_data = ngx.req.get_body_data()
if not body_data then
-- 3. 检查是否被写入临时文件
local tmp_file = ngx.req.get_body_file()
if tmp_file then
local f = io.open(tmp_file, "rb")
if f then
body_data = f:read("*a")
f:close()
end
end
end
-- 4. 处理数据不存在的情况
if not body_data then
ngx.log(ngx.ERR, "Failed to read request body")
return ngx.exit(400)
end
-- 5. 写入目标文件(注意用二进制模式)
local out_file = io.open("/emm/1.txt", "wb") -- 'b'模式避免编码问题
if out_file then
out_file:write(body_data)
out_file:close()
else
ngx.log(ngx.ERR, "Failed to open output file")
return ngx.exit(500)
end
return ngx.exit(200)
关键配置(nginx.conf)
http {
# 调整缓冲区大小(根据需求设置)
client_body_buffer_size 100k;
# 允许的最大请求体大小(必要!)
client_max_body_size 10m;
# 临时文件目录权限(确保OpenResty有写入权限)
client_body_temp_path /tmp/nginx_client_temp;
}
调试建议
检查请求头:
curl -v -X POST -d 'test=123' http://your_server/path
查看Nginx日志:
tail -f /usr/local/openresty/nginx/logs/error.log | grep lua
验证文件权限:
mkdir -p /emm && chown -R nobody:nobody /emm
(假设OpenResty以
nobody
用户运行)
如果仍有问题,可能是上游服务器提前关闭了连接,可以在Nginx配置中添加:
proxy_request_buffering off;
fastcgi_request_buffering off;
具体可参考零声教育《OpenResty核心编程》第6章内容。
内容由零声教学AI助手提供,问题来源于学员提问