From 26f581b0b04f7415c00f034a87d6db7d8500a5d3 Mon Sep 17 00:00:00 2001 From: shedfreewu Date: Wed, 11 Mar 2026 15:47:53 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BD=91=E5=85=B3=20api=20=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E5=B0=BE=E6=96=9C=E6=9D=A0=E7=9A=84=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gateway/context/ContextGatewayFilter.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java index 5d3de6671..e188d7702 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-gateway-plugin/src/main/java/com/tencent/cloud/plugin/gateway/context/ContextGatewayFilter.java @@ -251,6 +251,14 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered { ServerHttpRequest request = exchange.getRequest(); String[] apis = rebuildExternalApi(request, path.value()); GroupContext.ContextRoute contextRoute = manager.getGroupPathRoute(config.getGroup(), apis[0]); + // Before Spring 6.0, trailing slashes were matched by default (e.g. "/api/test/" could match "/api/test"). + // Retry without trailing slashes to maintain backward compatibility. + if (contextRoute == null) { + String trimmedMatchPath = stripTrailingSlashes(apis[0]); + if (!trimmedMatchPath.equals(apis[0])) { + contextRoute = manager.getGroupPathRoute(config.getGroup(), trimmedMatchPath); + } + } if (contextRoute == null) { String msg = String.format("[externalFilter] Can't find context route for group: %s, path: %s, origin path: %s", config.getGroup(), apis[0], path.value()); logger.warn(msg); @@ -273,6 +281,14 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered { logger.debug("[msFilter] path:{}, apis: {}", path, apis); // check api GroupContext.ContextRoute contextRoute = manager.getGroupPathRoute(config.getGroup(), apis[0]); + // Before Spring 6.0, trailing slashes were matched by default (e.g. "/api/test/" could match "/api/test"). + // Retry without trailing slashes to maintain backward compatibility. + if (contextRoute == null) { + String trimmedMatchPath = stripTrailingSlashes(apis[0]); + if (!trimmedMatchPath.equals(apis[0])) { + contextRoute = manager.getGroupPathRoute(config.getGroup(), trimmedMatchPath); + } + } if (contextRoute == null) { String msg = String.format("[msFilter] Can't find context route for group: %s, path: %s, origin path: %s", config.getGroup(), apis[0], path.value()); logger.warn(msg); @@ -334,6 +350,14 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered { logger.debug("[unitFilter] path:{}, apis: {}", path, apis); // check api GroupContext.ContextRoute contextRoute = manager.getGroupUnitPathRoute(config.getGroup(), apis[0]); + // Before Spring 6.0, trailing slashes were matched by default (e.g. "/api/test/" could match "/api/test"). + // Retry without trailing slashes to maintain backward compatibility. + if (contextRoute == null) { + String trimmedMatchPath = stripTrailingSlashes(apis[0]); + if (!trimmedMatchPath.equals(apis[0])) { + contextRoute = manager.getGroupUnitPathRoute(config.getGroup(), trimmedMatchPath); + } + } if (contextRoute == null) { String msg = String.format("[unitFilter] Can't find context route for group: %s, path: %s, origin path: %s", config.getGroup(), apis[0], path.value()); logger.warn(msg); @@ -629,4 +653,19 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered { } return path.substring(start, end); } + + /** + * Strips trailing slashes from the given path, e.g. "GET|/api/test/" → "GET|/api/test". + * Returns the original string if no trailing slashes are present. + *

+ * Used to maintain backward compatibility with pre-Spring-6.0 behavior, where trailing slashes + * were matched by default (e.g. "/api/test/" could match a route configured as "/api/test"). + */ + private String stripTrailingSlashes(String path) { + int end = path.length(); + while (end > 0 && path.charAt(end - 1) == '/') { + end--; + } + return path.substring(0, end); + } } \ No newline at end of file