spring-cloud / spring-cloud/spring-cloud-gateway

PathRoutePredicateFactory: matchTrailingSlash has no effect since Spring Framework 7.0

Open
#4,212 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

waiting-for-triage
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

Describe the bug
In Spring Cloud Gateway 5.0.x (built on Spring Framework 7.0 / Spring Boot 4), the matchTrailingSlash configuration on the Path route predicate no longer has any effect.

The root cause is that Spring Framework 7.0 removed PathPatternParser.setMatchOptionalTrailingSeparator() as part of spring-projects/spring-framework#34036. The Spring Cloud Gateway PathRoutePredicateFactory previously relied on this API to implement trailing slash tolerance.

In the current main branch of Spring Cloud Gateway, the call is commented out with a FIXME:

// FIXME: 5.0.0 setMatchOptionalTrailingSeparator missing
// pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchTrailingSlash());

This means the Config.matchTrailingSlash property still exists and is configurable, but silently does nothing — which is a breaking behavioral change for users relying on it.

Expected Behavior

When matchTrailingSlash is set to true (either globally or per-route), a path predicate like Path=/api/users/{segment} should match both:

  • /api/users/1
  • /api/users/1/

This was the documented behavior prior to Spring Cloud Gateway 5.0.

Actual Behavior

The path predicate /api/users/{segment} only matches /api/users/1. A request to /api/users/1/ returns 404 regardless of the matchTrailingSlash setting.

Versions Affected

  • Spring Cloud Gateway: 5.0.1
  • Spring Framework: 7.0.7
  • Spring Boot: 4.0.x

Spring's Original Behavior (pre-removal)

From the Spring Framework 6.2.x source (PathPatternParser Javadoc):

"If set to true a PathPattern without a trailing slash will also match request paths with a trailing slash."

The behavior was one-directional:

  • Pattern /api/users matches request /api/users/
  • Pattern /api/users/ does NOT match request /api/users

The matching was handled internally by individual PathElement implementations during pattern traversal via MatchingContext.isMatchOptionalTrailingSeparator().

Sample
Since PathPatternParser no longer supports this natively, Spring Cloud Gateway should implement the trailing slash tolerance at the predicate level. A possible approach:

  1. When matchTrailingSlash is true and the initial PathPattern.matches(path) fails:
  2. If the request path ends with /, strip it and retry the match
  3. Always restore the original path container in the exchange to avoid leaking state to downstream filters

This preserves the original one-directional semantics (patterns without trailing slash match requests with trailing slash) without depending on removed PathPatternParser internals.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at PathRoutePredicateFactory and its FIXME around the removed PathPatternParser trailing-separator API. Trace how the path is matched and how the exchange path is handled, then verify that matchTrailingSlash=true preserves the documented one-directional behavior for paths with and without a trailing slash, while the original path is restored afterward.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.