小程序上传文件nginx返回404原因排查

小程序上传文件nginx返回404原因排查

现象描述

微信小程序上传图片功能,服务端时ngnix代理到netty后端。开发工具使用iphone模拟器上传文件正常。但是iPhone手机测试返回404.
android手机测试OK。

故障排查

404状态码表示地址不存在。

PC开发工具和android手机测试正常,iPhone手机返回404,地址是找的到的。

打开nginx访问日志

1
2
x.x.x.x - - [18/Mar/2022:04:11:49 +0000] "POST /upload HTTP/2.0" 404 154 "https://servicewechat.com/wx0000000/0/page-frame.html" "Mozilla/5.0 (iPhone; CPU iPhone OS 15_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/8.0.16(0x18001023) NetType/4G Language/zh_CN" "-"
x.x.x.x - - [18/Apr/2022:10:04:44 +0000] "POST /upload HTTP/1.1" 200 103 "https://servicewechat.com/wx0000000/0/page-frame.html" "Mozilla/5.0 (Linux; Android 11; KB2000 Build/RP1A.201005.001; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/86.0.4240.99 XWEB/4207 MMWEBSDK/20220303 Mobile Safari/537.36 MMWEBID/4095 MicroMessenger/8.0.21.2120(0x28001553) Process/appbrand1 WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android" "-"

这里显示iPhone用的时HTTP/2.0协议,难道是后端netty不支持HTTP/2.0协议导致的?

netty 是其他人负责的,不能修改。那就在nginx中删除对HTTP/2.0的支持。测试后iPhone设备测试仍返回404.

迷茫中…

过了一天,另一台android设备测试也返回404,这就不单单是iPhone的问题了。

1
x.x.x.x - - [24/Mar/2022:06:49:24 +0000] "POST /upload HTTP/1.1" 404 556 "https://servicewechat.com/wx0000000/0/page-frame.html" "Mozilla/5.0 (Linux; Android 9; ARS-AL00 Build/HUAWEIARS-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/86.0.4240.99 XWEB/3195 MMWEBSDK/20220204 Mobile Safari/537.36 MMWEBID/8978 MicroMessenger/8.0.20.2100(0x28001451) Process/appbrand0 WeChat/arm64 Weixin NetType/WIFI Language/zh_CN ABI/arm64 MiniProgramEnv/android" "-"

这台nginx是用docker容器运行的,没有配置error.log.
配置error.log, 再次测试后查看error.log.

1
2
3
2022/03/24 07:14:37 [error] 12#12: *6 open() "/usr/share/nginx/html/50x.html" failed (2: No such file or directory), cli
ent: x.x.x.x, server: gw.xxx.com, request: "POST /upload HTTP/2.0", upstream: "http://172.17.0.1:8088/upload"
, host: "gw.xxx.com"

这里显示nginx找不到50x.html文件。

看来是upload请求时netty返回50x状态码,这时nginx查找50x.html返回给客户端,但是nginx没有配置50x.html为文件,然后nginx转而返回404状态码给客户端,导致真正的50x状态码丢失。

真相

Netty默认配置对上传文件有64k的限制。所以测试时如果上传的图片小于64k,则流程一切正常。当上传图片大于64k时,netty出错,返回50x错误(这里没有确认核对具体返回码)。如果正确的配置了nginx,那么这时nginx就会返回netty返回的状态码,页面内容为50x.html的内容。
但是这台运行在docker中的nginx配置不够完整,没有配置error.log和50x.html界面,结果倒置nginx无法找到50x.html文件,导致返回404错误码,掩盖了真正错误的原因。