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]

Reply via email to