hanzhe-one opened a new pull request, #7920: URL: https://github.com/apache/shenyu/pull/7920
Fixes #7908. `AiResponseTransformerDecorator` decompressed a gzip upstream body into a `String` and used that decoded text for two purposes: building the model prompt, and — when the model failed or produced no usable body — writing the response body. The response headers were never touched, so the client got plaintext that still carried `Content-Encoding: gzip` and a `Content-Length` of the decoded text. A gzip-decoding client cannot read that fallback. ### Change Separate the prompt representation from the fallback wire representation: - Keep the original wire bytes next to the decoded prompt text; the decoded text is now only ever used to populate the prompt. - **Model error** (`onErrorResume`): write the original bytes back instead of the decoded `String`. - **Invalid or missing generated body**: write the original bytes back. - **Successful transformation**: the new body is always written as plain UTF-8, so an inherited `Content-Encoding` is removed rather than left to describe bytes it no longer matches. This covers a model that echoes the upstream `Content-Encoding: gzip` header into its generated headers. - Both fallbacks go through one `writeOriginalResponse` helper, which writes via `super.writeWith` so the upstream headers and status are preserved exactly. ### Tests Four regressions in `AiResponseTransformerPluginTest`, each asserting the client-visible bytes and headers: | Case | Expectation | | --- | --- | | gzip upstream, model error | original gzip bytes returned, `Content-Encoding: gzip` kept, gunzips to the upstream JSON | | gzip upstream, invalid generated body | same | | uncompressed upstream, model error | original bytes returned, no `Content-Encoding` | | gzip upstream, successful transformation | plain UTF-8 body, `Content-Encoding` removed | The gzip cases fail on the current code exactly as the issue reports — `array lengths differ, expected: <40> but was: <20>`, i.e. the 20-byte decoded text was returned under the gzip header — and the uncompressed control passes both before and after. All 68 tests in `shenyu-plugin-ai-response-transformer` pass with checkstyle; the `-am` build additionally runs `shenyu-plugin-ai-common`, where `OpenAiModelFactoryTest`/`DeepSeekModelFactoryTest` fail on this machine with `Unable to establish loopback connection` (NIO loopback is broken locally), unrelated to this change. ### Not in scope - #6811 (Inflater/resource closure) and #6756 (successful-output header mutation timing) are separate defects and are untouched here. - Whether the transformer should re-compress a transformed body when the client sent `Accept-Encoding: gzip` is a behavior question, not a correctness one; this PR only makes sure the headers never misdescribe the bytes actually written. - [x] I have read the [contribution guidelines](https://shenyu.apache.org/community/contributor-guide). - [x] I submit test cases (unit or integration tests) that back your changes. - [ ] Your local test passed `./mvnw clean install -Dmaven.javadoc.skip=true` (full build not run; module tests + checkstyle pass). -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
