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 b4a67ccb3b fix(ai): preserve headers on transform fallback (#7122)
b4a67ccb3b is described below

commit b4a67ccb3bd0bae42b3a578456f99558a8950b87
Author: Liming Deng <[email protected]>
AuthorDate: Tue Sep 22 08:12:10 2026 +0800

    fix(ai): preserve headers on transform fallback (#7122)
    
    Co-authored-by: aias00 <[email protected]>
---
 .../response/AiResponseTransformerPlugin.java      |  5 ++--
 .../response/AiResponseTransformerPluginTest.java  | 29 ++++++++++++++++++++++
 2 files changed, 31 insertions(+), 3 deletions(-)

diff --git 
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPlugin.java
 
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPlugin.java
index 6dfea7c12d..8718bc1b3b 100644
--- 
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/main/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPlugin.java
@@ -358,10 +358,9 @@ public class AiResponseTransformerPlugin extends 
AbstractShenyuPlugin {
                                         HttpHeaders newHeaders = 
extractHeadersFromAiResponse(aiResponse);
                                         String newBody = 
extractBodyFromAiResponse(aiResponse);
 
-                                        this.getHeaders().clear();
-                                        this.getHeaders().putAll(newHeaders);
-
                                         if (Objects.nonNull(newBody) && 
!newBody.isEmpty()) {
+                                            this.getHeaders().clear();
+                                            
this.getHeaders().putAll(newHeaders);
                                             LOG.debug("Returning transformed 
response body: {}", newBody);
                                             return 
WebFluxResultUtils.result(this.exchange, 
newBody.getBytes(StandardCharsets.UTF_8));
                                         } else {
diff --git 
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPluginTest.java
index 2a7f835c6a..875ecc3ba9 100644
--- 
a/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPluginTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-ai/shenyu-plugin-ai-response-transformer/src/test/java/org/apache/shenyu/plugin/ai/transformer/response/AiResponseTransformerPluginTest.java
@@ -28,12 +28,16 @@ import 
org.apache.shenyu.plugin.ai.common.spring.ai.AiModelFactory;
 import 
org.apache.shenyu.plugin.ai.common.spring.ai.registry.AiModelFactoryRegistry;
 import 
org.apache.shenyu.plugin.ai.transformer.response.template.AiResponseTransformerTemplate;
 import org.apache.shenyu.plugin.api.ShenyuPluginChain;
+import org.apache.shenyu.plugin.api.result.DefaultShenyuResult;
+import org.apache.shenyu.plugin.api.result.ShenyuResult;
+import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.mockito.Mock;
 import org.mockito.MockedConstruction;
 import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.ai.chat.client.ChatClient;
 import org.springframework.ai.chat.model.ChatModel;
 import org.springframework.core.io.buffer.DataBuffer;
@@ -44,6 +48,7 @@ import org.springframework.http.MediaType;
 import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
 import org.springframework.mock.http.server.reactive.MockServerHttpResponse;
 import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
 import reactor.core.publisher.Mono;
 import reactor.test.StepVerifier;
 
@@ -56,6 +61,8 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mockConstruction;
 import static org.mockito.Mockito.verify;
@@ -171,6 +178,28 @@ class AiResponseTransformerPluginTest {
         }
     }
 
+    @Test
+    void testOriginalHeadersRemainWhenTransformedBodyIsInvalid() {
+        MockServerHttpResponse response = (MockServerHttpResponse) 
exchange.getResponse();
+        response.getHeaders().set("X-Original", "original");
+        AiResponseTransformerTemplate template = 
mock(AiResponseTransformerTemplate.class);
+        
when(template.assembleMessage(exchange)).thenReturn(Mono.just("{\"response\":{\"body\":\"\"}}"));
+        ChatClient chatClient = mock(ChatClient.class, RETURNS_DEEP_STUBS);
+        when(chatClient.prompt().user(anyString()).stream().content())
+                .thenReturn(Flux.just("HTTP/1.1 200 OK\nX-New: transformed"));
+        ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
+        when(context.getBean(ShenyuResult.class)).thenReturn(new 
DefaultShenyuResult());
+        SpringBeanUtils.getInstance().setApplicationContext(context);
+        AiResponseTransformerPlugin.AiResponseTransformerDecorator decorator =
+                new 
AiResponseTransformerPlugin.AiResponseTransformerDecorator(exchange, template, 
chatClient);
+        DataBuffer responseBody = 
response.bufferFactory().wrap("original".getBytes(StandardCharsets.UTF_8));
+
+        
StepVerifier.create(decorator.writeWith(Mono.just(responseBody))).verifyComplete();
+
+        assertEquals("original", response.getHeaders().getFirst("X-Original"));
+        assertNull(response.getHeaders().getFirst("X-New"));
+    }
+
     @Test
     void testExtractBodyFromAiResponse() {
         String aiResponse = "HTTP/1.1 200 OK\nContent-Type: 
application/json\n\n{\"status\":\"success\"}";

Reply via email to