OpenFeign引起的HTTP Status 400与Tomcat吞没数据()

  本篇文章为你整理了OpenFeign引起的HTTP Status 400与Tomcat吞没数据()的详细内容,包含有 OpenFeign引起的HTTP Status 400与Tomcat吞没数据,希望能帮助你了解 OpenFeign引起的HTTP Status 400与Tomcat吞没数据。

  OpenFeign拦截器

    在微服务中比较常见的场景:前端带了JWT令牌请求服务A,在服务A中使用Feign远程调用服务B、服务C等,A、B、C都接入了Spring Security;此时就会存在这样的需求,如服务A调用服务B、C时不带有JWT令牌就会出现服务调用失败,无法通过服务B、C鉴权认证;
 

    此时需要通过Feign提供的RequestInterceptor拦截器将A请求头中所持有的Token在Feign发起远程调用时继续传递给服务B、服务C;
 

  Demo示例代码:

  

public class DemoRequestInterceptor implements RequestInterceptor {

 

  private final BearerTokenResolver tokenResolver;

  @Override

  public void apply(RequestTemplate template) {

   ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

   HttpServletRequest request= attributes.getRequest();

   //获取当前请求header

   Enumeration String headerNames = request.getHeaderNames();

   if (headerNames != null) {

   while (headerNames.hasMoreElements()) {

   String name = headerNames.nextElement();

   String values = request.getHeader(name);

   //将header沿Feign调用链传递

   template.header(name, values);

  

 

  导致的问题

    这种简单粗暴全部将Header向下传递的方法将出现意想不到的副作用,导致程序请求调用失败;
 

    上面Demo代码,如发生如上图所示的服务调用,将产生服务调用失败,HTTP 400异常;
 

    以下分析环境为Spring Boot2.7,使用内置tomcat 9.0.65;

    1、客户端Put请求,content-length等于74
 

    2、全部拷贝UpdateA请求所携带的Header头,服务A发起feign调用服务B,Get请求;
 

    3、服务A发起feign调用服务C,Put请求;
 

    服务A调用服务B成功完成请求,在服务A继续发起的feign调用服务C出现如下异常,Tomcat无法解析该请求,抛出异常,此时请求头已经被破坏:

  

java.lang.IllegalArgumentException: Invalid character found in method name [late, ]. HTTP method names must be tokens

 

  at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:421)

  

 

    从异常中明显可以看出Tomcat在解析请求行时出现异常,但具体什么原因引起的还将要debug Tomcat源码才能发现问题所在;

    在Tomcat中从抛出异常的类处添加日志输出,跟踪问题;
 

    1、在Http11InputBuffer类的parseRequestLine方法中添加打印日志:
 

  可看到两个请求的请求头信息:

    服务A对服务B发起的Get请求信息,如上所述,Header头全部带上了:

  

2022-09-10 15:50:21.642 DEBUG 12028 --- [nio-8085-exec-5] 

 

  o.a.coyote.http11.Http11InputBuffer

  :2:parsingRequestLinePhase--Received [GET /infos?

  pageSize=10 pageNo=1 HTTP/1.1

  accept: */*

  accept-encoding: gzip, deflate, br

  authorization: Bearer admin11::ab5050d3-3542-4ada-80e9-

  6241132de5e5

  cache-control: no-cache

  connection: keep-alive

  content-length: 74

  content-type: application/json

  cookie: JSESSIONID=3A1FD18830F43E295F07E8F77C0FA9FF

  host: 127.0.0.1:7730

  postman-token: fe8cfff4-e10b-4286-98da-d6d7bc05c006

  user-agent: PostmanRuntime/7.29.2

  

 

    服务A对服务C发起的Put请求信息,但请求头并不完整;请求行已不见,请求头也只剩部分,请求体完整,这也是为什么抛出请求行解析失败的原因;

  

2022-09-10 15:50:39.126 DEBUG 12028 --- [nio-8085-exec-5] o.a.coyote.http11.Http11InputBuffer 

 

  :2:parsingRequestLinePhase--Received [late, br

  authorization: Bearer admin11::ab5050d3-3542-4ada-80e9-

  6241132de5e5

  cache-control: no-cache

  connection: keep-alive

  cookie: JSESSIONID=3A1FD18830F43E295F07E8F77C0FA9FF

  host: 127.0.0.1:7730

  postman-token: fe8cfff4-e10b-4286-98da-d6d7bc05c006

  user-agent: PostmanRuntime/7.29.2

  Content-Type: application/json

  Content-Length: 34

  {"aaabbbbId":123,"varray":["123"]}]

  

 

    第一个Get请求,虽然附加了content-length: 74,但并不影响请求;第二个Put请求,请求头直接被破坏;通过private boolean fill(boolean block)方法的日志发现,Put请求接收时HTTP请求头还是完整的;
 

    在Parameters类的processParameters方法中并没有对Get请求读取Content-Length长度的数据,目前只能从Get请求完成之后、Put头解析之前的代码进行跟踪分析,还是在Http11InputBuffer类中,在每个请求结束之后都会执行如下方法:

  

/**

 

  * 结束请求,消耗剩余字节

  void endRequest() throws IOException {

   //吞没机制是否开启

   if (swallowInput (lastActiveFilter != -1)) {

   int extraBytes = (int) activeFilters[lastActiveFilter].end();

   byteBuffer.position(byteBuffer.position() - extraBytes);

  

 

    此方法将会根据吞没机制配置与remaining字节数对byteBuffer数据进行吞没;
 

  
 

    根据吞没配置与上个请求完成后所剩余的字节数remaining,对数据byteBuffer数据进行吞没;
 

    在此可看到吞没掉的字节数为74,为第一个请求头所携带的contentLength数据,第二个Put请求头所丢失的数据;
 

    如Feign调用为Get、Put、Put请求;Get、Get、Get请求将不会有异常情况出现,上述异常情况为:Put、Get、Put请求;之所以remaining会剩余74是因为Tomcat并不会对Get请求从byteBuffer读取Content-Length所传输的字节数据;当请求没有导致吞没机制发生时就不会出现异常情况;

  文章首发地址:https://mp.weixin.qq.com/s/COfUWUshQge-i2UOST8QUw

  以上就是OpenFeign引起的HTTP Status 400与Tomcat吞没数据()的详细内容,想要了解更多 OpenFeign引起的HTTP Status 400与Tomcat吞没数据的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: