fix:fix header validation when using Chinese char. (#1168)

pull/1171/head
Haotian Zhang 1 year ago committed by GitHub
parent 28440f4035
commit 7f2e3b9cf5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -11,3 +11,4 @@
- [feat:add swagger report switch.](https://github.com/Tencent/spring-cloud-tencent/pull/1149) - [feat:add swagger report switch.](https://github.com/Tencent/spring-cloud-tencent/pull/1149)
- [fix: dynamic routing using cookies.](https://github.com/Tencent/spring-cloud-tencent/pull/1151) - [fix: dynamic routing using cookies.](https://github.com/Tencent/spring-cloud-tencent/pull/1151)
- [fix:fix retry loadbalancer not working bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1156) - [fix:fix retry loadbalancer not working bug.](https://github.com/Tencent/spring-cloud-tencent/pull/1156)
- [fix:fix header validation when using Chinese char.](https://github.com/Tencent/spring-cloud-tencent/pull/1168)

@ -47,7 +47,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT, @SpringBootTest(webEnvironment = DEFINED_PORT,
classes = EncodeTransferMedataFeignInterceptorTest.TestApplication.class, classes = EncodeTransferMedataFeignInterceptorTest.TestApplication.class,
properties = {"server.port=8081", "spring.config.location = classpath:application-test.yml"}) properties = {"server.port=48081", "spring.config.location = classpath:application-test.yml"})
public class EncodeTransferMedataFeignInterceptorTest { public class EncodeTransferMedataFeignInterceptorTest {
@Autowired @Autowired
@ -74,7 +74,7 @@ public class EncodeTransferMedataFeignInterceptorTest {
return MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "b"); return MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_TRANSITIVE, "b");
} }
@FeignClient(name = "test-feign", url = "http://localhost:8081") @FeignClient(name = "test-feign", url = "http://localhost:48081")
public interface TestFeign { public interface TestFeign {
@RequestMapping("/test") @RequestMapping("/test")

@ -47,7 +47,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
*/ */
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT, classes = ConfigChangeListenerTest.TestApplication.class, @SpringBootTest(webEnvironment = DEFINED_PORT, classes = ConfigChangeListenerTest.TestApplication.class,
properties = {"server.port=8081", "spring.config.location = classpath:application-test.yml"}) properties = {"server.port=48081", "spring.config.location = classpath:application-test.yml"})
public class ConfigChangeListenerTest { public class ConfigChangeListenerTest {
private static final CountDownLatch hits = new CountDownLatch(2); private static final CountDownLatch hits = new CountDownLatch(2);

@ -58,7 +58,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT, classes = PolarisConfigRefreshOptimizationListenerNotTriggeredTest.TestApplication.class, @SpringBootTest(webEnvironment = DEFINED_PORT, classes = PolarisConfigRefreshOptimizationListenerNotTriggeredTest.TestApplication.class,
properties = { properties = {
"server.port=8081", "server.port=48081",
"spring.cloud.polaris.address=grpc://127.0.0.1:10081", "spring.cloud.polaris.address=grpc://127.0.0.1:10081",
"spring.cloud.polaris.config.connect-remote-server=false", "spring.cloud.polaris.config.connect-remote-server=false",
"spring.cloud.polaris.config.refresh-type=reflect", "spring.cloud.polaris.config.refresh-type=reflect",

@ -59,7 +59,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT, classes = PolarisConfigRefreshOptimizationListenerTriggeredTest.TestApplication.class, @SpringBootTest(webEnvironment = DEFINED_PORT, classes = PolarisConfigRefreshOptimizationListenerTriggeredTest.TestApplication.class,
properties = { properties = {
"server.port=8081", "server.port=48081",
"spring.cloud.polaris.address=grpc://127.0.0.1:10081", "spring.cloud.polaris.address=grpc://127.0.0.1:10081",
"spring.cloud.polaris.config.connect-remote-server=false", "spring.cloud.polaris.config.connect-remote-server=false",
"spring.cloud.polaris.config.refresh-type=reflect", "spring.cloud.polaris.config.refresh-type=reflect",

@ -18,6 +18,8 @@
package com.tencent.cloud.polaris.ratelimit.filter; package com.tencent.cloud.polaris.ratelimit.filter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Duration; import java.time.Duration;
import java.util.Objects; import java.util.Objects;
@ -51,6 +53,8 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain; import org.springframework.web.server.WebFilterChain;
import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
/** /**
* Reactive filter to check quota. * Reactive filter to check quota.
* *
@ -58,7 +62,7 @@ import org.springframework.web.server.WebFilterChain;
*/ */
public class QuotaCheckReactiveFilter implements WebFilter, Ordered { public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
private static final Logger LOGGER = LoggerFactory.getLogger(QuotaCheckReactiveFilter.class); private static final Logger LOG = LoggerFactory.getLogger(QuotaCheckReactiveFilter.class);
private final LimitAPI limitAPI; private final LimitAPI limitAPI;
@ -122,22 +126,28 @@ public class QuotaCheckReactiveFilter implements WebFilter, Ordered {
response.getHeaders() response.getHeaders()
.add(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetFlowControl.getDesc()); .add(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetFlowControl.getDesc());
if (Objects.nonNull(quotaResponse.getActiveRule())) { if (Objects.nonNull(quotaResponse.getActiveRule())) {
response.getHeaders() try {
.add(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, quotaResponse.getActiveRule().getName() String encodedActiveRuleName = URLEncoder.encode(
.getValue()); quotaResponse.getActiveRule().getName().getValue(), UTF_8);
response.getHeaders().add(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, encodedActiveRuleName);
}
catch (UnsupportedEncodingException e) {
LOG.error("Cannot encode {} for header internal-callee-activerule.",
quotaResponse.getActiveRule().getName().getValue(), e);
}
} }
return response.writeWith(Mono.just(dataBuffer)); return response.writeWith(Mono.just(dataBuffer));
} }
// Unirate // Unirate
if (quotaResponse.getCode() == QuotaResultCode.QuotaResultOk && quotaResponse.getWaitMs() > 0) { if (quotaResponse.getCode() == QuotaResultCode.QuotaResultOk && quotaResponse.getWaitMs() > 0) {
LOGGER.debug("The request of [{}] will waiting for {}ms.", path, quotaResponse.getWaitMs()); LOG.debug("The request of [{}] will waiting for {}ms.", path, quotaResponse.getWaitMs());
waitMs = quotaResponse.getWaitMs(); waitMs = quotaResponse.getWaitMs();
} }
} }
catch (Throwable t) { catch (Throwable t) {
// An exception occurs in the rate limiting API call, // An exception occurs in the rate limiting API call,
// which should not affect the call of the business process. // which should not affect the call of the business process.
LOGGER.error("fail to invoke getQuota, service is " + localService, t); LOG.error("fail to invoke getQuota, service is " + localService, t);
} }
if (waitMs > 0) { if (waitMs > 0) {

@ -19,6 +19,8 @@
package com.tencent.cloud.polaris.ratelimit.filter; package com.tencent.cloud.polaris.ratelimit.filter;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
@ -50,6 +52,8 @@ import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
/** /**
* Servlet filter to check quota. * Servlet filter to check quota.
* *
@ -115,8 +119,15 @@ public class QuotaCheckServletFilter extends OncePerRequestFilter {
} }
response.addHeader(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetFlowControl.getDesc()); response.addHeader(HeaderConstant.INTERNAL_CALLEE_RET_STATUS, RetStatus.RetFlowControl.getDesc());
if (Objects.nonNull(quotaResponse.getActiveRule())) { if (Objects.nonNull(quotaResponse.getActiveRule())) {
response.addHeader(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, quotaResponse.getActiveRule().getName() try {
.getValue()); String encodedActiveRuleName = URLEncoder.encode(
quotaResponse.getActiveRule().getName().getValue(), UTF_8);
response.addHeader(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, encodedActiveRuleName);
}
catch (UnsupportedEncodingException e) {
LOG.error("Cannot encode {} for header internal-callee-activerule.",
quotaResponse.getActiveRule().getName().getValue(), e);
}
} }
return; return;
} }

@ -45,7 +45,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
*/ */
@ExtendWith(SpringExtension.class) @ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = DEFINED_PORT, classes = SCGPluginsAutoConfigurationTest.TestApplication.class, @SpringBootTest(webEnvironment = DEFINED_PORT, classes = SCGPluginsAutoConfigurationTest.TestApplication.class,
properties = {"server.port=8081", "spring.config.location = classpath:application-test.yml", properties = {"server.port=48081", "spring.config.location = classpath:application-test.yml",
"spring.cloud.tencent.plugin.scg.staining.rule-staining.enabled = true"}) "spring.cloud.tencent.plugin.scg.staining.rule-staining.enabled = true"})
public class SCGPluginsAutoConfigurationTest { public class SCGPluginsAutoConfigurationTest {

@ -79,6 +79,7 @@ public final class PolarisEnhancedPluginUtils {
private static final List<HttpStatus> HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY, private static final List<HttpStatus> HTTP_STATUSES = toList(NOT_IMPLEMENTED, BAD_GATEWAY,
SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES, SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, HTTP_VERSION_NOT_SUPPORTED, VARIANT_ALSO_NEGOTIATES,
INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED); INSUFFICIENT_STORAGE, LOOP_DETECTED, BANDWIDTH_LIMIT_EXCEEDED, NOT_EXTENDED, NETWORK_AUTHENTICATION_REQUIRED);
private PolarisEnhancedPluginUtils() { private PolarisEnhancedPluginUtils() {
} }
@ -216,7 +217,15 @@ public final class PolarisEnhancedPluginUtils {
if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME)) { if (headers != null && headers.containsKey(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME)) {
Collection<String> values = headers.get(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME); Collection<String> values = headers.get(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME);
if (CollectionUtils.isNotEmpty(values)) { if (CollectionUtils.isNotEmpty(values)) {
return com.tencent.polaris.api.utils.StringUtils.defaultString(new ArrayList<>(values).get(0)); String decodedActiveRuleName = "";
try {
decodedActiveRuleName = URLDecoder.decode(new ArrayList<>(values).get(0), UTF_8);
}
catch (UnsupportedEncodingException e) {
LOG.error("Cannot decode {} from header internal-callee-activerule.",
headers.get(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME).get(0), e);
}
return com.tencent.polaris.api.utils.StringUtils.defaultString(decodedActiveRuleName);
} }
} }
return ""; return "";

@ -17,9 +17,11 @@
package com.tencent.cloud.rpc.enhancement.plugin; package com.tencent.cloud.rpc.enhancement.plugin;
import java.io.UnsupportedEncodingException;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@ -46,6 +48,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import static com.tencent.cloud.common.constant.ContextConstant.UTF_8;
import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST;
import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -324,13 +327,14 @@ public class PolarisEnhancedPluginUtilsTest {
} }
@Test @Test
public void testGetActiveRuleNameFromRequest() { public void testGetActiveRuleNameFromRequest() throws UnsupportedEncodingException {
HttpHeaders headers = new HttpHeaders(); HttpHeaders headers = new HttpHeaders();
String ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers); String ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers);
assertThat(ruleName).isEqualTo(""); assertThat(ruleName).isEqualTo("");
headers.set(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, "mock_rule"); String encodedRuleName = URLEncoder.encode("mock_rule", UTF_8);
headers.set(HeaderConstant.INTERNAL_ACTIVE_RULE_NAME, encodedRuleName);
ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers); ruleName = PolarisEnhancedPluginUtils.getActiveRuleNameFromRequest(headers);
assertThat(ruleName).isEqualTo("mock_rule"); assertThat(ruleName).isEqualTo("mock_rule");
} }

Loading…
Cancel
Save