在 Spring Boot REST 应用程序中处理 gzipped 请求

Posted

技术标签:

【中文标题】在 Spring Boot REST 应用程序中处理 gzipped 请求【英文标题】:Handling gzipped requests in a Spring Boot REST application 【发布时间】:2018-02-28 04:39:05 【问题描述】:

我有一个 Spring Boot REST 应用程序 (1.5.6.RELEASE)。我想要 gzip 压缩传入和传出。根据这个文档https://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html我已经设置了

server.compression.enabled=true
server.compression.mime-types=...

但这似乎只适用于来自我的服务的 gzipping 响应(这就是文档实际上所说的“# If response compression is enabled.”)。

我的问题是传入的 gzipped 请求没有被解压缩,导致 JSON 解析错误。

有人知道如何在我的 Spring Boot 应用中开启请求解压功能吗?

编辑一个例子:

POM sn-p:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.6.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

控制器代码:

@RestController
public class Controller 
    @RequestMapping(value = "/", method = RequestMethod.POST, consumes = "application/json")
    public String post(@RequestBody Map<String, String> request) 
        return request.get("key");
   

使用 curl 测试:

$ echo ' "key":"hello" ' > body
$ curl -X POST -H "Content-Type: application/json" --data-binary @body http://localhost:8080 # prints 'hello'
$ echo ' "key":"hello" ' | gzip > body.gz
$ curl -X POST -H "Content-Type: application/json" -H "Content-Encoding: gzip" --data-binary @body.gz http://localhost:8080 # fails

gzipped 调用失败并显示消息:

"timestamp":1505843443456,"status":400,"error":"Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"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: java.io.PushbackInputStream@50ebec25; line: 1, column: 2]","path":"/"

【问题讨论】:

如何发出压缩请求? 见***.com/q/20507007/46673、***.com/q/16638345/466738、serverfault.com/questions/56700/… @diginoise 我无法控制客户端 给我们看一些代码!你的控制器是什么样的?客户端发送的是什么(HTTP 标头和正文),您遇到了什么错误,等等 @Brian Clozel,完成 【参考方案1】:

server.compression.* 配置键仅用于 HTTP 响应压缩。我不知道任何通用解决方案,也不知道服务器是否原生支持。

您可以通过使用 Servlet 过滤器来支持这一点,但 Spring Boot 不提供该功能。

【讨论】:

或者你把你的servlet容器放在Apache后面,让Apache处理它:serverfault.com/questions/56700/… 好吧,我看到了一些关于 nginx 是否这样做的问题 - serverfault.com/questions/334215/… - 从 2011 年开始。但我找不到任何更新的内容表明 nginx 现在允许请求压缩(搜索content-encoding 通过 nginx 文档) 是的,这些天你最好的选择是使用 HTTP/2。 有点沮丧,因为我已经在使用 NginX 进行响应压缩和 SSL。但我还没看完。

以上是关于在 Spring Boot REST 应用程序中处理 gzipped 请求的主要内容,如果未能解决你的问题,请参考以下文章

没有 REST 端点在 Spring Boot 应用程序中工作

在 Spring Boot REST 应用程序中处理 gzipped 请求

Spring Boot / REST - 示例代码在启动后终止

在 Spring Boot 2.2.0 应用程序中命中 REST 端点的问题

docker 镜像正在运行,但无法在 Spring Boot 应用程序中访问 REST 端点

Spring boot - 如何在 rest 应用程序中验证 Multipartfile