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]

Reply via email to