davsclaus commented on code in PR #26114:
URL: https://github.com/apache/camel/pull/26114#discussion_r3940537478


##########
components/camel-http-base/src/main/java/org/apache/camel/http/base/HttpHelper.java:
##########
@@ -135,6 +135,92 @@ public static boolean isStatusCodeOk(int statusCode, 
String okStatusCodeRange) {
         return HttpUtil.isStatusCodeOk(statusCode, okStatusCodeRange);
     }
 
+    /**
+     * Removes the leading portion of a request path that was matched by a 
consumer's registered path, so that what
+     * remains is the path relative to that consumer - the same way {@code 
camel-servlet}, {@code camel-jetty},
+     * {@code camel-netty-http} and {@code camel-undertow} already behave by 
default.
+     * <p/>
+     * This is a pure, defensive function: it never throws for malformed 
input, and whenever the match is anything less
+     * than a full, boundary-respecting match of every consumer path segment, 
it returns {@code requestPath} unchanged
+     * rather than risk producing a partial or incorrect result. In particular 
a {@code consumerPath} of {@code null},
+     * blank, {@code "/"} or {@code ""} (once normalized) is treated as "no 
prefix to strip" and always returns
+     * {@code requestPath} unchanged - this is what makes the platform-http 
{@code proxy} pseudo-path (whose consumer
+     * path is {@code "/"}) provably unaffected by callers of this method.
+     * <p/>
+     * The consumer path may contain REST-DSL style {@code {name}} placeholder 
segments, which match any single
+     * non-empty request segment.
+     *
+     * @param  requestPath  the incoming request path, e.g. {@code 
/reverse-proxy/get}
+     * @param  consumerPath the path the consumer is registered under, e.g. 
{@code /reverse-proxy} or
+     *                      {@code /reverse-proxy*}
+     * @return              the remaining path after stripping the matched 
consumer path, always starting with a
+     *                      {@code /}, or {@code requestPath} unchanged if the 
consumer path does not match (or there is
+     *                      nothing to strip)
+     */
+    public static String stripUriPrefix(String requestPath, String 
consumerPath) {
+        if (requestPath == null) {
+            return null;
+        }
+        if (consumerPath == null || consumerPath.isBlank()) {
+            return requestPath;
+        }
+
+        String normalized = consumerPath.trim();
+        if (!normalized.startsWith("/")) {
+            normalized = "/" + normalized;
+        }
+        if (normalized.endsWith("*")) {
+            normalized = normalized.substring(0, normalized.length() - 1);
+        }
+        while (normalized.length() > 1 && normalized.endsWith("/")) {
+            normalized = normalized.substring(0, normalized.length() - 1);
+        }
+        if (normalized.isEmpty() || "/".equals(normalized)) {
+            return requestPath;
+        }
+
+        // split using single char / is optimized in the jdk
+        final String[] consumerSegments = normalized.split("/");
+        final String[] requestSegments = requestPath.split("/", -1);
+
+        if (requestSegments.length < consumerSegments.length) {
+            return requestPath;
+        }
+
+        for (int i = 0; i < consumerSegments.length; i++) {
+            String consumerSegment = consumerSegments[i];
+            if (consumerSegment.isEmpty()) {
+                // leading empty segment produced by the split on the initial 
'/'
+                continue;
+            }
+            String requestSegment = i < requestSegments.length ? 
requestSegments[i] : null;
+            boolean placeholder = consumerSegment.startsWith("{") && 
consumerSegment.endsWith("}");
+            if (placeholder) {
+                if (requestSegment == null || requestSegment.isEmpty()) {
+                    return requestPath;
+                }
+            } else if (requestSegment == null || 
!consumerSegment.equalsIgnoreCase(requestSegment)) {

Review Comment:
   Using `equalsIgnoreCase` here creates a documented guarantee that literal 
path segments are matched case-insensitively. In practice this branch is 
unreachable via `camel-platform-http-vertx`: the Vert.x router performs 
case-sensitive path matching, so the consumer registered at `/reverse-proxy` 
will never receive a request whose path segment differs in case. Keeping it as 
`equals` would match the actual router behaviour and avoid creating a contract 
that future callers of this helper (from engines with case-sensitive routing) 
would have to think about. Happy to leave it if you prefer the defensive 
approach, but it's worth a conscious decision.



##########
components/camel-platform-http-vertx/pom.xml:
##########
@@ -42,6 +42,10 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-platform-http</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-http-base</artifactId>

Review Comment:
   `camel-http-base` is already a direct dependency of `camel-platform-http`, 
which `camel-platform-http-vertx` depends on, so this declaration is resolved 
transitively without it. Keeping it explicit is a style call (it does make the 
dependency visible in this module's POM), but Camel's convention generally 
avoids redundant explicit deps. Worth double-checking whether you'd like to 
keep it or rely on the transitive resolution.



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