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

liubao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new 7930c3b77 [SCB-2840]add request parameter to context parameter mapper 
(#4044)
7930c3b77 is described below

commit 7930c3b77cb6da3cb9dfe8423fb992e6ff6fff40
Author: liubao68 <[email protected]>
AuthorDate: Mon Nov 20 17:40:45 2023 +0800

    [SCB-2840]add request parameter to context parameter mapper (#4044)
---
 .../core/filter/CoreFilterConfiguration.java       |  7 ++
 .../core/filter/impl/ContextMapperFilter.java      | 84 ++++++++++++++++++++++
 .../servicecomb/core/governance/MatchType.java     | 10 +++
 .../governance/marker/GovernanceRequest.java       | 22 ++++++
 .../marker/GovernanceRequestExtractor.java         |  2 +
 .../servicecomb/governance/marker/Matcher.java     | 13 +++-
 .../governance/marker/RequestProcessor.java        | 16 +++++
 .../apache/servicecomb/governance/MapperTest.java  | 14 ++++
 governance/src/test/resources/application.yaml     |  8 +++
 9 files changed, 174 insertions(+), 2 deletions(-)

diff --git 
a/core/src/main/java/org/apache/servicecomb/core/filter/CoreFilterConfiguration.java
 
b/core/src/main/java/org/apache/servicecomb/core/filter/CoreFilterConfiguration.java
index d5a828a18..d0a734c03 100644
--- 
a/core/src/main/java/org/apache/servicecomb/core/filter/CoreFilterConfiguration.java
+++ 
b/core/src/main/java/org/apache/servicecomb/core/filter/CoreFilterConfiguration.java
@@ -16,10 +16,12 @@
  */
 package org.apache.servicecomb.core.filter;
 
+import org.apache.servicecomb.core.filter.impl.ContextMapperFilter;
 import org.apache.servicecomb.core.filter.impl.ParameterValidatorFilter;
 import org.apache.servicecomb.core.filter.impl.ProviderOperationFilter;
 import org.apache.servicecomb.core.filter.impl.RetryFilter;
 import org.apache.servicecomb.core.filter.impl.ScheduleFilter;
+import org.apache.servicecomb.governance.handler.MapperHandler;
 import org.apache.servicecomb.governance.handler.RetryHandler;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -41,6 +43,11 @@ public class CoreFilterConfiguration {
     return new RetryFilter(retryHandler);
   }
 
+  @Bean
+  public ContextMapperFilter contextMapperFilter(MapperHandler mapperHandler) {
+    return new ContextMapperFilter(mapperHandler);
+  }
+
   @Bean
   public FilterChainsManager filterChainsManager() {
     return new FilterChainsManager();
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ContextMapperFilter.java
 
b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ContextMapperFilter.java
new file mode 100644
index 000000000..a14e41dd6
--- /dev/null
+++ 
b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ContextMapperFilter.java
@@ -0,0 +1,84 @@
+/*
+ * 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.servicecomb.core.filter.impl;
+
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.core.CoreConst;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.filter.AbstractFilter;
+import org.apache.servicecomb.core.filter.EdgeFilter;
+import org.apache.servicecomb.core.filter.FilterNode;
+import org.apache.servicecomb.core.filter.ProviderFilter;
+import org.apache.servicecomb.core.governance.MatchType;
+import org.apache.servicecomb.governance.handler.MapperHandler;
+import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor;
+import org.apache.servicecomb.governance.processor.mapping.Mapper;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.springframework.util.CollectionUtils;
+
+public class ContextMapperFilter extends AbstractFilter implements 
ProviderFilter, EdgeFilter {
+  private final MapperHandler mapperHandler;
+
+  public ContextMapperFilter(MapperHandler mapperHandler) {
+    this.mapperHandler = mapperHandler;
+  }
+
+  @Override
+  public boolean enabledForTransport(String transport) {
+    return CoreConst.RESTFUL.equals(transport);
+  }
+
+  @Override
+  public int getOrder() {
+    return -1995;
+  }
+
+  @Override
+  public String getName() {
+    return "context-mapper";
+  }
+
+  @Override
+  public CompletableFuture<Response> onFilter(Invocation invocation, 
FilterNode nextNode) {
+    GovernanceRequestExtractor request = 
MatchType.createGovHttpRequest(invocation);
+    Mapper mapper = mapperHandler.getActuator(request);
+    if (mapper == null || CollectionUtils.isEmpty(mapper.target())) {
+      return nextNode.onFilter(invocation);
+    }
+    Map<String, String> properties = mapper.target();
+    properties.forEach((k, v) -> {
+      if (StringUtils.isEmpty(v)) {
+        return;
+      }
+      if ("$U".equals(v)) {
+        invocation.addContext(k, request.apiPath());
+      } else if ("$M".equals(v)) {
+        invocation.addContext(k, request.method());
+      } else if (v.startsWith("$H{") && v.endsWith("}")) {
+        invocation.addContext(k, request.header(v.substring(3, v.length() - 
1)));
+      } else if (v.startsWith("$Q{") && v.endsWith("}")) {
+        invocation.addContext(k, request.query(v.substring(3, v.length() - 
1)));
+      } else {
+        invocation.addContext(k, v);
+      }
+    });
+    return nextNode.onFilter(invocation);
+  }
+}
diff --git 
a/core/src/main/java/org/apache/servicecomb/core/governance/MatchType.java 
b/core/src/main/java/org/apache/servicecomb/core/governance/MatchType.java
index 5b7679cdb..c6adef1f7 100644
--- a/core/src/main/java/org/apache/servicecomb/core/governance/MatchType.java
+++ b/core/src/main/java/org/apache/servicecomb/core/governance/MatchType.java
@@ -20,6 +20,7 @@ package org.apache.servicecomb.core.governance;
 import java.util.Map;
 
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
 import org.apache.servicecomb.governance.marker.GovernanceRequestExtractor;
 import org.apache.servicecomb.swagger.SwaggerUtils;
 
@@ -73,6 +74,15 @@ public final class MatchType {
       return null;
     }
 
+    @Override
+    public String query(String key) {
+      HttpServletRequestEx requestEx = invocation.getRequestEx();
+      if (requestEx == null) {
+        return null;
+      }
+      return requestEx.getParameter(key);
+    }
+
     @Override
     public String instanceId() {
       if (invocation.isConsumer()) {
diff --git 
a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java
 
b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java
index 239b38efd..e3ac0b2ab 100644
--- 
a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java
+++ 
b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequest.java
@@ -29,6 +29,13 @@ public class GovernanceRequest implements 
GovernanceRequestExtractor {
    */
   private Map<String, String> headers = Collections.emptyMap();
 
+  /**
+   * Queries with this request, maybe null.
+   * For provider: Queries indicates the request params to me.
+   * For consumer: Queries indicates the request params to the target.
+   */
+  private Map<String, String> queries = Collections.emptyMap();
+
   /**
    * api path with this request, maybe null. For REST, e.g. /foo/bar; For RPC, 
e.g. MySchema.sayHello
    * For provider: uri indicates the request uri to me.
@@ -71,16 +78,31 @@ public class GovernanceRequest implements 
GovernanceRequestExtractor {
     return headers.get(key);
   }
 
+  @Override
+  public String query(String key) {
+    return queries.get(key);
+  }
+
   public Map<String, String> getHeaders() {
     return headers;
   }
 
+  public Map<String, String> getQueries() {
+    return queries;
+  }
+
   public void setHeaders(Map<String, String> headers) {
     Map<String, String> temp = new LinkedCaseInsensitiveMap<>();
     temp.putAll(headers);
     this.headers = temp;
   }
 
+  public void setQueries(Map<String, String> queries) {
+    Map<String, String> temp = new LinkedCaseInsensitiveMap<>();
+    temp.putAll(queries);
+    this.queries = temp;
+  }
+
   @Override
   public String apiPath() {
     return apiPath;
diff --git 
a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequestExtractor.java
 
b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequestExtractor.java
index 873f78665..28beb8e83 100644
--- 
a/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequestExtractor.java
+++ 
b/governance/src/main/java/org/apache/servicecomb/governance/marker/GovernanceRequestExtractor.java
@@ -23,6 +23,8 @@ public interface GovernanceRequestExtractor {
 
   String header(String key);
 
+  String query(String key);
+
   String instanceId();
 
   String serviceName();
diff --git 
a/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java
 
b/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java
index 1cff86523..6fb18fada 100644
--- 
a/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java
+++ 
b/governance/src/main/java/org/apache/servicecomb/governance/marker/Matcher.java
@@ -26,6 +26,8 @@ public class Matcher {
 
   private Map<String, RawOperator> headers;
 
+  private Map<String, RawOperator> queries;
+
   private RawOperator apiPath;
 
   private List<String> method;
@@ -46,11 +48,18 @@ public class Matcher {
     return headers;
   }
 
-  public void setHeaders(
-      Map<String, RawOperator> headers) {
+  public void setHeaders(Map<String, RawOperator> headers) {
     this.headers = headers;
   }
 
+  public Map<String, RawOperator> getQueries() {
+    return queries;
+  }
+
+  public void setQueries(Map<String, RawOperator> queries) {
+    this.queries = queries;
+  }
+
   public RawOperator getApiPath() {
     return apiPath;
   }
diff --git 
a/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java
 
b/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java
index a17d3f72b..f8e077ed1 100644
--- 
a/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java
+++ 
b/governance/src/main/java/org/apache/servicecomb/governance/marker/RequestProcessor.java
@@ -64,6 +64,9 @@ public class RequestProcessor implements 
ApplicationContextAware {
     if (!headersMatch(request, matcher)) {
       return false;
     }
+    if (!queriesMatch(request, matcher)) {
+      return false;
+    }
     if (!serviceNameMatch(request, matcher)) {
       return false;
     }
@@ -90,6 +93,19 @@ public class RequestProcessor implements 
ApplicationContextAware {
     return true;
   }
 
+  private boolean queriesMatch(GovernanceRequestExtractor request, Matcher 
matcher) {
+    if (matcher.getQueries() == null) {
+      return true;
+    }
+    for (Entry<String, RawOperator> entry : matcher.getQueries().entrySet()) {
+      if (request.query(entry.getKey()) == null ||
+          !operatorMatch(request.query(entry.getKey()), entry.getValue())) {
+        return false;
+      }
+    }
+    return true;
+  }
+
   private boolean apiPathMatch(GovernanceRequestExtractor request, Matcher 
matcher) {
     if (matcher.getApiPath() == null) {
       return true;
diff --git 
a/governance/src/test/java/org/apache/servicecomb/governance/MapperTest.java 
b/governance/src/test/java/org/apache/servicecomb/governance/MapperTest.java
index 176e25030..a8dcaac7e 100644
--- a/governance/src/test/java/org/apache/servicecomb/governance/MapperTest.java
+++ b/governance/src/test/java/org/apache/servicecomb/governance/MapperTest.java
@@ -17,6 +17,9 @@
 
 package org.apache.servicecomb.governance;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.servicecomb.governance.handler.MapperHandler;
 import org.apache.servicecomb.governance.marker.GovernanceRequest;
 import org.apache.servicecomb.governance.processor.mapping.Mapper;
@@ -50,6 +53,17 @@ public class MapperTest {
     Assertions.assertEquals("8080", mapper.target().get("port"));
   }
 
+  @Test
+  public void test_mapper_query_work() {
+    GovernanceRequest request = new GovernanceRequest();
+    Map<String, String> queries = new HashMap<>();
+    queries.put("name", "bob");
+    request.setQueries(queries);
+    Mapper mapper = mapperHandler.getActuator(request);
+    Assertions.assertEquals(1, mapper.target().size());
+    Assertions.assertEquals("$Q{name}", mapper.target().get("user-id"));
+  }
+
   @Test
   public void test_mapper2_work() {
     GovernanceRequest request = new GovernanceRequest();
diff --git a/governance/src/test/resources/application.yaml 
b/governance/src/test/resources/application.yaml
index 95eb39f61..96b614075 100644
--- a/governance/src/test/resources/application.yaml
+++ b/governance/src/test/resources/application.yaml
@@ -93,6 +93,11 @@ servicecomb:
       matches:
         - apiPath:
             prefix: "/mapper"
+    demo-mapper-query: |
+      matches:
+        - queries:
+            name: 
+              exact: "bob"
   rateLimiting:
     demo-rateLimiting: |
       rate: 1
@@ -203,6 +208,9 @@ servicecomb:
       target:
         host: 127.0.0.1
         port: 8080
+    demo-mapper-query: |
+      target:
+        user-id: $Q{name}
   mapper2:
     demo-mapper: |
       target:

Reply via email to