From 0cf3d21f12615e4384be35413c363615eb2b7204 Mon Sep 17 00:00:00 2001 From: Guoji Lu <63774857+luguoji@users.noreply.github.com> Date: Tue, 18 Feb 2025 16:47:39 +0800 Subject: [PATCH] feat:support polaris route for gateway mvc (#1493) --- CHANGELOG.md | 1 + .../pom.xml | 8 ++ .../config/RouterAutoConfiguration.java | 15 +++ .../scgmvc/RouterLabelMvcFilter.java | 62 ++++++++++++ .../scg/RouterLabelGlobalFilterTest.java | 2 +- .../scgmvc/RouterLabelMvcFilterTest.java | 97 +++++++++++++++++++ spring-cloud-tencent-dependencies/pom.xml | 2 +- 7 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scgmvc/RouterLabelMvcFilter.java create mode 100644 spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scgmvc/RouterLabelMvcFilterTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index acbf84d0c..546d6fe34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,3 +44,4 @@ - [feat:support smooth upgrade from tsf.](https://github.com/Tencent/spring-cloud-tencent/pull/1482) - [fix:fix caller disposable metadata handle when using tracing.](https://github.com/Tencent/spring-cloud-tencent/pull/1483) - [refactor:update registry status.](https://github.com/Tencent/spring-cloud-tencent/pull/1484) +- [feat:support polaris route for gateway mvc.](https://github.com/Tencent/spring-cloud-tencent/pull/1493) diff --git a/spring-cloud-starter-tencent-polaris-router/pom.xml b/spring-cloud-starter-tencent-polaris-router/pom.xml index e97f4d864..6f7a1dcec 100644 --- a/spring-cloud-starter-tencent-polaris-router/pom.xml +++ b/spring-cloud-starter-tencent-polaris-router/pom.xml @@ -76,6 +76,14 @@ + + + org.springframework.cloud + spring-cloud-gateway-server-mvc + true + + + org.springframework.boot spring-boot-actuator diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java index 48857ad46..1c8adb7da 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/config/RouterAutoConfiguration.java @@ -27,6 +27,7 @@ import com.tencent.cloud.polaris.router.config.properties.PolarisNearByRouterPro import com.tencent.cloud.polaris.router.config.properties.PolarisRuleBasedRouterProperties; import com.tencent.cloud.polaris.router.instrument.resttemplate.RouterLabelRestTemplateInterceptor; import com.tencent.cloud.polaris.router.instrument.scg.RouterLabelGlobalFilter; +import com.tencent.cloud.polaris.router.instrument.scgmvc.RouterLabelMvcFilter; import com.tencent.cloud.polaris.router.interceptor.MetadataRouterRequestInterceptor; import com.tencent.cloud.polaris.router.interceptor.NamespaceRouterRequestInterceptor; import com.tencent.cloud.polaris.router.interceptor.NearbyRouterRequestInterceptor; @@ -91,6 +92,20 @@ public class RouterAutoConfiguration { } + /** + * Create when gateway application is SCG MVC. + */ + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass(name = "org.springframework.cloud.gateway.server.mvc.filter.FormFilter") + protected static class RouterLabelScgMvcFilterConfig { + + @Bean + public RouterLabelMvcFilter routerLabelMvcFilter() { + return new RouterLabelMvcFilter(); + } + + } + /** * Create when RestTemplate exists. * @author liuye 2022-09-14 diff --git a/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scgmvc/RouterLabelMvcFilter.java b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scgmvc/RouterLabelMvcFilter.java new file mode 100644 index 000000000..2d8d21764 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/main/java/com/tencent/cloud/polaris/router/instrument/scgmvc/RouterLabelMvcFilter.java @@ -0,0 +1,62 @@ +/* + * Tencent is pleased to support the open source community by making spring-cloud-tencent available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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 com.tencent.cloud.polaris.router.instrument.scgmvc; + +import java.io.IOException; + +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.cloud.metadata.provider.ServletMetadataProvider; +import com.tencent.polaris.metadata.core.MetadataType; +import com.tencent.polaris.metadata.core.constant.MetadataConstants; +import com.tencent.polaris.metadata.core.manager.CalleeMetadataContainerGroup; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.core.Ordered; + +import static org.springframework.cloud.gateway.server.mvc.filter.FormFilter.FORM_FILTER_ORDER; + +/** + * Interceptor used for setting SCG MVC metadata provider. + * + * @author luguoji + */ +public class RouterLabelMvcFilter implements Filter, Ordered { + + @Override + public int getOrder() { + return FORM_FILTER_ORDER - 1; + } + + /** + * Create new RequestData for passing router labels. + */ + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) + throws IOException, ServletException { + MetadataContextHolder.get().getMetadataContainer(MetadataType.MESSAGE, false) + .setMetadataProvider(new ServletMetadataProvider((HttpServletRequest) request, + CalleeMetadataContainerGroup.getStaticApplicationMetadataContainer() + .getRawMetadataStringValue(MetadataConstants.LOCAL_IP))); + filterChain.doFilter(request, response); + } +} diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilterTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilterTest.java index 52c03f416..c41f84279 100644 --- a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilterTest.java +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scg/RouterLabelGlobalFilterTest.java @@ -45,7 +45,7 @@ import static org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClien */ @ExtendWith(SpringExtension.class) @SpringBootTest(classes = RouterLabelGlobalFilterTest.TestApplication.class, - properties = {"spring.cloud.polaris.namespace=test", "spring.application.name=test", "spring.main.web-application-type=reactive"}) + properties = {"spring.cloud.polaris.namespace=test", "spring.application.name=test", "spring.main.web-application-type=reactive", "spring.cloud.gateway.mvc.enabled=false"}) public class RouterLabelGlobalFilterTest { @Test diff --git a/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scgmvc/RouterLabelMvcFilterTest.java b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scgmvc/RouterLabelMvcFilterTest.java new file mode 100644 index 000000000..76fc4edb4 --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-router/src/test/java/com/tencent/cloud/polaris/router/instrument/scgmvc/RouterLabelMvcFilterTest.java @@ -0,0 +1,97 @@ +/* + * Tencent is pleased to support the open source community by making spring-cloud-tencent available. + * + * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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 com.tencent.cloud.polaris.router.instrument.scgmvc; + +import java.io.IOException; + +import com.tencent.cloud.common.metadata.MetadataContextHolder; +import com.tencent.polaris.metadata.core.MessageMetadataContainer; +import com.tencent.polaris.metadata.core.MetadataContainer; +import com.tencent.polaris.metadata.core.MetadataType; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; + +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpMethod; +import org.springframework.mock.web.MockCookie; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.fail; +import static org.springframework.cloud.gateway.server.mvc.filter.FormFilter.FORM_FILTER_ORDER; + +/** + * Test for ${@link RouterLabelMvcFilter}. + * + * @author luguoji + */ +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = RouterLabelMvcFilterTest.TestApplication.class, + properties = {"spring.cloud.polaris.namespace=test", "spring.application.name=test", "spring.main.web-application-type=servlet", "spring.cloud.gateway.enabled=false"}) +public class RouterLabelMvcFilterTest { + + @Test + public void testRouterLabelMvc() { + try { + RouterLabelMvcFilter routerLabelMvcFilter = new RouterLabelMvcFilter(); + + assertThat(routerLabelMvcFilter.getOrder()) + .isEqualTo(FORM_FILTER_ORDER - 1); + + FilterChain filterChain = (servletRequest, servletResponse) -> { + + }; + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("uid", "1000"); + request.setCookies(new MockCookie("k1", "v1")); + request.setMethod(HttpMethod.POST.name()); + request.setRequestURI("/test/path"); + request.setQueryString("q1=a1"); + + MockHttpServletResponse response = new MockHttpServletResponse(); + routerLabelMvcFilter.doFilter(request, response, filterChain); + // get message metadata container + MetadataContainer metadataContainer = MetadataContextHolder.get() + .getMetadataContainer(MetadataType.MESSAGE, false); + // method + assertThat(metadataContainer.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_METHOD)).isEqualTo(HttpMethod.POST.toString()); + // path + assertThat(metadataContainer.getRawMetadataStringValue(MessageMetadataContainer.LABEL_KEY_PATH)).isEqualTo("/test/path"); + // header + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_HEADER, "uid")).isEqualTo("1000"); + // cookie + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_COOKIE, "k1")).isEqualTo("v1"); + // query + assertThat(metadataContainer.getRawMetadataMapValue(MessageMetadataContainer.LABEL_MAP_KEY_QUERY, "q1")).isEqualTo("a1"); + } + catch (ServletException | IOException e) { + fail("Exception encountered.", e); + } + } + + @SpringBootApplication + protected static class TestApplication { + + } +} diff --git a/spring-cloud-tencent-dependencies/pom.xml b/spring-cloud-tencent-dependencies/pom.xml index f8af3f4fd..e63a07928 100644 --- a/spring-cloud-tencent-dependencies/pom.xml +++ b/spring-cloud-tencent-dependencies/pom.xml @@ -74,7 +74,7 @@ 2.0.0.0-2023.0.3-SNAPSHOT - 2.0.0.0-SNAPSHOT + 2.0.0.0 32.0.1-jre