You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by xi...@apache.org on 2022/06/18 13:29:19 UTC

[incubator-shenyu] branch master updated: What needs to be dealt with here is the and condition. If the number of and conditions is the same and is matched at the same time, (#3579)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new dfec52dee What needs to be dealt with here is the and condition. If the number of and conditions is the same and is matched at the same time, (#3579)
dfec52dee is described below

commit dfec52deeb5e5d5da0649383855551e59bdadb60
Author: Sixh-PrFor <ch...@163.com>
AuthorDate: Sat Jun 18 21:29:12 2022 +0800

    What needs to be dealt with here is the and condition. If the number of and conditions is the same and is matched at the same time, (#3579)
    
    it will be sorted by the sort field.
---
 .../apache/shenyu/common/enums/MatchModeEnum.java  | 28 +++++++----
 .../shenyu/plugin/base/AbstractShenyuPlugin.java   | 55 ++++++++++++++++------
 2 files changed, 61 insertions(+), 22 deletions(-)

diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/MatchModeEnum.java b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/MatchModeEnum.java
index ef8de61cb..7856456e0 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/enums/MatchModeEnum.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/enums/MatchModeEnum.java
@@ -18,26 +18,27 @@
 package org.apache.shenyu.common.enums;
 
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * MatchModeEnum.
  */
 public enum MatchModeEnum {
-
+    
     /**
      * And match mode enum.
      */
     AND(0, "and"),
-
+    
     /**
      * Or match mode enum.
      */
     OR(1, "or");
-
+    
     private final int code;
-
+    
     private final String name;
-
+    
     /**
      * all args constructor.
      *
@@ -48,7 +49,7 @@ public enum MatchModeEnum {
         this.code = code;
         this.name = name;
     }
-
+    
     /**
      * get code.
      *
@@ -57,7 +58,7 @@ public enum MatchModeEnum {
     public int getCode() {
         return code;
     }
-
+    
     /**
      * get name.
      *
@@ -66,7 +67,18 @@ public enum MatchModeEnum {
     public String getName() {
         return name;
     }
-
+    
+    /**
+     * Judgment code and enum eq.
+     *
+     * @param code          code.
+     * @param matchModeEnum enum
+     * @return true or false.
+     */
+    public static boolean match(final Integer code, final MatchModeEnum matchModeEnum) {
+        return Objects.equals(matchModeEnum.getCode(), code);
+    }
+    
     /**
      * get match mode name by code.
      *
diff --git a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/AbstractShenyuPlugin.java b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/AbstractShenyuPlugin.java
index 185b06198..20b9211b1 100644
--- a/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/AbstractShenyuPlugin.java
+++ b/shenyu-plugin/shenyu-plugin-base/src/main/java/org/apache/shenyu/plugin/base/AbstractShenyuPlugin.java
@@ -18,9 +18,11 @@
 package org.apache.shenyu.plugin.base;
 
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.shenyu.common.dto.PluginData;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.enums.MatchModeEnum;
 import org.apache.shenyu.common.enums.SelectorTypeEnum;
 import org.apache.shenyu.plugin.api.ShenyuPlugin;
 import org.apache.shenyu.plugin.api.ShenyuPluginChain;
@@ -32,16 +34,20 @@ import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
 
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * abstract shenyu plugin please extends.
  */
 public abstract class AbstractShenyuPlugin implements ShenyuPlugin {
-
+    
     private static final Logger LOG = LoggerFactory.getLogger(AbstractShenyuPlugin.class);
-
+    
     /**
      * this is Template Method child has Implement your own logic.
      *
@@ -52,7 +58,7 @@ public abstract class AbstractShenyuPlugin implements ShenyuPlugin {
      * @return {@code Mono<Void>} to indicate when request handling is complete
      */
     protected abstract Mono<Void> doExecute(ServerWebExchange exchange, ShenyuPluginChain chain, SelectorData selector, RuleData rule);
-
+    
     /**
      * Process the Web request and (optionally) delegate to the next
      * {@code ShenyuPlugin} through the given {@link ShenyuPluginChain}.
@@ -94,21 +100,42 @@ public abstract class AbstractShenyuPlugin implements ShenyuPlugin {
         }
         return chain.execute(exchange);
     }
-
+    
     protected Mono<Void> handleSelectorIfNull(final String pluginName, final ServerWebExchange exchange, final ShenyuPluginChain chain) {
         return chain.execute(exchange);
     }
-
+    
     protected Mono<Void> handleRuleIfNull(final String pluginName, final ServerWebExchange exchange, final ShenyuPluginChain chain) {
         return chain.execute(exchange);
     }
-
+    
     private SelectorData matchSelector(final ServerWebExchange exchange, final Collection<SelectorData> selectors) {
-        return selectors.stream()
-                .filter(selector -> selector.getEnabled() && filterSelector(selector, exchange))
-                .findFirst().orElse(null);
+        List<SelectorData> filterCollectors = selectors.stream()
+                .filter(selector -> selector.getEnabled() && filterSelector(selector, exchange)).collect(Collectors.toList());
+        if (filterCollectors.size() > 1) {
+            return manyMatchSelector(filterCollectors);
+        } else {
+            return filterCollectors.stream().findFirst().orElse(null);
+        }
     }
-
+    
+    private SelectorData manyMatchSelector(final List<SelectorData> filterCollectors) {
+        //What needs to be dealt with here is the and condition. If the number of and conditions is the same and is matched at the same time,
+        // it will be sorted by the sort field.
+        Map<Integer, List<Pair<Integer, SelectorData>>> collect =
+                filterCollectors.stream().map(selector -> {
+                    boolean match = MatchModeEnum.match(selector.getMatchMode(), MatchModeEnum.AND);
+                    int sort = 0;
+                    if (match) {
+                        sort = selector.getConditionList().size();
+                    }
+                    return Pair.of(sort, selector);
+                }).collect(Collectors.groupingBy(Pair::getLeft));
+        Integer max = Collections.max(collect.keySet());
+        List<Pair<Integer, SelectorData>> pairs = collect.get(max);
+        return pairs.stream().map(Pair::getRight).min(Comparator.comparing(SelectorData::getSort)).orElse(null);
+    }
+    
     private Boolean filterSelector(final SelectorData selector, final ServerWebExchange exchange) {
         if (selector.getType() == SelectorTypeEnum.CUSTOM_FLOW.getCode()) {
             if (CollectionUtils.isEmpty(selector.getConditionList())) {
@@ -118,21 +145,21 @@ public abstract class AbstractShenyuPlugin implements ShenyuPlugin {
         }
         return true;
     }
-
+    
     private RuleData matchRule(final ServerWebExchange exchange, final Collection<RuleData> rules) {
         return rules.stream().filter(rule -> filterRule(rule, exchange)).findFirst().orElse(null);
     }
-
+    
     private Boolean filterRule(final RuleData ruleData, final ServerWebExchange exchange) {
         return ruleData.getEnabled() && MatchStrategyFactory.match(ruleData.getMatchMode(), ruleData.getConditionDataList(), exchange);
     }
-
+    
     private void selectorLog(final SelectorData selectorData, final String pluginName) {
         if (selectorData.getLogged()) {
             LOG.info("{} selector success match , selector name :{}", pluginName, selectorData.getName());
         }
     }
-
+    
     private void ruleLog(final RuleData ruleData, final String pluginName) {
         if (ruleData.getLoged()) {
             LOG.info("{} rule success match , rule name :{}", pluginName, ruleData.getName());