The primary reason for this issue is https://github.com/spring-cloud/spring-cloud-gateway/issues/2795 which under the hood uses UriComponentsBuilder. See this comment specifically: https://github.com/spring-cloud/spring-cloud-gateway/issues/2795#issuecomment-2527587851

In the context of https://github.com/spring-projects/spring-framework/issues/14904 and https://github.com/spring-projects/spring-framework/issues/17006 there have been changes made to sanitise multiple consecutive slashes and replace them via a single slash: https://github.com/spring-projects/spring-framework/blob/78f28fda5481f28e0808cdfd85bd0c29a78f07c0/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java#L881-L891

Technically, there is no restriction on multiple consecutive slashes - those are valid urls, so I think that adding the option of preserving those in UriComponentsBuilder would be a good thing, and would solve the mentioned gateway issue.

What do you think?

Comment From: bclozel

Thanks for reaching out. I agree that multiple consecutive slashes are technically legal in URIs, and browsers normalize "/./" and "/../" but they do keep "//" and send them as is to servers.

But we must also consider that we're dealing with hierarchical URIs here and that supporting empty path segments is very problematic. The goal of UriComponentsBuilder is to help developers build URIs, including by concatenating path segments.

Consider this case:

UriComponents result = UriComponentsBuilder.fromUri(uri).path("/first/").path("/second").build();
// should we have instead "/first//second" because we allow empty path segments?
// maybe skip the "//" when concatenating?
assertThat(result.getPath()).isEqualTo("/first/second");
// this means we only keep "//" if they're in the middle of a path argument?
result = UriComponentsBuilder.fromUri(uri).path("/first//second").build();
assertThat(result.getPath()).isEqualTo("/first//second");

As you can see, behavior would be inconsistent. This behavior can be tracked to #14904 and has been long standing. I appreciate the use case here, but we didn't have much demand for empty paths support in Spring over the years and I don't think the tradeoff is in favor of introducing that change.

If there is indeed a specific use case in Spring Cloud Gateway, maybe a dedicated URI building implementation should be considered there.

Thanks!