zjncs opened a new pull request, #3311:
URL: https://github.com/apache/rocketmq-dashboard/pull/3311
## Problem
The DLQ export endpoints (`GET /api/dlq/export` and `GET
/api/dlq/export-excel`) report scan completeness through
`X-DLQ-Export-Truncated`, `X-DLQ-Export-FailedQueues` and `X-DLQ-Export-Limit`
response headers, and the web UI reads exactly those headers to decide whether
to show its "export may be incomplete" warning (`web/src/api/message.ts`,
consumed in `web/src/pages/instance/dlq.tsx`).
However, `CorsConfig` never declared `exposedHeaders`. Per the Fetch
specification, browsers only let cross-origin JavaScript read response headers
that the server lists in `Access-Control-Expose-Headers` (plus the safelisted
ones). So in any split frontend/backend deployment — precisely the setup
`studio.cors.allowed-origins` exists for, and whose default value is the Vite
dev-server origins — the `X-DLQ-Export-*` headers were still sent on the wire
but invisible to JavaScript:
- `res.headers['x-dlq-export-truncated']` came back `undefined`,
- the frontend export meta silently degraded to `{truncated: false,
failedQueueCount: 0, limit: 0}`,
- and a truncated export (hard cap hit, or queues that could not be scanned)
was presented to the user as complete.
Same-origin deployments (default `/api` reverse proxy) are unaffected, which
is why this went unnoticed.
## Fix
Declare the three header names in the CORS mapping via `exposedHeaders(...)`
in `CorsConfig`. The names now live in a small shared `DlqExportHeaders`
constants holder (common/util) that both `DLQController` and `CorsConfig`
reference, so the endpoint and its CORS declaration cannot drift apart.
## Verification
Base SHA: `36126024` (current `rocketmq-studio` head).
Fail-before on base (`mvn test -Dtest=CorsConfigTest`), new test class:
```
[ERROR] Tests run: 3, Failures: 3, Errors: 0, Skipped: 0
[ERROR] CorsConfigTest.corsMappingShouldDeclareTheDlqExportHeaders:78 CORS
mapping must expose the DLQ export scan headers ==> expected: not <null>
[ERROR]
CorsConfigTest.excelExportShouldExposeScanHeadersToCrossOriginClients:
Cross-origin browsers cannot read the DLQ export scan headers;
Access-Control-Expose-Headers was: []
[ERROR]
CorsConfigTest.jsonExportShouldExposeScanHeadersToCrossOriginClients:
Cross-origin browsers cannot read the DLQ export scan headers;
Access-Control-Expose-Headers was: []
```
The two MockMvc tests issue real cross-origin GETs (with `Origin:
http://localhost:5173`) against the export endpoints; on base the
`X-DLQ-Export-Truncated: true` header is set on the response but
`Access-Control-Expose-Headers` stays empty.
Pass-after with the fix:
```
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0 -- in
org.apache.rocketmq.studio.common.config.CorsConfigTest
```
Surrounding suites with the fix applied:
```
[INFO] Tests run: 24, Failures: 0 ... -- in
org.apache.rocketmq.studio.instance.dlq.DLQControllerTest
[INFO] Tests run: 17, Failures: 0 ... -- in
org.apache.rocketmq.studio.instance.dlq.DLQServiceTest
[INFO] all org.apache.rocketmq.studio.common.* tests green
```
Note: `AuthCorsIntegrationTest` has 2 failures on pristine base `36126024`
as well (it still verifies the old `AuthService.isAuthenticated` API while
`AuthInterceptor` now calls `getAuthenticatedUser`) — pre-existing and
unrelated to this change.
**AI disclosure:** This change was prepared with AI assistance (GitHub
Copilot/Claude-style tooling guided by a human contributor).
--
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]