feat(server): add response identity headers - #20268
Conversation
There was a problem hiding this comment.
🟢 Approval recommended
The implementation matches the documented proxy semantics, stays opt-in by default for security, and includes targeted unit + embedded test coverage for the new behavior.
Pull request overview
Adds an opt-in mechanism for Druid services to emit response identity headers on all HTTP responses (including early errors), and ensures Router proxying forwards these headers only as an all-or-nothing pair to avoid partial/ambiguous identity during mixed deployments.
Changes:
- Introduces
ResponseIdentityHeaderHandler(Jetty wrapper) to addX-Druid-Response-ServerandX-Druid-Response-Servicewhendruid.server.http.enableResponseIdentityHeaders=true. - Updates Router proxy servlets to clear Router-added identity and forward upstream identity headers only when both headers are present and the feature is enabled on the Router.
- Adds unit + embedded end-to-end coverage and documents the new configuration and proxy semantics.
File summaries
| File | Description |
|---|---|
| services/src/main/java/org/apache/druid/server/AsyncQueryForwardingServlet.java | Clears Router identity for proxied query responses and forwards upstream identity headers only as a complete pair when enabled. |
| server/src/main/java/org/apache/druid/server/AsyncManagementForwardingServlet.java | Applies the same all-or-nothing identity header forwarding rules for management proxying via Router. |
| server/src/main/java/org/apache/druid/server/initialization/ServerConfig.java | Adds enableResponseIdentityHeaders config flag with serde/equals/hashCode/toString support. |
| server/src/main/java/org/apache/druid/server/initialization/jetty/JettyServerModule.java | Wraps the full Jetty handler chain with ResponseIdentityHeaderHandler when enabled. |
| server/src/main/java/org/apache/druid/server/initialization/jetty/ResponseIdentityHeaderHandler.java | New handler that injects the two response identity headers and provides helper methods for Router proxy behavior. |
| server/src/test/java/org/apache/druid/initialization/ServerConfigTest.java | Verifies default config deserialization keeps identity headers disabled. |
| server/src/test/java/org/apache/druid/server/AsyncManagementForwardingServletTest.java | Updates test wiring for new ServerConfig dependency in the management forwarding servlet. |
| server/src/test/java/org/apache/druid/server/initialization/jetty/ResponseIdentityHeaderHandlerTest.java | New unit tests for clearing Router identity and enforcing pairwise forwarding rules. |
| embedded-tests/src/test/java/org/apache/druid/testing/embedded/server/ResponseIdentityHeaderTest.java | New embedded E2E tests covering direct vs Router-proxied identity behavior across multiple services/endpoints. |
| docs/configuration/index.md | Documents the new druid.server.http.enableResponseIdentityHeaders setting and security caveat. |
| docs/api-reference/api-reference.md | Documents the headers and Router proxy behavior in the API overview. |
Review details
- Files reviewed: 11/11 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
FrankChen021
left a comment
There was a problem hiding this comment.
| Severity | Findings |
|---|---|
| P0 | 0 |
| P1 | 0 |
| P2 | 3 |
| P3 | 0 |
| Total | 3 |
Static review found three correctness and integration issues in the response identity-header path. The inline comments describe the affected server configurations and response lifecycles.
Reviewed 11 of 11 changed files.
This is an automated review by Codex GPT-5.6-Luna(max)
There was a problem hiding this comment.
| Severity | Findings |
|---|---|
| P0 | 0 |
| P1 | 0 |
| P2 | 2 |
| P3 | 0 |
| Total | 2 |
Static review found two current-head correctness issues in error-response lifecycle and proxy failure handling.
Reviewed 15 of 15 changed files.
This is an automated review by Codex GPT-5.6-Luna(max)
FrankChen021
left a comment
There was a problem hiding this comment.
I have reviewed the code for correctness, edge cases, concurrency, and integration risks; no new-head issues found.
Reviewed 15 of 15 changed files.
This is an automated review by Codex GPT-5.6-Luna(max)
Description
This PR adds opt-in response headers that identify the Druid process which generated an HTTP response:
X-Druid-Server: advertised host and portX-Druid-Service: configureddruid.servicenameX-Druid-Version: Druid versionThe feature is disabled by default and can be enabled with:
druid.server.http.enableResponseIdentityHeaders=trueThe identity handler wraps the complete Jetty handler chain and restores the headers after downstream response resets, so locally generated responses, including early HTTP errors, receive the headers when enabled.
Proxy behavior
For query and management requests proxied by a Router:
Treating the three headers as an all-or-nothing triple prevents clients from receiving an ambiguous partial identity.
The standalone Coordinator's
/druid/indexer/*proxy to a separate Overlord follows the same contract, so it forwards a complete Overlord identity without mixing it with the Coordinator identity.Security
The headers can reveal internal hostnames, IP addresses, ports, and the Druid version. The setting remains disabled by default and should only be enabled when clients are authorized to receive this information.
Automated tests
ResponseIdentityHeaderTest: 6 embedded end-to-end tests passed.git diff --checkpassed.Real nano cluster validation
The feature was tested against a locally built
apache-druid-39.0.0-SNAPSHOTnano-quickstart cluster. All 16 requests returned the expected status and complete identity triple.X-Druid-ServerX-Druid-ServiceX-Druid-Versionhttp://localhost:8888/status/healthlocalhost:8888druid/router39.0.0-SNAPSHOThttp://localhost:8082/status/healthlocalhost:8082druid/broker39.0.0-SNAPSHOThttp://localhost:8081/status/healthlocalhost:8081druid/coordinator39.0.0-SNAPSHOThttp://localhost:8083/status/healthlocalhost:8083druid/historical39.0.0-SNAPSHOThttp://localhost:8091/status/healthlocalhost:8091druid/middleManager39.0.0-SNAPSHOThttp://localhost:8081/druid/coordinator/v1/isLeaderlocalhost:8081druid/coordinator39.0.0-SNAPSHOThttp://localhost:8888/druid/coordinator/v1/isLeaderlocalhost:8081druid/coordinator39.0.0-SNAPSHOThttp://localhost:8081/druid/indexer/v1/isLeaderlocalhost:8081druid/coordinator39.0.0-SNAPSHOThttp://localhost:8888/druid/indexer/v1/isLeaderlocalhost:8081druid/coordinator39.0.0-SNAPSHOThttp://localhost:8082/druid/v2/sqllocalhost:8082druid/broker39.0.0-SNAPSHOThttp://localhost:8888/druid/v2/sqllocalhost:8082druid/broker39.0.0-SNAPSHOThttp://localhost:8082/druid/v2localhost:8082druid/broker39.0.0-SNAPSHOThttp://localhost:8888/druid/v2localhost:8082druid/broker39.0.0-SNAPSHOThttp://localhost:8083/druid/v2localhost:8083druid/historical39.0.0-SNAPSHOThttp://localhost:8888/status/healthPATCHrejectionlocalhost:8888druid/router39.0.0-SNAPSHOThttp://localhost:8888/not-a-druid-endpointlocalhost:8888druid/router39.0.0-SNAPSHOTThe nano configuration runs Coordinator and Overlord in one process on port
8081withdruid.service=druid/coordinator, so requests to Overlord endpoints correctly report that process identity.Release note
Druid can optionally return
X-Druid-Server,X-Druid-Service, andX-Druid-Versionon HTTP responses, allowing operators to identify the process and version that served a direct or Router-proxied request. Enable the feature withdruid.server.http.enableResponseIdentityHeaders=trueonly for clients permitted to receive cluster topology and version information.Key changed/added classes in this PR
ResponseIdentityHeaderHandlerOverlordProxyServletAsyncManagementForwardingServletAsyncQueryForwardingServletResponseIdentityHeaderTestThis PR has: