This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 8ba79510 fix(message): preserve UTF-8 message body truncation 
boundaries (#1496)
8ba79510 is described below

commit 8ba79510a4219242be993bfb58efaf840b9a2402
Author: yyqdbngt <[email protected]>
AuthorDate: Tue Aug 11 17:53:15 2026 +0800

    fix(message): preserve UTF-8 message body truncation boundaries (#1496)
    
    Co-authored-by: yyqdbngt <[email protected]>
---
 .../studio/provider/apache/RocketMQMessageProvider.java    | 14 ++++++--------
 .../provider/apache/RocketMQMessageProviderTest.java       | 14 ++++++++++++++
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProvider.java
 
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProvider.java
index 208b3000..64ad563c 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProvider.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProvider.java
@@ -494,14 +494,8 @@ public class RocketMQMessageProvider implements 
MessageProvider {
             return new DisplayBody(null, null, false);
         }
         int textLength = Math.min(body.length, MAX_BODY_DISPLAY_BYTES);
-        // When truncating, walk back to the last complete UTF-8 character 
boundary
-        // to avoid splitting a multi-byte character, which would cause the 
decoder
-        // to fall through to BASE64 encoding even for valid UTF-8 text.
-        if (textLength < body.length) {
-            while (textLength > 0 && (body[textLength] & 0xC0) == 0x80) {
-                textLength--;
-            }
-            if (textLength > 0 && (body[textLength] & 0xC0) == 0xC0) {
+        if (textLength < body.length && 
isUtf8ContinuationByte(body[textLength])) {
+            while (textLength > 0 && isUtf8ContinuationByte(body[textLength])) 
{
                 textLength--;
             }
         }
@@ -519,6 +513,10 @@ public class RocketMQMessageProvider implements 
MessageProvider {
         }
     }
 
+    private boolean isUtf8ContinuationByte(byte value) {
+        return (value & 0xC0) == 0x80;
+    }
+
     private Map<String, String> limitProperties(Map<String, String> 
properties) {
         if (properties == null || properties.isEmpty()) {
             return Collections.emptyMap();
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProviderTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProviderTest.java
index 6028ceb0..cc57db38 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProviderTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/provider/apache/RocketMQMessageProviderTest.java
@@ -192,6 +192,20 @@ class RocketMQMessageProviderTest {
         assertThat(record.isBodyTruncated()).isFalse();
     }
 
+    @Test
+    void toRecordVODoesNotSplitUtf8CharacterAtBodyLimit() {
+        MessageExt message = new MessageExt();
+        message.setMsgId("msg-utf8");
+        message.setTopic("TopicA");
+        message.setBody(("x".repeat(64 * 1024 - 1) + 
"\u4E2Dsuffix").getBytes(StandardCharsets.UTF_8));
+
+        MessageRecordVO record = provider.toRecordVO(message);
+
+        assertThat(record.getBodyEncoding()).isEqualTo("UTF-8");
+        assertThat(record.getBody()).isEqualTo("x".repeat(64 * 1024 - 1));
+        assertThat(record.isBodyTruncated()).isTrue();
+    }
+
     @Test
     void getMessageTraceParsesPubAndSubAfterPerRocketMq533Layout() throws 
Exception {
         // Field order follows RocketMQ 5.3.3 TraceDataEncoder: Pub = type, 
time, region, group,

Reply via email to