From 2a449141d1cee415770c3a2aa49ae991ae795a64 Mon Sep 17 00:00:00 2001 From: ashinnotfound Date: Tue, 9 Apr 2024 22:04:33 +0800 Subject: [PATCH 1/2] Fix Bug(Gateway MVC): Make sure Retry filter sends correct body when retrying POST/PUT/etc --- .../cloud/gateway/server/mvc/common/MvcUtils.java | 10 ++++++++-- .../server/mvc/filter/RetryFilterFunctions.java | 4 +++- .../server/mvc/handler/RestClientProxyExchange.java | 4 +++- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java index 1afb1c52cc..0b99af7d39 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java @@ -102,8 +102,14 @@ public static Optional cacheAndReadBody(ServerRequest request, Class t public static ByteArrayInputStream cacheBody(ServerRequest request) { try { byte[] bytes = StreamUtils.copyToByteArray(request.servletRequest().getInputStream()); - ByteArrayInputStream body = new ByteArrayInputStream(bytes); - putAttribute(request, MvcUtils.CACHED_REQUEST_BODY_ATTR, body); + ByteArrayInputStream body; + if (bytes.length > 0) { + body = new ByteArrayInputStream(bytes); + putAttribute(request, MvcUtils.CACHED_REQUEST_BODY_ATTR, body); + } + else { + body = getAttribute(request, CACHED_REQUEST_BODY_ATTR); + } return body; } catch (IOException e) { diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/RetryFilterFunctions.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/RetryFilterFunctions.java index c7fd9acb5e..96fc9506c4 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/RetryFilterFunctions.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/filter/RetryFilterFunctions.java @@ -43,6 +43,8 @@ import org.springframework.web.servlet.function.ServerRequest; import org.springframework.web.servlet.function.ServerResponse; +import static org.springframework.cloud.gateway.server.mvc.filter.BodyFilterFunctions.adaptCachedBody; + public abstract class RetryFilterFunctions { private RetryFilterFunctions() { @@ -75,7 +77,7 @@ public static HandlerFilterFunction retry(RetryC if (isRetryableStatusCode(serverResponse.statusCode(), config) && isRetryableMethod(request.method(), config)) { // use this to transfer information to HttpStatusRetryPolicy - throw new RetryException(request, serverResponse); + throw new RetryException(adaptCachedBody().apply(request), serverResponse); } return serverResponse; }); diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/RestClientProxyExchange.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/RestClientProxyExchange.java index 1f24992472..5e6ad53364 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/RestClientProxyExchange.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/handler/RestClientProxyExchange.java @@ -24,6 +24,8 @@ import org.springframework.web.client.RestClient; import org.springframework.web.servlet.function.ServerResponse; +import static org.springframework.cloud.gateway.server.mvc.common.MvcUtils.cacheBody; + public class RestClientProxyExchange implements ProxyExchange { private final RestClient restClient; @@ -41,7 +43,7 @@ public ServerResponse exchange(Request request) { } private static int copyBody(Request request, OutputStream outputStream) throws IOException { - return StreamUtils.copy(request.getServerRequest().servletRequest().getInputStream(), outputStream); + return StreamUtils.copy(cacheBody(request.getServerRequest()), outputStream); } private static ServerResponse doExchange(Request request, ClientHttpResponse clientResponse) throws IOException { From 160f96928a017b39c92b8024c03baf63ea07ab1b Mon Sep 17 00:00:00 2001 From: ashinnotfound Date: Thu, 11 Apr 2024 19:41:27 +0800 Subject: [PATCH 2/2] Fix: Return correct ByteArrayInputStream object instead of null in some cases --- .../cloud/gateway/server/mvc/common/MvcUtils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java index 0b99af7d39..afcd4023aa 100644 --- a/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java +++ b/spring-cloud-gateway-server-mvc/src/main/java/org/springframework/cloud/gateway/server/mvc/common/MvcUtils.java @@ -109,6 +109,10 @@ public static ByteArrayInputStream cacheBody(ServerRequest request) { } else { body = getAttribute(request, CACHED_REQUEST_BODY_ATTR); + if (body == null) { + body = new ByteArrayInputStream(bytes); + putAttribute(request, MvcUtils.CACHED_REQUEST_BODY_ATTR, body); + } } return body; }