From 258dc09b4908d7608228821f1d52da480147e7fc Mon Sep 17 00:00:00 2001 From: Muchnik Andrey Date: Sat, 9 Mar 2024 00:22:53 +0300 Subject: [PATCH] Fix bug for ModifyResponseBodyGatewayFilter not setting up response content-type, if newContentType is present in config. Fixes gh-2647 (#2649) --- ...odifyResponseBodyGatewayFilterFactory.java | 6 ++++++ ...ResponseBodyGatewayFilterFactoryTests.java | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java index d365ed6768..5d274e1db8 100644 --- a/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java +++ b/spring-cloud-gateway-server/src/main/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactory.java @@ -40,6 +40,7 @@ import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpResponseDecorator; +import org.springframework.util.StringUtils; import org.springframework.web.reactive.function.BodyInserter; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.ClientResponse; @@ -233,6 +234,11 @@ public Mono writeWith(Publisher body) { || headers.containsKey(HttpHeaders.CONTENT_LENGTH)) { messageBody = messageBody.doOnNext(data -> headers.setContentLength(data.readableByteCount())); } + + if (StringUtils.hasText(config.newContentType)) { + headers.set(HttpHeaders.CONTENT_TYPE, config.newContentType); + } + // TODO: fail if isStreamingMediaType? return getDelegate().writeWith(messageBody); })); diff --git a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactoryTests.java b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactoryTests.java index 6db20d0b27..8fc2160770 100644 --- a/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactoryTests.java +++ b/spring-cloud-gateway-server/src/test/java/org/springframework/cloud/gateway/filter/factory/rewrite/ModifyResponseBodyGatewayFilterFactoryTests.java @@ -39,6 +39,8 @@ import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.util.UriComponentsBuilder; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @SpringBootTest(webEnvironment = RANDOM_PORT, properties = "spring.codec.max-in-memory-size=40") @@ -63,6 +65,16 @@ public void testModificationOfResponseBody() { .exchange().expectBody().json("{\"value\": \"httpbin compatible home\", \"length\": 23}"); } + @Test + public void testModificationOfContentType() { + URI uri = UriComponentsBuilder.fromUriString(this.baseUri + "/").build(true).toUri(); + + testClient.get().uri(uri).header("Host", "www.modifyresponsebodyjavacontenttype.org").accept(MediaType.ALL) + .exchange().expectHeader().valueEquals(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE) + .expectBody().consumeWith(result -> assertThat(new String(result.getResponseBody(), UTF_8)) + .isEqualTo("Modified response")); + } + @Test public void modifyResponeBodyToLarge() { testClient.post().uri("/post").header("Host", "www.modifyresponsebodyjavatoolarge.org") @@ -97,6 +109,14 @@ public RouteLocator testRouteLocator(RouteLocatorBuilder builder) { return Mono.just(toLarge); })) .uri(uri)) + .route("modify_response_java_test_content_type", + r -> r.path("/").and().host("www.modifyresponsebodyjavacontenttype.org") + .filters( + f -> f.prefixPath("/httpbin").modifyResponseBody(String.class, String.class, + MediaType.TEXT_PLAIN_VALUE, (webExchange, originalResponse) -> { + return Mono.just("Modified response"); + })) + .uri(uri)) .build(); }