[
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)