nginx代理转发因http_version导致lua读取文件不存在问题
本文由希希大队长原创,原文链接:https://www.cnblogs.com/dongxixi/p/16267036.html
需求:
有一个POST接口,我希望在nginx上解析body体参数并直接返回一个对应的json文本文件
实现:
因需求比较复杂,我选择用lua脚本实现body体解析并读取对应文件返回
nginx实现如下:
location /v1/list-panoramas {
access_by_lua_file /mnt/lua/list_pano.lua;
}
lua实现如下:
ngx.req.read_body();
local data = ngx.req.get_body_data();
local reqObj = ngx.req.get_post_args();
local storeId = reqObj["store_id"]
-- 如果Content-Type是表单类型,则storeId有值
if storeId == nil then
-- storeId无值表明Content-Type可能是application/json,需要从body体反序列化
jsonData = json.decode(nil, data)
storeId = jsonData["store_id"]
end
-- 从静态文件目录读取, /mnt/static_file为nginx服务挂载的静态目录
local filePath = string.format("/mnt/static_file/%s", storeId)
local fh, err = io.open(filePath, "r")
if fh == nil then
ngx.exit(404)
else
fileData = fh:read()
io.close()
ngx.header['Content-Type'] = 'application/json; charset=utf-8'
ngx.say(fileData)
end
问题描述:
当使用postman直接访问该nginx时,可以获取到对应json文件内容
但因为需求需要,我需要从其他nginx代理转发到该nginx,为方便理解,我们姑且命名该nginx为ng-A,代理转发nginx为ng-B
ng-B的代理location如下:
location /v1/list-panoramas {
proxy_pass http://172.16.15.44;
}
当我向ng-B发起请求时(参数均为变,仅仅替换了请求host),却意外得到了nginx返回的404结果
此时我检查ng-A的error.log,发现请求已经到达ng-A,错误发生在lua脚本open文件时
2022/05/13 06:19:01 [error] 18#18: *2 open() "/etc/nginx/html/v1/list-panoramas" failed (2: No such file or directory), client: 10.100.39.1, server: 172.16.15.44, request: "POST /v1/list-panoramas HTTP/1.0", host: "172.16.15.44"
可以看出,这里open的是 ‘/etc/nginx/html/v1/list-panoramas’
显然与我上述lua脚本中需要打开的路径不一致
lua中
local filePath = string.format("/mnt/static_file/%s", storeId)
这使我百思不得其解
问题排查与解决:
在一顿尝试仍未解决以后,我在ng-A的日志中发现,我直接请求ng-A成功得到预期结果时,log中打印的请求http version为HTTP/1.1,
但在我通过ng-B请求代理到ng-A时,ng-A打印的请求http version为HTTP/1.0,我隐隐感觉问题可能出在转发时http version上,当
我在ng-B上加上 proxy_http_version 1.1; 后,再请求ng-B,顺利拿到预期结果
location /v1/list-panoramas {
proxy_pass http://172.16.15.44;
proxy_http_version 1.1;
}
思考:
1、为什么在ng代理转发后http version变成了1.0呢?
在查阅相关资料后得知,代理转发过程中,http version nginx会有一个默认值,默认1.0
2、为什么在http version为1.0时,lua在打开文件时与预期不一致呢?
这个问题暂时没有得到答案,欢迎大佬留言
本篇完结!