关于HTTP 请求头Accept-Encoding 的理解
Accept-Encoding表示Http响应是否进行压缩,一般的浏览器在访问网页时,是默认在请求头中加入
Accept-Encoding: gzip, deflate ,表示这个请求的内容希望被压缩,压缩的目的是为了减少网络流量,
但是这个只是协议,只能是要求而不是强制的,如果服务器不支持压缩或者没有开启压缩,则不能起到作用,
如果服务器也是支持压缩或者开启压缩,则会在响应头中加入Content-Encoding: gzip 头部,
起因
需要feign调用传递token,于是自定义了RequestInterceptor 进行头信息的传递,
状况
由于项目有配置开启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:
request:
enabled: true
# 配置压缩数据大小的下限
min-request-size: 8192
response:
enabled: true