Spring Module and Version
Spring Web – v7.0.1
Issue Description
I have a few suggestions regarding improvements to parts of the UrlHandlerFilter implementations. They are not necessarily requests, but just areas that I'm enquiring about to gauge whether they might be valid places for enhancements.
- Handle patterns by match specificity.
Currently, the handlers are checked in the order in which they were added to the builder, using the supports method of the handler, until there is a match, and then checking the PathPatterns in order, until there is a match. It might be better to match based on the how well the pattern matches the request path instead. This would be similar to how resource handler patterns are matched (i.e. with AbstractUrlHandlerMapping.lookupHandler).
The use case would be something like with:
UrlHandlerFilter filter = UrlHandlerFilter
.trailingSlashHandler("/**").mutateRequest()
.trailingSlashHandler("/some/specific/path/**").redirect(HttpStatus.PERMANENT_REDIRECT)
.build();
In which you would want /some/specific/path/page/// to redirect instead of mutate. Currently it would mutate as the mutate handler is the first supported handler in the handlers map, and /** is the first matching pattern.
- Check that the HTTP status code is valid for redirect handlers.
Currently, whatever code passed into the redirect handler, e.g. .redirect(HttpStatus.PERMANENT_REDIRECT), will be used as the response status code alongside the Location header. Although maybe not a major issue, maybe an error should be thrown or a warning should be logged in the case that a non-3XX code is provided, given that the response produced would have Location header with a non-3XX status.
- Support additional specs for handling cases other than trailing slashes.
The only handler type currently is the TrailingSlashSpec. I know that the UrlHandlerFilter was added mainly as a replacement for the now-deprecated trailing slash match. However, if the thought is that the UrlHandlerFilter is a general convenience feature for configuring url handling, there might be other ways that request paths might want to be mapped by users.
The main one I can think of would be replacing multiple slashes with a single slash, with mutation or redirection options in the same way as with TrailingSlashSpec.
Something similar already exists with resource handlers, as the ResourceHttpRequestHandler and ResourceWebHandler both use ResourceHandlerUtils.normalizeInputPath(path) before locating a resource.
This means that, for example, if a resource handler is registered with the pattern /resources/**, both https://example.com/resources/styles/home.css and https://example.com/resources/styles////home.css can actually be used to find the same resource. This creates a behaviour that is similar to a handler created by .mutateRequest().
For 1 and 3, it might be better to refactor the MultiValueMap<Handler, PathPattern> handlers to something like Map<PathPattern, Handler> handlers to facilitate finding the most appropriate handler for a request.
This is analogous to how AbstractUrlHandlerMapping is implemented with it's Map<PathPattern, Object> pathPatternHandlerMap (standard variant) or Map<PathPattern, Object> handlerMap (reactive variant).