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