引言
之前在项目中遇到一个关于http协议header部分最大长度限制的问题,个人觉得很有意思,于是写下这篇文章记录这个问题。
http协议,超文本传输协议,HyperText Transfer Protocol,是互联网上应用最为广泛的一种网络协议,所有的WWW文件都遵守这个标准。关于http协议消息的格式,大家可以网上自行搜索,这里不再赘述。本文关注的是其header部分,如下图所示(红框标注部分):
问题原型
有一个web application提供web service,这个web application基于java开发,部署在tomcat容器上。问题是:当客户端发送一个GET请求,结果得到400的response,意思是说bad request。检查了这个request的代码实现逻辑,并没有相关input validation的逻辑,并且检查server端日志发现,request请求似乎并没有到达我们自己代码实现逻辑部分。这是为什么呢?
问题解释
遇到这个问题时,第一步就是查看server端日志,但是觉得很tricky的是,最开始并没有发现相关的日志,只是发现request并没有到达我们自己代码实现逻辑部分。后来,mina同学眼神很好,发现了如下日志:
通过日志note信息发现,该条日志在info级别下只会打印一次,之后都会是debug级别才打印,难怪之前没有注意到这条日志。
从日志信息可知,request的header部分太大,超过了tomcat允许的最大值。默认情况下,tomcat(8.0版本)允许的http请求header的最大值是8024个字节(8KB)。那为什么之前没有出现这个问题呢?原因是,项目迁移到SCP平台上之后,改成JWT token做权限校验,这个JWT token会被添加到request的header,然而JWT token一般来说都很大(平均有6k个字节左右),所以说在增加了JWT token这个header以及其他一些相关的headers之后,整个request的header部分就超过8024个字节,于是就出现了这个问题。
那么如何解决这个问题呢?可以从两个方面考虑:
扩展
在研究这个问题的过程中,其实还有一些其他疑问。首先,一个request的转发流程大致如下:
那么,在这个流程中,为什么request在前面的部分没有出现这个问题,而这个问题出现在最后一个技术栈是java/tomcat的component呢?
原因是,每个web服务器的http header最大长度的默认值不一样,同时随语言、版本不同也会不一样。举个例子tomcat 5的http header size的默认值是4K。
我找到了其他component中对于http header size的默认值的定义:
以上两个默认值都要远远大于8KB,这也就解释了没什么问题出在最后一个component。
References