[ 
https://issues.apache.org/jira/browse/CAMEL-25854?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18131930#comment-18131930
 ] 

Claus Ibsen commented on CAMEL-25854:
-------------------------------------

Fixed by https://github.com/apache/camel/pull/28377 (merged as 7d2bac0a5239).

_Claude Code on behalf of davsclaus_

> camel-undertow - rest-dsl and plain undertow consumers on the same port: only 
> the kind that registers first is served, and stopping the last consumer of 
> one kind stops the server for the other
> ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25854
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25854
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-undertow
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>             Fix For: 4.24.0
>
>
> {{DefaultUndertowHost}} (main 20cdb309f7d0) runs one Undertow server per host 
> and port for the consumers of the component. It has two handlers: 
> {{RestRootHandler}} for the rest-dsl consumers and {{CamelRootHandler}} for 
> the plain {{undertow:}} endpoints. The server is given only one of them, 
> chosen from the first consumer that registers on the port:
> {code:java}
> // use the rest handler as its a rest consumer
> serverHandler = consumer != null && consumer.isRest() ? restHandler : 
> rootHandler;
> {code}
> A later consumer of the other kind is still added to its own handler 
> ({{registerHandler}}, the last if/else), but the server never calls that 
> handler. Its route starts normally and logs nothing, and every request to it 
> gets 404 "No matching path found". For example, take 
> {{restConfiguration().component("undertow").port(8080)}} with 
> {{rest("/users").get("{id}")}} next to 
> {{from("undertow:http://0.0.0.0:8080/health";)}}. Only the kind whose route 
> starts first is served. A plain route usually starts first, because routes 
> built from the rest-dsl are added after the plain routes of the same builder, 
> so the REST API is the part that answers 404.
> {{unregisterHandler}} also checks only one kind: it stops the server when the 
> kind of the consumer being removed has no consumer left 
> ({{restHandler.consumers() <= 0}} or {{rootHandler.isEmpty()}}), even if 
> consumers of the other kind are still registered. Stopping or reloading the 
> last REST route therefore stops the server under the started plain undertow 
> routes, and the reverse also happens. Their clients get connection refused 
> until those routes are restarted.
> *Fix*: the server always calls the handler of the plain endpoints. Its 
> default handler (used when no plain endpoint matches) is now the rest-dsl 
> handler instead of {{NotFoundHandler}}. The rest-dsl handler answers 404 "No 
> matching path found" (the same response as {{NotFoundHandler}}), or 405 when 
> none of its consumers matches either. The server stops only when neither kind 
> has a consumer left. When a path is served by both a plain endpoint and a 
> rest-dsl consumer, the plain endpoint takes it: a setup whose rest-dsl 
> consumers registered first and that has a plain endpoint overlapping their 
> paths (for example {{matchOnUriPrefix=true}} on {{/}}) can notice it, so 
> there is a note in the 4.24 upgrade guide. Undertow keeps a plain endpoint on 
> {{/}} with {{matchOnUriPrefix=true}} as the default handler of its path 
> handler and leaves no default handler when it is removed; 
> {{CamelPathHandler}} now puts its default handler back then, so the rest-dsl 
> consumers are served again once such an endpoint stops. A plain endpoint with 
> a path template (such as {{/api/{name}}}) registers a template handler on the 
> static part of its path ({{/api}}); a request under it that no template 
> matches, while no plain endpoint has that static path, now goes on to the 
> rest-dsl consumers (404 when none matches) instead of getting 405 from the 
> template handler's empty default; this also keeps the rest-dsl consumers of 
> the port served next to a template on {{/}} (such as {{/{file}}}).
> *Tests*: new {{RestUndertowAndPlainConsumerSamePortTest}} (a rest-dsl GET 
> {{/users/{id}}} and a plain {{undertow:http://localhost:port/plain}} on the 
> same port). On main the first 4 tests fail. {{testBothKindsAreServed}} and 
> {{testPlainConsumerAddedAfterRestConsumer}} fail with {{/users/123 ==> 
> expected: <200> but was: <404>}}. {{testServerKeepsServingWhenOneKindStops}} 
> stops the REST route and then calls {{/plain}}, which fails with {{expected: 
> <200> but was: <null>}} because the server was stopped and the connection was 
> refused. {{testPlainConsumerOnRootTakesThePathsUntilItStops}} adds a plain 
> endpoint on {{/}} with {{matchOnUriPrefix=true}} (it takes {{/users/123}}) 
> and stops it; without the {{CamelPathHandler}} change {{/users/123}} then 
> gets 404. {{testRestPathUnderTheBaseOfAPlainTemplatePath}} (a plain 
> {{/api/{name}}} next to a rest-dsl {{/api/orders/{id}}}) and 
> {{testPlainTemplatePathOnRootKeepsTheRestConsumers}} (a plain {{/{file}}}) 
> fail without the template fallback with {{/api/orders/1 ==> expected: <200> 
> but was: <405>}} and {{/users/123 ==> expected: <200> but was: <405>}}. With 
> the fix all 6 pass, and the camel-undertow unit tests run 241 tests with 0 
> failures (1 skipped).
> *How it was found*: a review of shared per-port server state in the HTTP 
> consumer components, after the per-owner resource fixes CAMEL-25849 and 
> CAMEL-25850. The JUnit test above confirmed it.
> *Affected*: main, camel-4.23.x, camel-4.22.x and camel-4.18.x all have the 
> same handler choice and the same stop condition in {{DefaultUndertowHost}}. 
> This was checked by reading the code, not by running it.
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to