起因
需要feign调用传递token,于是自定义了RequestInterceptor 进行头信息的传递,
代码如下:
@Slf4j
@Component
public class GatewayFeignHeaderProcessInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate requestTemplate) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (null == requestAttributes) return;
HttpServletRequest request = requestAttributes.getRequest();
if (request == null) {
if (log.isDebugEnabled()) {
log.debug("被调环境中不存在request对象,则不往header里添加当前请求环境的header!");
}
return;
} else {
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
String values = request.getHeader(name);
requestTemplate.header(name, values);
}
}
}
this.addOtherHeaders(requestTemplate);
}
public void addOtherHeaders(RequestTemplate requestTemplate) {
// Do nothing but you have other implementation.
}
}
状况
由于项目有配置开启GZIP压缩
server:
compression:
enabled: true
在通过feign调用的时候,报如下错误:
Error while extracting response for type [class com.central.common.model.SysAdmin] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens; nested exception is com.fasterxml.jackson.core.JsonParseException: Illegal character ((CTRL-CHAR, code 31)): only regular white space (\r, \n, \t) is allowed between tokens
at [Source: (PushbackInputStream); line: 1, column: 2]
大致意思是可以看到,feign调用完在json解析的时候报错了.
分析
跟一下feign调用的源码源码
有两个实现,这里我们看feign.SynchronousMethodHandler#invoke这个方法,SynchronousMethodHandler支持远程调用
跟进executeAndDecode方法里面
这里我们直接看response里面的内容,这个时候已经远程调用远成了,看我们的请求头是有带有Accept-Encoding这个头的
Accept-Encoding:[gzip, deflate, br]
看一下这个两个头的作用,
- content-encoding:是指网页使用了哪种压缩方式传输数据给你,
- accept-encoding:表示你发送请求时告诉服务器,我可以解压这些格式的数据。
二者的关系是,对方网页会根据你发送的accept-encoding来决定用什么格式(content-encoding)传给你。
**
原因就明了,我在头信息的传递,把所有的头信息都传递了,告诉服务端我需要压缩,导致feign解析不了
**
解决办法
方法一: 只传递自己需要的,或者排除accept-encoding这个头
if(name != null && name.equalsIgnoreCase("authorization")) {
requestTemplate.header(name, values);
}
//if(name != null && !name.equalsIgnoreCase("accept-encoding")) {
// requestTemplate.header(name, values);
//}
方法二:直接改yml配置,告诉feign我们需要解压
feign:
compression:
response:
enabled: true
参考
https://cloud.tencent.com/developer/article/1588497