Spring MVC (3.0) considers URLs with and without trailing slashes as the same URL.
For example:
http://www.example.org/data/something = http://www.example.org/data/something/
I need to redirect the URL with trailing slashes
to the URL without it:
I need to do this internally the application (so not rewrite rules via Apache, etc).
A way to do it is:
@ResponseStatus(value=HttpStatus.MOVED_PERMANENTLY)
@RequestMapping(value = "/data/something/")
public String dataSomethingRedirect(...) {
return "redirect:/data/something";
}
but this has generally 2 problems:
- too many controllers
- problem with parameters: like wrong encoding
Question
Is there a way to intercept all the URLs and in case they have a trailing slash, redirect them to the relative one without slash?
I think you best option would be to do this before entering in Spring web's servlet, using UrlRewriteFilter. This will ensure that your redirect rules would not impact your controllers.
Please note that you write the rules in your .war project, not in an apache with mod_rewrite.
Go here for the library's project on googlecode.
in the urlrewrite.xml write :
In the web.xml of your application, add :
Beware, the declaration order of the filters in the web.xml is important, so try to declare this one before anything from spring.
Of course, this is but a fraction of what UrlRewriteFilter can do.
Regards.
Based on SEO, I think it is important to make a distinction.
If the URL that finished in the trailing slash exist, is indexed in the search engines and there are links on Internet, a permanent redirection (301) is required as Uddhav Kambli says. The standard redirection (302) will be better than having a duplicated URL, but is not good enough.
However, if the URL never existed, it is not indexed on Internet and there are no external links, the URL does not exist. Therefore a 404, page not found, is a better fit.
WEB-INF/urlrewrite.xml
And in order to complete the configuration ...
add to WEB-INF/web.xml
Maven
I have found that this can also be handled much more simply by using an ErrorViewResolver bean somewhere in your @Configuration:
I'm not sure if this is good or bad practice, but it is effective in my circumstance, and does exactly what I need it to do for an arbitrary path 'foo': respond with a 302 redirect to /foo/ when you request /foo and respond as it should when you request /foo.
Not sure if spring 3.0 had this, but spring 3.1 RequestMappingHandlerMapping allows you to set a "useTrailingSlashMatch" property. By default it is true.
I think switching it to false would solve your issue, however it would affect ALL mappings handled by RequestMappingHandlerMapping across your application... so you may have a fair amount of regression to do.
I agree with @Brian Clozel: I don't think is a good idea to do what you want. So, why you need it?
Anyway, I think the simplest solution is to write a custom
javax.servlet.Filter
. So, no Spring dependency. If the request URL ends with slash you just have to redirect to the same url without it. But caution:All parameters (GET and POST) must be added as GET parameters. Are you sure that your application is method agnostic?
You can have some problems with encoding. In the filter you can encode POST parameters to the required encoding. But the default encoding for GET parameters is not configured in your application. Is configured in server.xml (if Tomcat) and default value is ISO-8859-1.
Good luck!
This usually works for me with URLRewriteFilter in Spring.