【发布时间】:2020-01-23 22:34:08
【问题描述】:
我想从 webflux 端点返回一个大的(3 到 9 Mb 之间)json 正文。在这一点上,我只是试图将它作为Mono<ResponseEntity<String>> 返回——完全绕过任何序列化/反序列化。但是,在大多数情况下,它只返回实际字符串的一部分。 Content-Type 是正确的,但发送的字节不匹配 - 通常相差一个 Mb 或更多,但肯定短了几百 k。
您将在下面看到 Content-Type 正在设置(在较低级别),因此它不会将其发送到分块。既然 chunked 是默认设置,为什么会这样呢?它发生在 netty 或 jetty 上。
当我在发送 ResponseEntity 之前输出标头时,它显示传输编码:分块。然而,响应头(在 curl、chrome、Python 请求库中)都显示 Content-Length 而不是分块。
// IN CONTROLLER
log.info(response.getHeaders());
return Mono.just(new ResponseEntity<>(findByApplicationId(id), HttpStatus.OK));
这将记录以下[transfer-encoding:"chunked"]
// IN TERMINAL WITH CURL
MBP:my-test em$ curl -v localhost:8888/api/thing/0 > /dev/null
* TCP_NODELAY set
* Connected to localhost (::1) port 8888 (#0)
> GET /api/thing/0 HTTP/1.1
> Host: localhost:8888
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 5198562
<
{ [16308 bytes data]
100 5076k 100 5076k 0 0 16.0M 0 --:--:-- --:--:-- --:--:-- 16.0M
* Connection #0 to host localhost left intact
为什么要在上面设置 Content-Length - chunked 去哪里了?
报告的 Content-Length 和实际收到的字符串不匹配是很常见的(显然被截短了)
为了完整起见,这是我的 POM:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>bugfix-group</groupId>
<artifactId>webflux-jsonb</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>webflux-jsonb</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
【问题讨论】:
-
你永远不应该在响应头中设置
Transfer-Encoding,这是由容器来做的。 -
请在您的代码中包含a minimal, complete, verifiable example,而不仅仅是maven pom。您的 2 行不足以提供正确的答案。
-
您好 Joakim,感谢您的回复。我从来没有设置它,但它在发送响应之前已经设置(如预期的那样),但是它被 Content-Length 覆盖在较低级别的地方,我不知道为什么。
-
不要专注于
Content-Length和Transfer-Encoding,一旦你提供了minimal, complete, and verifiable example,那么其他人可以帮助你。 -
显然在您未提供的代码中做了一些事情。如果您希望我们为您提供帮助,您需要提供完整的图片。
标签: spring-boot spring-webflux embedded-jetty reactor-netty