Wang1rrr opened a new issue, #4870: URL: https://github.com/apache/rocketmq-dashboard/issues/4870
### Before Creating the Bug Report - [x] I have searched the [open issues](https://github.com/apache/rocketmq-dashboard/issues) of this repository and believe that this is not a duplicate. - [x] This is a defect in RocketMQ Studio, not a usage question and not a defect in another Apache RocketMQ repository. - [x] I can reproduce this on the current `rocketmq-studio` branch (the Studio trunk the pull request template points at), commit `4c697f07acde460e2344375cb1f82669f5b270fd`. ### Studio Version ``` branch: rocketmq-studio git commit id: 4c697f07acde460e2344375cb1f82669f5b270fd deployed as: built from source ``` ### Runtime Environment ``` OS: Windows 11 (development box); the defect is in the web layer, so the host does not matter MySQL: required only to run the console against a real cluster; reproduced from the sources and the web unit tests browser (for UI issues): any; the affected page is web/src/pages/instance/message.tsx (消息查询 -> 详情) ``` ### Connected RocketMQ Cluster ``` RocketMQ version: 5.5.0 self-managed (the Apache provider path); the Aliyun and Tencent providers set the same fields access mode: Direct / Proxy Local / Proxy Cluster - the response shape is identical deployment: any cluster holding a message whose body is larger than 64 KiB, or whose body is not valid UTF-8 ``` ### Build Toolchain ``` node: v22 (web/ package.json engines), npm ci from web/package-lock.json ``` ### Describe the Bug The server already tells the console when the body it is returning is not the whole body, and the console throws that information away. `RocketMQMessageProvider.displayBody` (`provider/apache/RocketMQMessageProvider.java:881`-`:903`) caps what it puts on the wire: - a body that decodes as UTF-8 is cut at `MAX_BODY_DISPLAY_BYTES = 64 * 1024` (`:87`), returned with `bodyEncoding = "UTF-8"` and `bodyTruncated = body.length > textLength`; - a body that does not decode is base64-encoded, cut at `MAX_BINARY_BODY_DISPLAY_BYTES = 48 * 1024` (`:88`), and returned with `bodyEncoding = "BASE64"` and the same truncation flag. `toRecordVO` (`:867`-`:869`) copies both onto `MessageRecordVO` (`instance/message/MessageRecordVO.java:39`-`:40`), the Aliyun provider sets them too (`provider/alibaba/AliyunConverters.java:241`, `:243`), and the AI tool schema publishes them (`resources/tool-catalog/tools/message.yaml:86`, `:88`). The project's own API specification documents them. `docs/api-spec.md` §8.1 has a `#### MessageRecord` field table (`:1324`-`:1343`) listing `bodyEncoding` (`:1336`, 消息体编码,如 `UTF-8` / `BASE64`), `bodyTruncated` (`:1337`, 消息体是否被截断) and `propertiesTruncated` (`:1342`). So this is not an undocumented server behaviour that the frontend never learned about - the contract is written down, and the frontend type does not implement it. The web type does not declare them. `web/src/api/message.ts:4`-`:19` lists `msgId`, `topic`, `tag`, `key`, `brokerName`, `queueId`, `queueOffset`, `body`, `storeTime`, `bornHost`, `storeHost`, `reconsumeTimes`, `properties`, `size` - no `bodyEncoding`, no `bodyTruncated`, no `propertiesTruncated`. So no page can read them, and `tsc` cannot complain about the omission because the fields are simply absent from the contract as far as the frontend knows. The detail panel then presents whatever arrived as the message body: - `web/src/pages/instance/message.tsx:959` renders `formatBody(selectedMsg.body)` inside a `copyable` `Paragraph` under the 消息体 heading, with no marker of any kind; - `web/src/pages/instance/message.tsx:731` saves `formatBody(record.body)` as `${record.msgId}.json` with `type: 'application/json'`. Two concrete operator-facing failures follow: 1. **A truncated body reads as a complete one.** Query a 5 MiB JSON message and the panel shows the first 64 KiB, pretty-printed, in a monospace block with a copy button, and the download writes a `.json` file. The JSON is cut mid-token, so anyone who copies or downloads it gets a file that does not parse, with nothing on screen explaining why. The natural conclusion - "this producer is writing malformed JSON" - is wrong. 2. **A binary body is shown as text.** For a protobuf, gzip or otherwise non-UTF-8 payload the panel shows base64 in a block styled for JSON, and the download names it `.json`. `formatBody` (`:140`) tries `JSON.parse` first, so the operator gets an unexplained wall of base64 rather than the statement "this is not text". The repository already has the right idiom for exactly this situation on the DLQ page: `web/src/pages/instance/dlq.tsx:917`-`:923` renders 属性过多或单值过长,服务端已截断展示 whenever `propertiesTruncated` is set, and `DLQMessage` declares that field (`web/src/api/message.ts:123`). The message page is the one place the flags are dropped. #4777 fixed the copy/download path to preserve the received body verbatim and explicitly scoped this out: "It does not recover backend-truncated or encoded data." This report is that remaining half - not recovering the data (the server never sent it) but stopping the UI from implying it did. ### Steps to Reproduce 1. Against a self-managed cluster, send a message whose body is larger than 64 KiB (a big JSON document is enough), and a second message whose body is binary (any non-UTF-8 bytes). 2. Console -> 消息查询, pick the topic, query by Message ID, and open 详情 on the large message. 3. Read the 消息体 block, then click 下载. 4. Repeat for the binary message. ### What Did You Expect to See? The panel to state what the server already reported: that the body was cut at the display limit, so what is shown, copied and downloaded is incomplete; and, for the binary message, that the body is not UTF-8 text and is being shown base64-encoded. The same treatment the DLQ page gives `propertiesTruncated`. ### What Did You See Instead? A complete-looking, pretty-printed body with no truncation marker, and a base64 blob presented as if it were the message text. Both download as `<msgId>.json` with `Content-Type: application/json`. The `bodyEncoding` and `bodyTruncated` values the server computed are present in the HTTP response and discarded by the frontend type. ### Additional Context Fix scope: declare `bodyEncoding` and `bodyTruncated` on `MessageRecord`, render a truncation warning and a binary-body notice above the 消息体 block in the detail panel, add the two zh/en strings under `web/src/i18n/`, and pin both with tests in `web/src/pages/instance/__tests__/MessagePage.test.tsx` - one that fails if either notice disappears, one that fails if a complete UTF-8 body starts showing warnings. Deliberately left out of this report, so the fix stays reviewable: - the detail panel shows no message **properties** at all, so `propertiesTruncated` has nothing to annotate yet; adding a properties table (with the DLQ page's truncation note) is a separate change - the download filename and MIME type for a base64 body (`.json` / `application/json`) - that is #4777's area - `storeTime: number | string` on the same interface, which papers over the mock layer using ISO strings while `MessageRecordVO.storeTime` is a `long` and §8.1 documents the field as `number` (`:1338`) ### Are You Willing to Submit a Pull Request? - [x] Yes, I am willing to submit a pull request. -- 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]
