allthingssecurity opened a new pull request, #28811: URL: https://github.com/apache/camel/pull/28811
# Description [CAMEL-26432](https://issues.apache.org/jira/browse/CAMEL-26432) Follow-up of CAMEL-26418 (#28754), under CAMEL-26330, asked for in its review. CAMEL-26418 added `error status=<code>` for the HTTP components, so that a fault looks like the HTTP status a real server returns. For `netty-http` such a rule was rejected (`status= is not supported yet for netty-http`), because `NettyHttpOperationFailedException` takes a Netty `HttpContent` for the body, and camel-chaos had no test with camel-netty-http on the classpath. This PR supports it, as the JIRA proposes and as `design/chaos.adoc` already says ("`NettyHttpOperationFailedException` for camel-netty-http"). ## Matching netty-http (and undertow) endpoints camel-netty-http gives its endpoints the URI of their address: a route that sends to `netty-http:http://inventory/stock` has an endpoint whose `getEndpointUri()` is `http://inventory/stock` (`NettyHttpComponent.createEndpoint` builds it from the remaining part). camel-undertow does the same (`undertow:http://inventory/stock` has the endpoint URI `http://inventory/stock`). Chaos matched rules against that URI, so on main: - a `component=netty-http` or `endpoint=netty-http:...` rule never matched a netty-http endpoint, for any fault (not only `status`); - a `component=http` or `endpoint=http:...` rule matched netty-http endpoints, and a `status` rule then raised the `HttpOperationFailedException` of camel-http-base (camel-netty-http depends on camel-http-base) with the message changes of camel-http, instead of the failure of camel-netty-http; - the same for undertow: the undertow part of CAMEL-26418 (`component=undertow` with `status`) never matched a real undertow endpoint, and `component=http` rules took undertow endpoints for camel-http ones. Its tests did not show it, as the fake component that stands for undertow in `ChaosHttpFaultTest` kept `undertow:` in its endpoint URI, which the real component does not. Chaos now matches an endpoint by `ChaosPatterns.endpointUri(endpoint)`: the endpoint URI, unless its scheme is not a name of the endpoint's component in the context (`context.hasComponent(scheme) != endpoint.getComponent()`), in which case the component's default name (`Component.getDefaultName()`, `netty-http`) is put in front: `netty-http:http://inventory/stock`. The send hook and the poll strategy compute it once per send or poll (only when there are rules for that hook) and give it to `ChaosRule.matchesUri`; the HTTP fault uses it too. It fixes undertow as well: `undertow:http://inventory/stock` is matched as `undertow:http://inventory/stock`. For endpoints whose URI starts with the name their component has in the context (camel-http, `https`, vertx-http, direct, seda, kafka, a component bound under its own name) the URI is unchanged. The name put in front is the default name of the component, not the name it has in the context: a camel-netty-http component added as `nh` is ma tched as `netty-http:...` (test below). camel-chaos is new in 4.24 (not released yet), so no upgrade guide entry. The cost is one substring (the scheme) and one map lookup of the context per send or poll with rules, plus one concatenated string for these components. `ChaosConsumers` (which consumers keep a failed message, by scheme: file, ftp, jms, kafka) still reads the scheme of the endpoint URI; none of its schemes has this case. A component added under a name of its own (`jms-a`, `myhttp`) is still not recognised there, nor by `status=` (which takes the component name of the rule); that is for a follow-up JIRA I will file (use the default name of the component there too). ## What the fault does for netty-http It mirrors what the producer of camel-netty-http does for a response with that status (`NettyHttpProducer.NettyHttpProducerCallback` and `NettyHttpHelper.populateNettyHttpOperationFailedException`). The producer is not called. - The failure is a `NettyHttpOperationFailedException(uri, statusCode, statusText, location, content)`, where the content is a Netty `DefaultFullHttpResponse` (HTTP/1.1) with the status and its reason phrase, the `header.*` values of the rule as its headers, and the `body` of the rule (empty without it). The real producer passes its `FullHttpResponse` there too, so `getHttpContent()` (deprecated) is a `FullHttpResponse` and `getContentAsString()` is the body. The status text is the standard reason phrase, as for the other HTTP components (`Service Unavailable` for 503, empty for a less common status), the location is the `Location` header of the rule, and the uri is the endpoint base uri without its options, as for the other HTTP components; for netty-http that is the address (`http://host:port/path`), which is also what the real producer puts there (the url of its request) when the address has no query and no `CamelHttpUri`/`CamelHttpPath`/`CamelHttpQuery` header changes it. The location is now given only for a 3xx status, for every HTTP component, as camel-http and camel-netty-http do (before, a `header.Location` of a 503 rule became the redirect location of the failure). The body is wrapped in an unpooled heap buffer (`Unpooled.wrappedBuffer`), which is not tracked by the Netty leak detector and needs no release. - The message: camel-netty-http replaces the message with the response before it decides to fail, so the message gets the response, as chaos does for undertow, but with the reason phrase (camel-netty-http sets `CamelHttpResponseText` from the response status): `CamelHttpResponseCode`, `CamelHttpResponseText` (when there is a reason phrase; a text from an earlier response is removed), the `header.*` values, and the `body`. Chaos keeps the request headers, as for undertow. - With `throwExceptionOnFailure=false`, or an `okStatusCodeRange` that has the status, the response is returned instead, as for the other HTTP components. The options are read through the endpoint configurer of camel-netty-http (`NettyHttpEndpointConfigurer` reads them from the `NettyHttpConfiguration` of the endpoint). - The netty-http types stay optional in camel-chaos: they are loaded through the class resolver of the context only when a `status` rule fires at a `netty-http` endpoint, as the `HttpOperationFailedException` of camel-http-base already is. camel-netty-http is a test dependency only. Not mirrored: `transferException=true` (a server that sends a serialized Java exception as the body) is a server reply, not a status; a chaos rule cannot send one. ## Changes - `ChaosRuleParser`: `netty-http` is one of the HTTP schemes of `status=`; the list of HTTP components whose `status=` was not supported yet (only netty-http) and its check are removed, so the error for a component that is not HTTP lists netty-http with the others. - `ChaosPatterns.endpointUri`, used by `ChaosSendHook`, `ChaosPollStrategy` (through `ChaosRule.matchesUri`, which replaces `matchesEndpoint`) and `ChaosFaults`: the matching above. - `ChaosFaults`: the location only for a 3xx status; a value of the rule that a component refuses (Netty validates header values: a leading space is refused) fails the send with a `ChaosException` whose cause is that refusal, not the `InvocationTargetException` of the reflection. - `ChaosFaults`: the netty-http failure and message, as above. - `chaos.adoc` (and its catalog copy): the paragraph of `status`, without "netty-http is not supported yet". - `pom.xml`: camel-netty-http as a test dependency. No upgrade guide entry: camel-chaos is not released yet; a rule that was rejected is now accepted. `design/chaos.adoc` on main already names `NettyHttpOperationFailedException` for camel-netty-http. The open #28788 (camel-chaos-control) adds a sentence there that `status` is not supported yet for netty-http (CAMEL-26432): whichever of the two PRs merges second removes that sentence (if #28788 merges first, I rebase this PR and remove it here). ## Tests New `ChaosNettyHttpFaultTest` (AssertJ, as the module, 11 tests), with the real camel-netty-http component and endpoints on a port where nothing listens (the producer is not called; the producer connects lazily, so starting the routes opens no connection): - `statusRaisesTheNettyHttpOperationFailedException`: status, status text, content, not a redirect, uri, the `FullHttpResponse` (status, reason phrase, header), the message (code, text, header, body, and the request header kept), the rule fired once at the send; - `withoutBodyTheContentIsEmpty`, `locationHeaderIsTheRedirectLocation` (302), `aLessCommonStatusHasNoReasonPhrase` (418, and an earlier `CamelHttpResponseText` removed); - `withoutThrowExceptionOnFailureTheResponseIsReturned`, `aStatusInTheOkRangeOfTheEndpointIsAResponse` (`okStatusCodeRange=200-299,503` gives the response, the same rule fails a send to an endpoint without it); - `aComponentUnderANameOfItsOwnIsMatchedByItsDefaultName` (a NettyHttpComponent added as `nh`: `component=nh` does not match, `component=netty-http` fires), `aLocationIsARedirectLocationOnlyForARedirect` (503 with a `Location` header), `aHeaderValueThatNettyRefusesFailsTheSendWithItsReason`; - `nettyHttpEndpointsAreMatchedByTheirComponent`: a `component=http` and an `endpoint=http://localhost:9/*` rule do not match the netty-http endpoint (0 matches), an `endpoint=netty-http:http://localhost:9/*` rule fires; - `onExceptionOfTheRouteHandlesTheFailure`: a route with `onException(NettyHttpOperationFailedException.class).handled(true)` handles it, and `CamelExceptionCaught` has the status. `ChaosHttpFaultTest`: the fake component that stands for undertow now has the default name `undertow` and gives its endpoints the URI of their address, as `UndertowComponent` does, so the undertow tests go through the matching above (they fail with the matching of main). `ChaosRuleParserTest` (one line of the `@CsvSource` next to the changed one is re-indented by the formatter): the two cases that expected the rejection are replaced by accepted rules (`endpoint=netty-http:...` and `component=netty-http` with `status`), and the error for a component that is not HTTP lists netty-http. Without the change (main's `ChaosFaults`, `ChaosRuleParser`, `ChaosRule`, `ChaosPatterns`, `ChaosSendHook`, `ChaosPollStrategy`), the 11 tests of `ChaosNettyHttpFaultTest`, 2 of `ChaosRuleParserTest` and the undertow test of `ChaosHttpFaultTest` (with the faithful undertow fake) fail; with only the matching reverted (the endpoint URI as before), the 11 netty-http tests and the undertow test fail. - `ChaosNettyHttpFaultTest` and `ChaosHttpFaultTest` 20 times in one JVM: 400 tests, 0 failures. - camel-chaos tests: 264 tests, 0 failures. - The branch merges cleanly with main, with #28788 (camel-chaos-control) and with the 4b MCP branch stacked on it (see the design doc note above). - Formatter and import-sort: no changes; `chaos.adoc` copied to the catalog (identical). # Target - [x] I checked that the commit is targeting the correct branch (Camel 4 uses the `main` branch) # Tracking - [x] If this is a large change, bug fix, or code improvement, I checked there is a [JIRA issue](https://issues.apache.org/jira/browse/CAMEL-26432) filed for the change (usually before you start working on it): [CAMEL-26432](https://issues.apache.org/jira/browse/CAMEL-26432). # Apache Camel coding standards and style - [x] I checked that each commit in the pull request has a meaningful subject line and body. - [ ] I have run `mvn clean install -DskipTests` locally from root folder and I have committed all auto-generated changes. (I built camel-chaos with the modules on its test classpath and ran its tests, including the formatter and import-sort plugins, and copied `chaos.adoc` to the catalog. I did not run the full root build.) # AI-assisted contributions - [x] If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., `Co-authored-by` trailers) and the PR description identifies the AI tool used. This PR was prepared with Claude Code (Claude Opus 5.5). The commit carries a `Co-Authored-By` trailer. _Claude Code on behalf of allthingssecurity_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- 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]
