From cddeeedc5293c10a41369676b11802c0bbd61ba1 Mon Sep 17 00:00:00 2001 From: limbo Date: Mon, 17 Aug 2026 10:03:24 +0800 Subject: [PATCH] fix: specify UTF-8 charset for SSE event and comment byte encoding and add corresponding unit tests --- .../server/transport/SseEventFormatter.java | 5 +- .../transport/SseEventFormatterTest.java | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/transport/SseEventFormatterTest.java diff --git a/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/transport/SseEventFormatter.java b/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/transport/SseEventFormatter.java index 5cbcdf6eafe5..d20509a7d5fa 100644 --- a/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/transport/SseEventFormatter.java +++ b/shenyu-plugin/shenyu-plugin-mcp-server/src/main/java/org/apache/shenyu/plugin/mcp/server/transport/SseEventFormatter.java @@ -23,6 +23,7 @@ import org.springframework.http.codec.ServerSentEvent; import org.springframework.web.server.ServerWebExchange; +import java.nio.charset.StandardCharsets; import java.util.Objects; /** @@ -73,7 +74,7 @@ public static DataBuffer formatEvent(final ServerSentEvent event, final Serve String formattedEvent = sseData.toString(); LOG.debug("Formatted SSE event: {}", formattedEvent.trim()); - return exchange.getResponse().bufferFactory().wrap(formattedEvent.getBytes()); + return exchange.getResponse().bufferFactory().wrap(formattedEvent.getBytes(StandardCharsets.UTF_8)); } /** @@ -86,6 +87,6 @@ public static DataBuffer formatEvent(final ServerSentEvent event, final Serve public static DataBuffer formatComment(final String comment, final ServerWebExchange exchange) { String formattedComment = ": " + comment + "\n\n"; LOG.debug("Formatted SSE comment: {}", formattedComment.trim()); - return exchange.getResponse().bufferFactory().wrap(formattedComment.getBytes()); + return exchange.getResponse().bufferFactory().wrap(formattedComment.getBytes(StandardCharsets.UTF_8)); } } diff --git a/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/transport/SseEventFormatterTest.java b/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/transport/SseEventFormatterTest.java new file mode 100644 index 000000000000..18eb658e3587 --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-mcp-server/src/test/java/org/apache/shenyu/plugin/mcp/server/transport/SseEventFormatterTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shenyu.plugin.mcp.server.transport; + +import org.junit.jupiter.api.Test; +import org.springframework.core.io.buffer.DataBuffer; +import org.springframework.core.io.buffer.DataBufferUtils; +import org.springframework.http.codec.ServerSentEvent; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.web.server.MockServerWebExchange; + +import java.nio.charset.StandardCharsets; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +/** + * Test cases for {@link SseEventFormatter}. + */ +final class SseEventFormatterTest { + + @Test + void testFormatEventUsesUtf8() { + MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/mcp/sse").build()); + ServerSentEvent event = ServerSentEvent.builder("{\"message\":\"你好,世界\"}") + .event("message") + .build(); + + DataBuffer buffer = SseEventFormatter.formatEvent(event, exchange); + + assertArrayEquals("event: message\ndata: {\"message\":\"你好,世界\"}\n\n".getBytes(StandardCharsets.UTF_8), + readAndRelease(buffer)); + } + + @Test + void testFormatCommentUsesUtf8() { + MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/mcp/sse").build()); + + DataBuffer buffer = SseEventFormatter.formatComment("保持连接", exchange); + + assertArrayEquals(": 保持连接\n\n".getBytes(StandardCharsets.UTF_8), readAndRelease(buffer)); + } + + private static byte[] readAndRelease(final DataBuffer buffer) { + try { + byte[] bytes = new byte[buffer.readableByteCount()]; + buffer.read(bytes); + return bytes; + } finally { + DataBufferUtils.release(buffer); + } + } +}