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

commit 9fca19a36e24836825c3242f6483ef03e020c5f5
Author: heyile <[email protected]>
AuthorDate: Fri Mar 27 19:42:34 2020 +0800

    [SCB-1832] Edge will lose public request headers
---
 .../edge/core/DefaultEdgeClientFilter.java         | 91 ++++++++++++++++++++++
 .../edge/core/URLMappedEdgeDispatcher.java         |  8 +-
 ...servicecomb.common.rest.filter.HttpClientFilter | 18 +++++
 .../org/apache/servicecomb/it/ConsumerMain.java    |  2 +
 .../publicHeaders/TestPublicHeadersEdge.java       | 73 +++++++++++++++++
 .../it-edge/src/main/resources/microservice.yaml   | 23 ++++++
 .../EdgePublicHeadersJaxrsSchema.java              | 43 ++++++++++
 .../EdgePublicHeadersSpringMVCSchema.java          | 42 ++++++++++
 8 files changed, 296 insertions(+), 4 deletions(-)

diff --git 
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeClientFilter.java
 
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeClientFilter.java
new file mode 100644
index 0000000..22d4f06
--- /dev/null
+++ 
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeClientFilter.java
@@ -0,0 +1,91 @@
+/*
+ * 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.edge.core;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.common.rest.filter.HttpClientFilter;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
+import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
+import org.apache.servicecomb.swagger.invocation.Response;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.netflix.config.ConcurrentCompositeConfiguration;
+import com.netflix.config.DynamicPropertyFactory;
+
+public class DefaultEdgeClientFilter implements HttpClientFilter {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(DefaultEdgeClientFilter.class);
+
+  private static final String KEY_ENABLED = 
"servicecomb.http.dispatcher.edge.public.enabled";
+
+  private static final String KEY_HEADERS = 
"servicecomb.http.dispatcher.edge.public.headers";
+
+  private static boolean ENABLED = false;
+
+  private static List<String> PUBLIC_HEADER = new ArrayList<>();
+
+  static {
+    init();
+    ((ConcurrentCompositeConfiguration) DynamicPropertyFactory
+        .getBackingConfigurationSource()).addConfigurationListener(event -> {
+      if (event.getPropertyName().startsWith(KEY_HEADERS) || 
event.getPropertyName().startsWith(KEY_ENABLED)) {
+        LOGGER.info("Public header config have been changed. Event=" + 
event.getType());
+        init();
+      }
+    });
+  }
+
+  private static void init() {
+    ENABLED = 
DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_ENABLED, 
false).get();
+    String publicHeaderStr = 
DynamicPropertyFactory.getInstance().getStringProperty(KEY_HEADERS, "").get();
+    String[] split = publicHeaderStr.split(",");
+    if (split.length > 0) {
+      PUBLIC_HEADER = Arrays.asList(split);
+    }
+  }
+
+  @Override
+  public int getOrder() {
+    return 0;
+  }
+
+  @Override
+  public boolean enabled() {
+    return ENABLED;
+  }
+
+  @Override
+  public void beforeSendRequest(Invocation invocation, HttpServletRequestEx 
requestEx) {
+    HttpServletRequestEx oldRequest = invocation.getRequestEx();
+    PUBLIC_HEADER.forEach(key -> {
+      if (StringUtils.isEmpty(oldRequest.getHeader(key))) {
+        return;
+      }
+      requestEx.addHeader(key, oldRequest.getHeader(key));
+    });
+  }
+
+  @Override
+  public Response afterReceiveResponse(Invocation invocation, 
HttpServletResponseEx responseEx) {
+    return null;
+  }
+}
diff --git 
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java
 
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java
index 31d6936..7bb1a88 100644
--- 
a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java
+++ 
b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java
@@ -43,7 +43,7 @@ public class URLMappedEdgeDispatcher extends 
AbstractEdgeDispatcher {
 
   private static final String KEY_PATTERN = 
"servicecomb.http.dispatcher.edge.url.pattern";
 
-  private static final String KEY_MAPPING_PREIX = 
"servicecomb.http.dispatcher.edge.url.mappings";
+  private static final String KEY_MAPPING_PREFIX = 
"servicecomb.http.dispatcher.edge.url.mappings";
 
   private Map<String, URLMappedConfigurationItem> configurations = new 
HashMap<>();
 
@@ -74,11 +74,11 @@ public class URLMappedEdgeDispatcher extends 
AbstractEdgeDispatcher {
   private void loadConfigurations() {
     ConcurrentCompositeConfiguration config = 
(ConcurrentCompositeConfiguration) DynamicPropertyFactory
         .getBackingConfigurationSource();
-    configurations = URLMappedConfigurationLoader.loadConfigurations(config, 
KEY_MAPPING_PREIX);
+    configurations = URLMappedConfigurationLoader.loadConfigurations(config, 
KEY_MAPPING_PREFIX);
     config.addConfigurationListener(event -> {
-      if (event.getPropertyName().startsWith(KEY_MAPPING_PREIX)) {
+      if (event.getPropertyName().startsWith(KEY_MAPPING_PREFIX)) {
         LOG.info("Map rule have been changed. Reload configurations. Event=" + 
event.getType());
-        configurations = 
URLMappedConfigurationLoader.loadConfigurations(config, KEY_MAPPING_PREIX);
+        configurations = 
URLMappedConfigurationLoader.loadConfigurations(config, KEY_MAPPING_PREFIX);
       }
     });
   }
diff --git 
a/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter
 
b/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter
new file mode 100644
index 0000000..bfdfd2a
--- /dev/null
+++ 
b/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.common.rest.filter.HttpClientFilter
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.servicecomb.edge.core.DefaultEdgeClientFilter
diff --git 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
index 6821d56..1f1b724 100644
--- 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
+++ 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
@@ -53,6 +53,7 @@ import 
org.apache.servicecomb.it.testcase.objectparams.TestJAXRSObjectParamType;
 import org.apache.servicecomb.it.testcase.objectparams.TestRPCObjectParamType;
 import 
org.apache.servicecomb.it.testcase.objectparams.TestSpringMVCObjectParamType;
 import 
org.apache.servicecomb.it.testcase.objectparams.TestSpringMVCObjectParamTypeRestOnly;
+import org.apache.servicecomb.it.testcase.publicHeaders.TestPublicHeadersEdge;
 import org.apache.servicecomb.it.testcase.thirdparty.Test3rdPartyInvocation;
 import org.apache.servicecomb.it.testcase.weak.consumer.TestSpringmvcBasic;
 
@@ -108,6 +109,7 @@ public class ConsumerMain {
   }
 
   private static void runShareTestCases() throws Throwable {
+    ITJUnitUtils.runWithHighwayAndRest(TestPublicHeadersEdge.class);
     ITJUnitUtils.runWithHighwayAndRest(TestChangeTransport.class);
     ITJUnitUtils.runWithHighwayAndRest(TestDataTypePrimitive.class);
     ITJUnitUtils.runWithHighwayAndRest(TestAnnotatedAttribute.class);
diff --git 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/publicHeaders/TestPublicHeadersEdge.java
 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/publicHeaders/TestPublicHeadersEdge.java
new file mode 100644
index 0000000..b103775
--- /dev/null
+++ 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/publicHeaders/TestPublicHeadersEdge.java
@@ -0,0 +1,73 @@
+/*
+ * 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.it.testcase.publicHeaders;
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.servicecomb.it.extend.engine.GateRestTemplate;
+import org.junit.Test;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+
+public class TestPublicHeadersEdge {
+  static GateRestTemplate jaxClient = 
GateRestTemplate.createEdgeRestTemplate("edgePublicHeadersJaxrsSchema");
+
+  static GateRestTemplate springMvcClient = 
GateRestTemplate.createEdgeRestTemplate("edgePublicHeadersSpringMVCSchema");
+
+  private static final String expectHeaderTest = "x_cse_test";
+
+  private static final String expectExternal1 = "external_1";
+
+  private static final String expectExternal2 = "external_2";
+
+  private static final String external3 = "external_3";
+
+  @Test
+  public void testJaxrsClientPublicRequestHeaders() {
+    HttpHeaders headers = new HttpHeaders();
+    headers.add("x_cse_test", expectHeaderTest);
+    headers.add("external_1", expectExternal1);
+    headers.add("external_2", expectExternal2);
+    headers.add("external_3", external3);
+
+    HttpEntity<?> entity = new HttpEntity<>(headers);
+    ResponseEntity<String> response = jaxClient.exchange("/requestHeaders",
+        HttpMethod.GET,
+        entity,
+        String.class);
+    assertEquals(expectHeaderTest + "_" + expectExternal1 + "_" + 
expectExternal2, response.getBody());
+  }
+
+  @Test
+  public void testSpringMvcClientPublicRequestHeaders() {
+    HttpHeaders headers = new HttpHeaders();
+    headers.add("x_cse_test", expectHeaderTest);
+    headers.add("external_1", expectExternal1);
+    headers.add("external_2", expectExternal2);
+    headers.add("external_3", external3);
+
+    HttpEntity<?> entity = new HttpEntity<>(headers);
+    ResponseEntity<String> response = 
springMvcClient.exchange("/requestHeaders",
+        HttpMethod.GET,
+        entity,
+        String.class);
+    assertEquals(expectHeaderTest + "_" + expectExternal1 + "_" + 
expectExternal2, response.getBody());
+  }
+}
diff --git a/integration-tests/it-edge/src/main/resources/microservice.yaml 
b/integration-tests/it-edge/src/main/resources/microservice.yaml
index cd69580..fcf649e 100644
--- a/integration-tests/it-edge/src/main/resources/microservice.yaml
+++ b/integration-tests/it-edge/src/main/resources/microservice.yaml
@@ -54,6 +54,10 @@ servicecomb:
         transport: rest
       springMVCObjectRestSchemaRestOnly:
         transport: rest
+      edgePublicHeadersJaxrsSchema:
+        transport: rest
+      edgePublicHeadersSpringMVCSchema:
+        transport: rest
     it-producer-h2:
       generic:
         genericUser:
@@ -75,6 +79,10 @@ servicecomb:
         transport: rest
       springMVCObjectRestSchemaRestOnly:
         transport: rest
+      edgePublicHeadersJaxrsSchema:
+        transport: rest
+      edgePublicHeadersSpringMVCSchema:
+        transport: rest
     it-producer-h2c:
       generic:
         genericUser:
@@ -96,6 +104,10 @@ servicecomb:
         transport: rest
       springMVCObjectRestSchemaRestOnly:
         transport: rest
+      edgePublicHeadersJaxrsSchema:
+        transport: rest
+      edgePublicHeadersSpringMVCSchema:
+        transport: rest
     it-producer-deploy-springboot2-servlet:
       generic:
         genericUser:
@@ -117,6 +129,10 @@ servicecomb:
         transport: rest
       springMVCObjectRestSchemaRestOnly:
         transport: rest
+      edgePublicHeadersJaxrsSchema:
+        transport: rest
+      edgePublicHeadersSpringMVCSchema:
+        transport: rest
     it-producer-deploy-springboot2-standalone:
       generic:
         genericUser:
@@ -138,9 +154,16 @@ servicecomb:
         transport: rest
       springMVCObjectRestSchemaRestOnly:
         transport: rest
+      edgePublicHeadersJaxrsSchema:
+        transport: rest
+      edgePublicHeadersSpringMVCSchema:
+        transport: rest
   http:
     dispatcher:
       edge:
+        public:
+          headers: external_1,external_2
+          enabled: true
         default:
           enabled: true
           prefix: rest
diff --git 
a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/publicHeaders/EdgePublicHeadersJaxrsSchema.java
 
b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/publicHeaders/EdgePublicHeadersJaxrsSchema.java
new file mode 100644
index 0000000..fa1cff0
--- /dev/null
+++ 
b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/publicHeaders/EdgePublicHeadersJaxrsSchema.java
@@ -0,0 +1,43 @@
+/*
+ * 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.it.schema.publicHeaders;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+
+@RestSchema(schemaId = "edgePublicHeadersJaxrsSchema")
+@Path("/v1/edgePublicHeadersJaxrsSchema")
+public class EdgePublicHeadersJaxrsSchema {
+
+  @Path("requestHeaders")
+  @GET
+  public String getRequestHeaders(@HeaderParam(value = "x_cse_test") String 
testHeader,
+      HttpServletRequest request) {
+    String external1 = request.getHeader("external_1");
+    String external2 = request.getHeader("external_2");
+    String external3 = request.getHeader("external_3");
+    if (StringUtils.isEmpty(external3)) {
+      return testHeader + "_" + external1 + "_" + external2;
+    }
+    return testHeader + "_" + external1 + "_" + external2 + "_" + external3;
+  }
+}
diff --git 
a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/publicHeaders/EdgePublicHeadersSpringMVCSchema.java
 
b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/publicHeaders/EdgePublicHeadersSpringMVCSchema.java
new file mode 100644
index 0000000..9a4025b
--- /dev/null
+++ 
b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/publicHeaders/EdgePublicHeadersSpringMVCSchema.java
@@ -0,0 +1,42 @@
+/*
+ * 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.it.schema.publicHeaders;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.ws.rs.HeaderParam;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@RestSchema(schemaId = "edgePublicHeadersSpringMVCSchema")
+@RequestMapping(path = "/v1/edgePublicHeadersSpringMVCSchema")
+public class EdgePublicHeadersSpringMVCSchema {
+
+  @GetMapping("/requestHeaders")
+  public String getRequestHeaders(@HeaderParam(value = "x_cse_test") String 
testHeader,
+      HttpServletRequest request) {
+    String external1 = request.getHeader("external_1");
+    String external2 = request.getHeader("external_2");
+    String external3 = request.getHeader("external_3");
+    if (StringUtils.isEmpty(external3)) {
+      return testHeader + "_" + external1 + "_" + external2;
+    }
+    return testHeader + "_" + external1 + "_" + external2 + "_" + external3;
+  }
+}

Reply via email to