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; + } +}
