shashank created CAMEL-26083:
--------------------------------

             Summary: camel-support - RestConsumerContextPathMatcher: stopping 
one consumer of a wildcard path stops the wildcard matching of every other 
consumer with the same path
                 Key: CAMEL-26083
                 URL: https://issues.apache.org/jira/browse/CAMEL-26083
             Project: Camel
          Issue Type: Bug
          Components: camel-netty-http, camel-servlet, camel-support, 
camel-undertow
            Reporter: shashank
            Assignee: shashank


{{RestConsumerContextPathMatcher}} keeps the compiled regex of each wildcard 
consumer path in a static map keyed only by the path string ({{PATH_PATTERN}}, 
main 6a2f66ddec3e line 43). {{register(path)}} puts it, {{unRegister(path)}} 
removes it (lines 245-272), and {{matchWildCard}} returns false for a path 
without a pattern (line 388), the last step of {{matchBestPath}}. The map is 
one per JVM, so all consumers with the same path share one entry: the same 
wildcard path for two HTTP methods ({{GET /files/*}} and {{POST /files/*}}), on 
two ports, in two CamelContexts or two components. Stopping, suspending 
(netty-http with {{send503whenSuspended=false}}), removing or reloading one of 
them removes the pattern for all: every other consumer of that path, still 
started, no longer matches. Its requests get 404, or are routed to a broader 
wildcard consumer of the same server ({{/*}}). Callers: netty-http 
{{HttpServerMultiplexChannelHandler}}, servlet/jetty 
{{CamelServlet.connect/disconnect}} (camel-http-common), undertow 
{{RestRootHandler}}.

*Fix*: each entry counts the consumers that registered the path; {{unRegister}} 
removes the pattern only when no consumer is left 
({{ConcurrentHashMap.compute}}/{{computeIfPresent}}). Compiling on demand was 
not chosen, as it would change matching for camel-rest-openapi and 
camel-rest-postman, which call {{matchBestPath}} without registering. 
{{CamelServlet.disconnect}} (servlet, jetty) now unregisters only when 
{{consumers.remove(endpointUri, consumer)}} removed this consumer: with an 
{{httpRegistry}} shared by servlets of different names, 
{{CamelHttpTransportServlet.connect}} registers a consumer only in the servlet 
of its name while {{disconnect}} ran for every servlet, and a connect refused 
as "Duplicate request path" was followed by a {{disconnect}} that unregistered 
a path it never registered (and removed the other consumer's map entry).

*Tests*: new {{NettyHttpTwoRoutesSameWildcardPathStopOneRouteTest}}, 2 tests, 
both fail on main ({{expected: <post> but was: <>}} after stopping the GET 
route of the same path; {{expected: <other-port> but was: <catch-all>}} after 
stopping the same path on another port); new 
{{ServletSharedHttpRegistryWildcardPathTest}} (shared {{httpRegistry}} with 
servlets {{a}} and {{b}}; stop one of two consumers of a path; a duplicate 
consumer), 2 tests, fail on main and with only the matcher change; new 
{{RestConsumerContextPathMatcherTest#wildcardPathStaysRegisteredWhileAnotherConsumerUsesIt}}
 fails on main ({{expected: not <null>}}). Unit tests with the fix: 
camel-netty-http 316 run, 0 failures, 8 skipped; camel-servlet 112 run, 0 
failures, 2 skipped; camel-http-common 48 run, 0 failures.

*How it was found*: spec mining of {{RestConsumerContextPathMatcherTest}} and a 
stateful lifecycle-sequence harness over HTTP consumers sharing a server.

*Affected*: main, camel-4.22.x, camel-4.18.x and camel-4.14.x (same code). 
Read, not run.

_Filed with Claude Code on behalf of allthingssecurity._



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

Reply via email to