This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new cd514ff292 fix(modify-response): preserve non-json bodies (#7131)
cd514ff292 is described below
commit cd514ff292d6e85f299ae3a549544f6fa2d04936
Author: Liming Deng <[email protected]>
AuthorDate: Sun Sep 20 16:54:44 2026 +0800
fix(modify-response): preserve non-json bodies (#7131)
Co-authored-by: aias00 <[email protected]>
---
.../modify/response/ModifyResponsePlugin.java | 17 ++++++++++
.../modify/response/ModifyResponsePluginTest.java | 37 ++++++++++++++++++++++
2 files changed, 54 insertions(+)
diff --git
a/shenyu-plugin/shenyu-plugin-modify-response/src/main/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePlugin.java
b/shenyu-plugin/shenyu-plugin-modify-response/src/main/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePlugin.java
index d4ff5a4003..dd2598e724 100644
---
a/shenyu-plugin/shenyu-plugin-modify-response/src/main/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePlugin.java
+++
b/shenyu-plugin/shenyu-plugin-modify-response/src/main/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePlugin.java
@@ -40,6 +40,7 @@ import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@@ -97,6 +98,9 @@ public class ModifyResponsePlugin extends
AbstractShenyuPlugin {
@NonNull
public Mono<Void> writeWith(@NonNull final Publisher<? extends
DataBuffer> body) {
modifyResponseHeadersAndStatus();
+ if (!hasBodyModifications() || !isJsonResponse()) {
+ return super.writeWith(body);
+ }
final Mono<DataBuffer> dataBufferMono = DataBufferUtils.join(body);
return dataBufferMono.flatMap(dataBuffer -> {
byte[] bytes = new byte[dataBuffer.readableByteCount()];
@@ -152,6 +156,19 @@ public class ModifyResponsePlugin extends
AbstractShenyuPlugin {
this.getDelegate().getHeaders().putAll(httpHeaders);
}
+ private boolean hasBodyModifications() {
+ return CollectionUtils.isNotEmpty(this.ruleHandle.getAddBodyKeys())
+ ||
CollectionUtils.isNotEmpty(this.ruleHandle.getReplaceBodyKeys())
+ ||
CollectionUtils.isNotEmpty(this.ruleHandle.getRemoveBodyKeys());
+ }
+
+ private boolean isJsonResponse() {
+ MediaType contentType = this.getHeaders().getContentType();
+ return Objects.isNull(contentType)
+ || MediaType.APPLICATION_JSON.isCompatibleWith(contentType)
+ || contentType.getSubtype().endsWith("+json");
+ }
+
private byte[] modifyBody(final byte[] responseBody) {
try {
String bodyStr = modifyBody(new String(responseBody,
StandardCharsets.UTF_8));
diff --git
a/shenyu-plugin/shenyu-plugin-modify-response/src/test/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePluginTest.java
b/shenyu-plugin/shenyu-plugin-modify-response/src/test/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePluginTest.java
index 0f23982365..7aeeab8c01 100644
---
a/shenyu-plugin/shenyu-plugin-modify-response/src/test/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePluginTest.java
+++
b/shenyu-plugin/shenyu-plugin-modify-response/src/test/java/org/apache/shenyu/plugin/modify/response/ModifyResponsePluginTest.java
@@ -32,6 +32,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.reactivestreams.Publisher;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.MockServerHttpResponse;
import org.springframework.mock.web.server.MockServerWebExchange;
@@ -42,6 +43,7 @@ import reactor.test.StepVerifier;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -129,6 +131,41 @@ public final class ModifyResponsePluginTest {
.verifyComplete();
}
+ @Test
+ public void testWriteWithPreservesNonJsonBodyForHeaderOnlyRule() {
+ final ModifyResponseRuleHandle responseRuleHandle = new
ModifyResponseRuleHandle();
+ responseRuleHandle.setAddHeaders(Collections.singletonMap("X-Test",
"header-only"));
+ final ModifyResponsePlugin.ModifyResponseDecorator decorator =
+ new ModifyResponsePlugin.ModifyResponseDecorator(exchange,
responseRuleHandle);
+ final MockServerHttpResponse response = (MockServerHttpResponse)
exchange.getResponse();
+ response.getHeaders().setContentType(MediaType.TEXT_HTML);
+ final DataBuffer dataBuffer =
response.bufferFactory().wrap("<p>unchanged</p>".getBytes(StandardCharsets.UTF_8));
+
+
StepVerifier.create(decorator.writeWith(Mono.just(dataBuffer))).verifyComplete();
+
+ assertEquals("header-only", response.getHeaders().getFirst("X-Test"));
+ StepVerifier.create(response.getBodyAsString())
+ .expectNext("<p>unchanged</p>")
+ .verifyComplete();
+ }
+
+ @Test
+ public void testWriteWithSkipsBodyRulesForNonJsonResponse() {
+ final ModifyResponseRuleHandle responseRuleHandle = new
ModifyResponseRuleHandle();
+ responseRuleHandle.setRemoveBodyKeys(Collections.singleton("$.value"));
+ final ModifyResponsePlugin.ModifyResponseDecorator decorator =
+ new ModifyResponsePlugin.ModifyResponseDecorator(exchange,
responseRuleHandle);
+ final MockServerHttpResponse response = (MockServerHttpResponse)
exchange.getResponse();
+ response.getHeaders().setContentType(MediaType.APPLICATION_XML);
+ final DataBuffer dataBuffer =
response.bufferFactory().wrap("<value>unchanged</value>".getBytes(StandardCharsets.UTF_8));
+
+
StepVerifier.create(decorator.writeWith(Mono.just(dataBuffer))).verifyComplete();
+
+ StepVerifier.create(response.getBodyAsString())
+ .expectNext("<value>unchanged</value>")
+ .verifyComplete();
+ }
+
@Test
public void testGetOrder() {
assertEquals(modifyResponsePlugin.getOrder(),
PluginEnum.MODIFY_RESPONSE.getCode());