diff --git a/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java b/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
index bda24e6bc0d99..6b45e375f6799 100644
--- a/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
+++ b/core/camel-support/src/main/java/org/apache/camel/support/RestConsumerContextPathMatcher.java
@@ -16,21 +16,16 @@
*/
package org.apache.camel.support;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.OptionalInt;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
* A context path matcher when using rest-dsl that allows components to reuse the same matching logic.
*
- * The component should use the {@link #matchBestPath(String, String, java.util.List)} with the request details and the
- * matcher returns the best matched, or null if none could be determined.
+ * The component should use the {@link #matchBestPath(String, String, List)} with the request details and the matcher
+ * returns the best matched, or null if none could be determined.
*
* The {@link ConsumerPath} is used for the components to provide the details to the matcher.
*/
@@ -156,9 +151,9 @@ T> ConsumerPath matchBestPath(String requestMethod, String requestPath, List<
}
}
- // if there are no wildcards, then select the matching with the longest path
- boolean noWildcards = candidates.stream().allMatch(p -> countWildcards(p.getConsumerPath()) == 0);
- if (noWildcards) {
+ // if there are no uri template, then select the matching with the longest path
+ boolean noCurlyBraces = candidates.stream().allMatch(p -> countCurlyBraces(p.getConsumerPath()) == 0);
+ if (noCurlyBraces) {
// grab first which is the longest that matched the request path
answer = candidates.stream()
.filter(c -> matchPath(requestPath, c.getConsumerPath(), c.isMatchOnUriPrefix()))
@@ -172,6 +167,17 @@ T> ConsumerPath matchBestPath(String requestMethod, String requestPath, List<
// then match by wildcard path
it = candidates.iterator();
+ while (it.hasNext()) {
+ ConsumerPath consumer = it.next();
+ // filter non matching paths
+ if (matchWildCard(requestPath, consumer.getConsumerPath())) {
+ answer = consumer;
+ break;
+ }
+ }
+
+ // then match by uri template path
+ it = candidates.iterator();
while (it.hasNext()) {
ConsumerPath> consumer = it.next();
// filter non matching paths
@@ -180,16 +186,16 @@ T> ConsumerPath matchBestPath(String requestMethod, String requestPath, List<
}
}
- // if there is multiple candidates with wildcards then pick anyone with the least number of wildcards
+ // if there is multiple candidates with uri template then pick anyone with the least number of uri template
ConsumerPath best = null;
Map>> pathMap = new HashMap<>();
if (candidates.size() > 1) {
it = candidates.iterator();
while (it.hasNext()) {
ConsumerPath entry = it.next();
- int wildcards = countWildcards(entry.getConsumerPath());
- if (wildcards > 0) {
- List> consumerPathsLst = pathMap.computeIfAbsent(wildcards, key -> new ArrayList<>());
+ int curlyBraces = countCurlyBraces(entry.getConsumerPath());
+ if (curlyBraces > 0) {
+ List> consumerPathsLst = pathMap.computeIfAbsent(curlyBraces, key -> new ArrayList<>());
consumerPathsLst.add(entry);
}
}
@@ -206,12 +212,12 @@ T> ConsumerPath matchBestPath(String requestMethod, String requestPath, List<
}
if (best != null) {
- // pick the best among the wildcards
+ // pick the best among uri template
answer = best;
}
}
- // if there is one left then its our answer
+ // if there is one left then it's our answer
if (answer == null && candidates.size() == 1) {
answer = candidates.get(0);
}
@@ -257,10 +263,10 @@ private static boolean isOptionsMethod(String method) {
* Matches the given request path with the configured consumer path
*
* @param requestPath the request path
- * @param consumerPath the consumer path which may use { } tokens
+ * @param isUriTemplate the consumer path which may use { } tokens
* @return true if matched, false otherwise
*/
- private static boolean matchRestPath(String requestPath, String consumerPath, boolean wildcard) {
+ private static boolean matchRestPath(String requestPath, String consumerPath, boolean isUriTemplate) {
// deal with null parameters
if (requestPath == null && consumerPath == null) {
return true;
@@ -297,7 +303,7 @@ private static boolean matchRestPath(String requestPath, String consumerPath, bo
String p1 = requestPaths[i];
String p2 = consumerPaths[i];
- if (wildcard && p2.startsWith("{") && p2.endsWith("}")) {
+ if (isUriTemplate && p2.startsWith("{") && p2.endsWith("}")) {
// always matches
continue;
}
@@ -312,13 +318,13 @@ private static boolean matchRestPath(String requestPath, String consumerPath, bo
}
/**
- * Counts the number of wildcards in the path
+ * Counts the number of uri template's curlyBraces in the path
*
* @param consumerPath the consumer path which may use { } tokens
- * @return number of wildcards, or 0 if no wildcards
+ * @return number of curlyBraces, or 0 if no curlyBraces
*/
- private static int countWildcards(String consumerPath) {
- int wildcards = 0;
+ private static int countCurlyBraces(String consumerPath) {
+ int curlyBraces = 0;
// remove starting/ending slashes
if (consumerPath.startsWith("/")) {
@@ -331,11 +337,31 @@ private static int countWildcards(String consumerPath) {
String[] consumerPaths = consumerPath.split("/");
for (String p2 : consumerPaths) {
if (p2.startsWith("{") && p2.endsWith("}")) {
- wildcards++;
+ curlyBraces++;
}
}
- return wildcards;
+ return curlyBraces;
+ }
+
+ private static boolean matchWildCard(String requestPath, String consumerPath) {
+ if (!requestPath.endsWith("/")) {
+ requestPath = requestPath + "/";
+ }
+ // Convert URI template to a regex pattern
+ String regex = consumerPath
+ .replace("/", "\\/")
+ .replace("{", "(?<")
+ .replace("}", ">[^\\/]+)");
+
+ // Add support for wildcard * as path suffix
+ regex = regex.replace("*", ".*");
+
+ // Match the provided path against the regex pattern
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(requestPath);
+
+ return matcher.matches();
}
}