diff --git a/pom.xml b/pom.xml
index e9e3f4bd..e0fb91c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,6 +57,7 @@
3.0.1-SNAPSHOT
4.0.1-SNAPSHOT
1.17.3
+ 1.6.21
diff --git a/spring-cloud-gateway-sample/pom.xml b/spring-cloud-gateway-sample/pom.xml
index 06456cf8..5ffe37d8 100644
--- a/spring-cloud-gateway-sample/pom.xml
+++ b/spring-cloud-gateway-sample/pom.xml
@@ -95,6 +95,7 @@
org.jetbrains.kotlin
kotlin-maven-plugin
+ ${kotlin-maven-plugin.version}
-Xjsr305=strict
diff --git a/spring-cloud-gateway-server/pom.xml b/spring-cloud-gateway-server/pom.xml
index b0afd78f..f49720cc 100644
--- a/spring-cloud-gateway-server/pom.xml
+++ b/spring-cloud-gateway-server/pom.xml
@@ -230,6 +230,7 @@
kotlin-maven-plugin
org.jetbrains.kotlin
+ ${kotlin-maven-plugin.version}
17
diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
index 45c7ff72..57a041b4 100644
--- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
+++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtils.java
@@ -369,14 +369,19 @@ public final class ServerWebExchangeUtils {
if (log.isTraceEnabled()) {
log.trace("retaining body in exchange attribute");
}
- exchange.getAttributes().put(CACHED_REQUEST_BODY_ATTR, dataBuffer);
+
+ Object cachedDataBuffer = exchange.getAttribute(CACHED_REQUEST_BODY_ATTR);
+ // don't cache if body is already cached
+ if (!(cachedDataBuffer instanceof DataBuffer)) {
+ exchange.getAttributes().put(CACHED_REQUEST_BODY_ATTR, dataBuffer);
+ }
}
ServerHttpRequest decorator = new ServerHttpRequestDecorator(exchange.getRequest()) {
@Override
public Flux getBody() {
return Mono.fromSupplier(() -> {
- if (exchange.getAttributeOrDefault(CACHED_REQUEST_BODY_ATTR, null) == null) {
+ if (exchange.getAttribute(CACHED_REQUEST_BODY_ATTR) == null) {
// probably == downstream closed or no body
return null;
}
diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtilsTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtilsTests.java
index d3dce34b..2531370b 100644
--- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtilsTests.java
+++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/support/ServerWebExchangeUtilsTests.java
@@ -16,14 +16,17 @@
package org.springframework.cloud.gateway.support;
+import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBuffer;
+import org.springframework.http.HttpMethod;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.reactive.function.server.HandlerStrategies;
@@ -70,8 +73,42 @@ public class ServerWebExchangeUtilsTests {
.block();
}
+ @Test
+ public void duplicatedCachingDataBufferHandling() {
+ MockServerWebExchange exchange = mockExchange(HttpMethod.POST, Collections.emptyMap());
+ DataBuffer dataBufferBeforeCaching = exchange.getResponse().bufferFactory()
+ .wrap("Cached buffer".getBytes(StandardCharsets.UTF_8));
+ exchange.getAttributes().put(CACHED_REQUEST_BODY_ATTR, dataBufferBeforeCaching);
+
+ ServerWebExchangeUtils
+ .cacheRequestBodyAndRequest(exchange,
+ (serverHttpRequest) -> ServerRequest
+ .create(exchange.mutate().request(serverHttpRequest).build(),
+ HandlerStrategies.withDefaults().messageReaders())
+ .bodyToMono(DefaultDataBuffer.class))
+ .block();
+
+ DataBuffer dataBufferAfterCached = exchange.getAttribute(CACHED_REQUEST_BODY_ATTR);
+
+ Assertions.assertThat(dataBufferBeforeCaching).isEqualTo(dataBufferAfterCached);
+ }
+
private MockServerWebExchange mockExchange(Map vars) {
- MockServerHttpRequest request = MockServerHttpRequest.get("/get").build();
+ return mockExchange(HttpMethod.GET, vars);
+ }
+
+ private MockServerWebExchange mockExchange(HttpMethod method, Map vars) {
+
+ MockServerHttpRequest request = null;
+ if (HttpMethod.GET.equals(method)) {
+ request = MockServerHttpRequest.get("/get").build();
+ }
+ else if (HttpMethod.POST.equals(method)) {
+ request = MockServerHttpRequest.post("/post").body("post body");
+ }
+
+ Assertions.assertThat(request).as("Method was not one of GET or POST").isNotNull();
+
MockServerWebExchange exchange = MockServerWebExchange.from(request);
ServerWebExchangeUtils.putUriTemplateVariables(exchange, vars);
return exchange;