Feign GET 请求400 (一下正常200,一下异常400)

背景: 公司多个服务间sdk调用, 需要传递token等header信息鉴权, feign在调用其他服务时, 使用GET请求发现一下正常(200), 一下异常(400), 当时觉得很诡异, 其他组调用都没问题, 找了半天, 在此记录下:

异常的请求路径打印出来发现没有任何问题, 其他博客所说的 header信息过长, get参数过长, 参数接收注解等等都没问题(因为存在正常调用的时候, 不是全部异常)

打印异常如下:

feign.FeignException$BadRequest: [400 ] during [GET] to [http://服务调用的完整路径] [Feign调用的方法(String)]: [<!doctype html><html lang="en"><head><title>HTTP Status 400 – Bad Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;... (435 bytes)]
  at feign.FeignException.clientErrorStatus(FeignException.java:195) ~[feign-core-10.10.1.jar:na]
  at feign.FeignException.errorStatus(FeignException.java:177) ~[feign-core-10.10.1.jar:na]
  at feign.FeignException.errorStatus(FeignException.java:169) ~[feign-core-10.10.1.jar:na]

排查过程: 

  1. 检查请求参数是否存在特殊字符, 是否存在转义问题(无)
  2. 检查目标服务参数接收注解是否正常 (废话, 别人用的好好的, 况且又不是全部异常)
  3. 检查springboot版本号 (一度怀疑是框架bug, 更换版本号没有解决)
  4. 检查是否所有请求都存在问题 (发现只是被调用方的GET请求有问题, POST正常, 所以临时拜托小伙伴替换成POST方法, 不可能全部替换, 接着找...)
  5. 检查请求信息 (200 和 400 的请求信息完全一样, 这个目前还是没有找到具体问题...但是不影响)
  6. 尝试不同的请求调用链, 即
    1. A服务的Get请求 -> feign -> B服务的Get     (完全正常)
    2. A服务的Get请求 -> feign -> B服务的Post    (完全正常)
    3. A服务的Post请求 -> feign -> B服务的Get    (问题复现)
    4. A服务的Post请求 -> feign -> B服务的Post   (完全正常)

突然想到前边提到, header信息传递时, 定义了一个feign拦截器:

@Configuration
public class FeignConfiguration implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String values = request.getHeader(name);
                requestTemplate.header(name, values);
            }
        }
    }
}

将A服务的header信息全部传递至B服务, 那么A服务的POST请求的header信息会携带至B服务的GET请求上, 当POST请求存在body请求体时, header会带上

content-type:application/json

此时, 底层okhttp解析该请求时, 就会存在异常!

问题找到了,解决就简单了, feign拦截器里只过滤自己需要的header信息即可, 不要全部传递!!!!!!!

@Configuration
@Slf4j
public class FeignConfiguration implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String values = request.getHeader(name);
                if (checkEssential(name)) {
                    requestTemplate.header(name, values);
                }
            }
        }
    }

    /**
     * 请求头必要传递参数过滤,只携带必要请求头信息
     *
     * @param name
     * @return
     */
    private boolean checkEssential(String name) {
        ArrayList<String> headers = Lists.newArrayList("productId", "topGroupId", "customId", "userId", "lesseeId");
        return headers.stream().anyMatch(e -> e.equalsIgnoreCase(name));
    }
}

  • 17
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值