javaspring-bootspring-webflux

How do you ignore trailing slash in webflux in spring boot 3?


In Spring Boot 3, they have changed so that trailing slashes, by default, are no longer ignored. For example, if I have a GET resource, /users, and I navigate to /users/ then Spring Boot webflux will now respond with 404.

You can change this by implementing a WebFluxConfigurer and overriding the configurePathMatching method:

@Override
public void configurePathMatching(PathMatchConfigurer configurer) {
     configurer.setUseTrailingSlashMatch();
}

However, setUseTrailingSlashMatch is deprecated, and the docs says to use PathPatternParser.setMatchOptionalTrailingSeparator(boolean) instead. However, I don't understand how/where you actually configure this.

So the question is, how do I set PathPatternParser.setMatchOptionalTrailingSeparator(boolean)?


Solution

  • As @joe-clay has mentioned in his comment, PathPatternParser.setMatchOptionalTrailingSeparator(boolean) is deprecated as well in favour of explicit redirects. So you have 3 options:

    1. Declare both routes explicitly in the controller handler @GetMapping({"/users", "/users/"}). The downside is that you need to do this for every controller, but can be used as a stop-gap solution.

    2. Implement org.springframework.web.server.WebFilter interface to explicitly redirect to the desired url. Something along these lines:

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    
        URI originalUri = exchange.getRequest().getURI();
    
        if (/* check condition for trailing slash using originalUri getPath(), getQuery() etc. */) {
            String originalPath = originalUri.getPath();
            String newPath = originalPath.substring(0, originalPath.length() - 1); // ignore trailing slash
            try {
                URI newUri = new URI(originalUri.getScheme(),
                        originalUri.getUserInfo(),
                        originalUri.getHost(),
                        originalUri.getPort(),
                        newPath,
                        originalUri.getQuery(),
                        originalUri.getFragment());
    
                ServerHttpResponse response = exchange.getResponse();
                response.setStatusCode(HttpStatus.MOVED_PERMANENTLY);    // optional
                response.getHeaders().setLocation(mutatedUri);
    
                return Mono.empty();
    
            } catch (URISyntaxException e) {
                throw new IllegalStateException(e.getMessage(), e);
            }
        }
        return chain.filter(exchange);
    }
    
    1. Explicitly rewrite the incoming url in the proxy (for example using rewrite rules in nginx) to match the expected url.

    In options 2 and 3, you may choose to return an HTTP 301 response as well.