错误信息
{
"msg": "Error while extracting response for type [XXX] 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\n at [Source: (PushbackInputStream); line: 1, column: 2]",
"code": "500",
"root": ""
}
问题分析
Tomcat 9.0.45
FeignClient Request
Request Header包含
accept-encoding = gzip, deflate, br
FeignServer Request
Request Header包含,但是也被分成了两个header
accept-encoding=gzip
accept-encoding=deflate
FeignClient Response
包含content-encoding:gzip
所以在JSON反序列化时会报错
原因
org.apache.coyote.CompressionConfig只考虑一个Accept-Encoding请求头。当请求包含多个这样的标头时,可能不使用压缩,具体取决于所考虑的标头是哪个。(fixed in 9.0.25)
在上述验证过程中,FeignServer接收FeignClient请求时,Accept-Encoding请求头确实被分成了两个。
相关链接
Spring Boot:
Server Side Compression not working when sending Accept-Encoding with multiple values separately · Issue #18176 · spring-projects/spring-boot · GitHub
Apache Tomcat:
63737 – Compression may not work when there are multiple Accept-Encoding headers in the request
解决方案
方案一
Spring Cloud升级至Hoxton版本
针对除OkHttpClient以外的http客户端,可以启用默认的gzip解码器,以UTF-8编码/解码gzip响应
相关配置:
feign.compression.response.enabled=true
feign.compression.response.useGzipDecoder=true
相关链接:
Adding gzip support for Spring Decoder by jskim1991 · Pull Request #230 · spring-cloud/spring-cloud-openfeign · GitHub
方案二
引入依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency> |
添加配置:
feign.okhttp.enabled=true |