This is an automated email from the ASF dual-hosted git repository.

Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new f897a5c647 fix(plugin): prefer specific metadata path patterns (#7086)
f897a5c647 is described below

commit f897a5c647a7331233b38548838032e2f4fccdaa
Author: Liming Deng <[email protected]>
AuthorDate: Wed Sep 30 09:57:33 2026 +0800

    fix(plugin): prefer specific metadata path patterns (#7086)
    
    * fix(plugin): prefer specific metadata path patterns
    
    * fix(plugin): invalidate cached wildcard matches
---
 .../shenyu/plugin/base/cache/MetaDataCache.java    |  7 ++-
 .../shenyu/plugin/base/utils/PathMatchUtils.java   | 12 +++++
 .../plugin/base/cache/MetaDataCacheTest.java       | 55 ++++++++++++++++++++++
 3 files changed, 73 insertions(+), 1 deletion(-)

diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MetaDataCache.java
 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MetaDataCache.java
index 70d6725844..344fa049ca 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MetaDataCache.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/cache/MetaDataCache.java
@@ -97,6 +97,11 @@ public final class MetaDataCache {
     }
 
     private void clean(final String key) {
+        if (key.contains("*")) {
+            CACHE.clear();
+            MAPPING.clear();
+            return;
+        }
         // springCloud and divide are needs to be cleaned
         Optional.ofNullable(MAPPING.get(key))
                 .ifPresent(paths -> {
@@ -125,7 +130,7 @@ public final class MetaDataCache {
                     final MetaData value = META_DATA_MAP.values()
                             .stream()
                             .filter(data -> data.getEnabled() && 
PathMatchUtils.match(data.getPath(), path))
-                            .findFirst()
+                            .min((left, right) -> 
PathMatchUtils.compare(left.getPath(), right.getPath(), path))
                             .orElse(null);
                     final String metaPath = Optional.ofNullable(value)
                             .map(MetaData::getPath)
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/PathMatchUtils.java
 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/PathMatchUtils.java
index e69c062200..e3041780b9 100644
--- 
a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/PathMatchUtils.java
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/utils/PathMatchUtils.java
@@ -54,6 +54,18 @@ public class PathMatchUtils {
     public static boolean match(final String matchUrls, final String realPath) 
{
         return MATCHER.match(matchUrls, realPath);
     }
+
+    /**
+     * Compare two path patterns for a concrete path.
+     *
+     * @param left the left path pattern
+     * @param right the right path pattern
+     * @param realPath the concrete path
+     * @return a negative value when left is more specific
+     */
+    public static int compare(final String left, final String right, final 
String realPath) {
+        return MATCHER.getPatternComparator(realPath).compare(left, right);
+    }
     
     /**
      * Path pattern boolean.
diff --git 
a/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/cache/MetaDataCacheTest.java
 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/cache/MetaDataCacheTest.java
new file mode 100644
index 0000000000..a7e6b43690
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-base/src/test/java/org/apache/shenyu/plugin/base/cache/MetaDataCacheTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.base.cache;
+
+import org.apache.shenyu.common.dto.MetaData;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+class MetaDataCacheTest {
+
+    private final MetaDataCache cache = MetaDataCache.getInstance();
+
+    @AfterEach
+    void tearDown() {
+        cache.getMetaDataMap().clear();
+        cache.getMetaDataCache().clear();
+    }
+
+    @Test
+    void shouldPreferMostSpecificMatchingPattern() {
+        MetaData broad = createMetaData("p", "/api/**");
+        MetaData specific = createMetaData("a", "/api/users/**");
+        cache.cache(broad);
+        assertSame(broad, cache.obtain("/api/users/42"));
+
+        cache.cache(specific);
+
+        assertSame(specific, cache.obtain("/api/users/42"));
+    }
+
+    private MetaData createMetaData(final String id, final String path) {
+        MetaData metaData = new MetaData();
+        metaData.setId(id);
+        metaData.setPath(path);
+        metaData.setEnabled(true);
+        return metaData;
+    }
+}

Reply via email to