使用@RequestParam导致请求头爆掉了

1,087 阅读3分钟

今天在工作中遇到了一个很简单的问题,确没有快速定位到出现这个问题的原因,还是自己对HTTP的了解的不够多,对HTTP的状态码理解的不够透彻,本篇文章将分享一下关于这个问题我的思考。

出现问题

feign.FeignException$BadRequest:status 400 reading MenuClient#getMenusByRoleIdList

定位问题

遇到这个问题,我第一时间没有读懂问题就着急去业务代码中查找问题的原因

却没有分析到出现这个问题的本质HTTP status 400代表的是客户端问题,我们定位问题一定要先分析这个是什么原因产生的,400意味着这个请求并没有发送到对应的服务端。

所以说这个地方报错和对应的服务端是一点关系都没有的。(这里我还研究了半天对应的服务端是如何处理业务的,太傻了,哎)

后来对客户端业务代码进行了分析,发现使用的是GET请求时,请求参数使用的是@RequestParam形式

这种形式不就是拼接URL吗?

我就想会不会是URL超出了长度限制,然后去查阅资料发现,真的是!!!

问题原因

HTTP协议规范中并没有对URL长度做限制,但是一些浏览器会进行限制,我这里是通过服务端作为客户端调另一个服务,不存在浏览器的,于是查询到Spring中规定HTTP请求头最大长度为server.max-http-header-size:8k,URL也是包含在请求头中的,所有URL过长会直接导致HTTP的Header变大,最终导致请求失败。

Tomcat也会对HTTP的Header也有限制,tomcat(8.0版本)允许的http请求header的最大值是8024个字节(8KB)。

Http 的GET方法对提交数据的大小和长度并没有限制,Http协议规范没有对URL长度进行限制。

解决问题

将需要携带大量参数的请求改为POST请求,同时通过@RequestBody来传送参数,也就是通过请求体传输,请求体支持传送更大的数据量。

通过HTTP状态码判断问题很重要

常见的HTTP的状态码:

  • 200 正常访问,一般和请求就没啥关系了,出问题也是最外层的服务端对http的处理不规范
  • 300 发生重定向的,服务端对页面进行了重定向
  • 400 客户端问题,出现400这个错,一般请求是到不了服务端的,服务端也不会有日志产生

    • 401 访问受保护的资源,未携带令牌,或是携带了错误的令牌,常见与不带token或cookie访问
    • 404 找不到资源,服务端找不到对应的接口
  • 500 服务端问题,这个是我们最常遇到的,一般都是后端代码报错

    • 502 代理出现问题
    • 504表示代理无法连接上行服务器