请求头有问题导致Nginx返回400状态码
背景
上个星期有人找我看了Nginx的问题,场景是这样的,用户访问一个网址,这个网址有一个按钮,点击这个按钮后会跳转到新的页面,但这个跳转,有时候可以,有时候不可以——不可以的时候页面显示400状态码(开发反馈,同一个手机,不同浏览器,有的可以有的不可以;同一个手机,同一个浏览器,不同网络,有的可以,有的不可以)
问题排查
使用nginx日志排查问题
开发的手上有Nginx的access日志,通过查看返回400状态码的日志,我们发现日志显示进来的请求没有携带Host头的,而HTTP协议规定必须携带Host头,否则Nginx会直接抛出400 Bad Request。那么,问题的原因就是进来的请求没有携带Host头吗?并没有那么简单
分析抓包数据
一般来说,发出的请求不带Host是比较少见的,而且这个访问有时正常有时不正常,所以我们怀疑原因不是这个,要定位到问题原因,需要更多的数据进行分析。我们通常是在部署Nginx的Linux服务器上,使用tcpdump命令进行抓包,然后将抓到的包下载到本地的windows机器,使用wireshark工具进行分析。找到返回400状态码的Http流,查看请求头——(由于是在内网环境执行的操作,这些信息只能通过文字描述了),发现Host头是有的,并不像nginx的access日志所显示的没有Host头,那么为什么nginx没有识别到Host头呢?
原因分析
我们通过抓到的包,里面有正常请求和返回400的请求,经过比较,发现是其中一个请求头Refer不一样,并且返回400的请求的Refer在末尾携带了不可见字符(/000/000类似这样),我猜是因为这些字符,导致nginx对请求头都解析失败了,没有解析到Host头,于是就返回了400。
解决措施
联系相关的应用开发检查为什么会出现携带不可见字符的Refer并改正
总结
排查问题的时候,我们看到的原因可能不是根本原因,我们需要进一步获取原始数据、复现问题,经过对比和思考,定位根本原因并解决它
如果你对本文章有建议或疑问,欢迎在下面进行留言,一起交流
我是Vapire,一个普通的全栈开发。
以开发的角度看问题,用开发的方式学知识。
参考
鲜为人知的HTTP协议头字段详解大全 - 知乎 (zhihu.com)