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,