Bozhidar Bozhanov opened SPR-8473 and commented
It would be nice to use strict url matching and at the same time be able to redirect alternatives with 301 (permanent).
For example:
http://example.com/foo/bar -> no trailing slash, and it is specified that way in the @RequsetMapping
http://example.com/foo/bar/ -> 301 redirect to /foo/bar
This is to enforce consistency of urls and at the same time not loose traffic/SEO value if someone accidentally adds the wrong link. Logging could be configured to report these redirects.
Affects: 3.1 M2
Referenced from: commits https://github.com/spring-projects/spring-framework-issues/commit/5eacd228f7aa79661f087ecb42d90112fec189bf
5 votes, 6 watchers
Comment From: spring-projects-issues
Rossen Stoyanchev commented
Would a HandlerInterceptor do the job? In preHandle(), issue response.sendRedirect() to the URL without the trailing slash and return false. Or perhaps even earlier - a UrlRewriteFilter or Apache mode_rewrite rule.
Comment From: spring-projects-issues
Bozhidar Bozhanov commented
(Sorry, there's a typo in the title - I meant 301 redirect)
And yes, a handleInterceptor will do. UrlRewriteFilter also (we are currently doing it that way), but it would require some parsing logic - you can't just use endsWith("/"). My point was to make it configurable with one switch rather than doing it yourself. Not that it is impossible, but instead of having everyone develop a custom solution (or don't do anything at all, which will be wrong), spring could provide an option for that.
Furthermore, if you have one mapping: /foo/bar and another one: bar/baz/, you can't easily handle it (you will need the mapping info from spring mvc in order to know whether the url to redirect to is with or without the slash)
Comment From: spring-projects-issues
Rossen Stoyanchev commented
I can imagine multiple ways to handle trailing slashes strictly - a 404 (not found), a 301 (redirect), or a rel="canonical" directive (as a link tag in HTML content or response header otherwise).
And yes, a handleInterceptor will do. UrlRewriteFilter also (we are currently doing it that way), but it would require some parsing logic - you can't just use endsWith("/").
Could you elaborate?
Furthermore, if you have one mapping: /foo/bar and another one: bar/baz/, you can't easily handle it (you will need the mapping info from spring mvc in order to know whether the url to redirect to is with or without the slash)
A general solution might be tricky to implement. Also the component best suited to detect the condition -- the HandlerMapping, isn't the best one to enforce it in all of the above ways. We could provide a simple flag to enforce strict matching and raise an exception if the incoming URL and a @RequestMapping
pattern differ by a '/'.
Comment From: spring-projects-issues
Bozhidar Bozhanov commented
About the parsing logic - you can't check with url.endsWith("/") - you have to take into account GET parameters (don't know about jsessionid). So at least you should get the url minus the query string (that's what we do now)
About the flag - that's what I mean - detect if the incoming URL and the @RequestMapping
pattern differ by a '/', but instead of raising an exception, 301 redirect to the alternative (if it's coming /foo/bar and is expected /foo/bar/ , then 301 to /foo/bar/)
Comment From: spring-projects-issues
Rossen Stoyanchev commented
Okay, I think this could be a useful feature.
In the very least we'll provide a flag in RequestMappingHandlerMapping
to disable trailing slash pattern matching, resulting in a 404 if there is no match. Additionally we can consider a configuration option for a permanent redirect, which would perform a second search (via RequestMappingHandlerMapping#handleNoMatch
), this time with the trailing slash, to see if any controller method would match, and if so either send the permanent redirect or expose information in a request attribute or in an exception that would allow you handle it accordingly.
Comment From: spring-projects-issues
Keith Donald commented
http://webmasters.stackexchange.com/questions/2498/does-it-make-a-difference-if-your-url-ends-in-a-trailing-slash-or-not
Comment From: spring-projects-issues
Bozhidar Bozhanov commented
Exactly. It will treat them as two separate URLs, which is not what you want normally. http://techblog.bozho.net/?p=401
Comment From: spring-projects-issues
Rossen Stoyanchev commented
Something like this should work. It needs a little more work and test cases added but the basic idea is there. If anyone wants to put together a pull request based on that, it'll help get it in quicker.
Comment From: spring-projects-issues
Ben Fagin commented
Rossen, will this implementation work for most cases? It seems like the interceptor would only be called if a handler was found. Since there would be no handler here the request is already 404'd by the time it hits the interceptor.
Comment From: spring-projects-issues
Rossen Stoyanchev commented
If it should work. If there is no "/foo" but there is "/foo/", you could map "/foo" as well and it should get redirected.
Comment From: spring-projects-issues
Bulk closing outdated, unresolved issues. Please, reopen if still relevant.
Comment From: OrangeDog
I think this is still relevant? Especially as Spring 6 deprecated useTrailingSlashMatch
.
Comment From: bclozel
I think this will be covered with #31366