FrankChen021 opened a new pull request, #20268: URL: https://github.com/apache/druid/pull/20268
### Description This PR adds opt-in response headers that identify the Druid process which generated an HTTP response: - `X-Druid-Response-Server`: advertised host and port - `X-Druid-Response-Service`: configured `druid.service` name The feature is disabled by default and can be enabled with: ```properties druid.server.http.enableResponseIdentityHeaders=true ``` The identity handler wraps the complete Jetty handler chain, so locally generated responses, including early HTTP errors, receive the headers when enabled. #### Router proxy behavior For query and management requests proxied by a Router: - If the upstream returns both identity headers, the Router forwards the upstream identity. - If the upstream returns neither header or only one header, the Router returns neither identity header. - If no upstream response is received and the Router generates the response, the headers identify the Router. - A Router with the feature disabled suppresses upstream identity headers. Treating the two headers as an all-or-nothing pair prevents clients from receiving an ambiguous partial identity during rolling upgrades or partial configuration. #### Security The server header can reveal internal hostnames, IP addresses, and ports. The setting remains disabled by default and should only be enabled when clients are authorized to receive cluster topology information. #### Automated tests - 45 focused configuration, handler, management-proxy, and query-proxy tests passed. - `ResponseIdentityHeaderTest`: 6 embedded end-to-end tests passed. - The embedded coverage includes Coordinator and Overlord APIs directly and through Router, Broker SQL and native queries directly and through Router, a native query directly to Historical, and Router-generated responses. - `git diff --check origin/master...HEAD` passed. #### Real nano cluster validation The feature was also tested against a locally built `apache-druid-39.0.0-SNAPSHOT` nano-quickstart cluster. All 16 requests returned the expected status and process identity. | URL | Request | Status | Response server | Response service | |---|---|---:|---|---| | `http://localhost:8888/status/health` | Router health | 200 | `localhost:8888` | `druid/router` | | `http://localhost:8082/status/health` | Broker health | 200 | `localhost:8082` | `druid/broker` | | `http://localhost:8081/status/health` | Coordinator/Overlord health | 200 | `localhost:8081` | `druid/coordinator` | | `http://localhost:8083/status/health` | Historical health | 200 | `localhost:8083` | `druid/historical` | | `http://localhost:8091/status/health` | Middle Manager health | 200 | `localhost:8091` | `druid/middleManager` | | `http://localhost:8081/druid/coordinator/v1/isLeader` | Coordinator API direct | 200 | `localhost:8081` | `druid/coordinator` | | `http://localhost:8888/druid/coordinator/v1/isLeader` | Coordinator API via Router | 200 | `localhost:8081` | `druid/coordinator` | | `http://localhost:8081/druid/indexer/v1/isLeader` | Overlord API direct | 200 | `localhost:8081` | `druid/coordinator` | | `http://localhost:8888/druid/indexer/v1/isLeader` | Overlord API via Router | 200 | `localhost:8081` | `druid/coordinator` | | `http://localhost:8082/druid/v2/sql` | SQL direct to Broker | 200 | `localhost:8082` | `druid/broker` | | `http://localhost:8888/druid/v2/sql` | SQL via Router | 200 | `localhost:8082` | `druid/broker` | | `http://localhost:8082/druid/v2` | Native query direct to Broker | 200 | `localhost:8082` | `druid/broker` | | `http://localhost:8888/druid/v2` | Native query via Router | 200 | `localhost:8082` | `druid/broker` | | `http://localhost:8083/druid/v2` | Native query direct to Historical | 200 | `localhost:8083` | `druid/historical` | | `http://localhost:8888/status/health` | Router-generated `PATCH` rejection | 405 | `localhost:8888` | `druid/router` | | `http://localhost:8888/not-a-druid-endpoint` | Router-generated missing endpoint | 404 | `localhost:8888` | `druid/router` | The nano configuration runs Coordinator and Overlord in one process on port `8081` with `druid.service=druid/coordinator`, so requests to Overlord endpoints correctly report that process identity. #### Release note Druid can optionally return `X-Druid-Response-Server` and `X-Druid-Response-Service` on HTTP responses, allowing operators to identify the process that served a direct or Router-proxied request. Enable the feature with `druid.server.http.enableResponseIdentityHeaders=true` only for clients permitted to receive cluster topology information. <hr> ##### Key changed/added classes in this PR - `ResponseIdentityHeaderHandler` - `AsyncManagementForwardingServlet` - `AsyncQueryForwardingServlet` - `ResponseIdentityHeaderTest` <hr> This PR has: - [x] been self-reviewed. - [x] added documentation for new or modified features or behaviors. - [x] a release note entry in the PR description. - [x] added comments explaining the "why" and the intent of the code wherever it would not be obvious for an unfamiliar reader. - [x] added unit tests or modified existing tests to cover new code paths. - [x] added integration tests. - [x] been tested in a test Druid cluster. -- 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] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
