How to redirect URLs with trailing slash to the corresponding ones without it?
Solution 1
You could list all the rewrite rules you need in your web configuration
If there aren't many of those, you can configure redirect views like this
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/my/path/", "/my/path")
.setKeepQueryParams(true)
.setStatusCode(HttpStatus.PERMANENT_REDIRECT);
}
Or you could create a custom HandlerInterceptor
But interceptors occur before requests are mapped to a specific Controller.action
and you've got no way of knowing Controllers and actions in that context.
All you've got is HTTPServlet API and request+response; so you can:
response.sendRedirect("http://example.org/whitout-trailing-slash");
The answer you don't want to read
This behavior (URL with trailing slash = URL without it) is perfectly "valid" when considering HTTP. At least this is the default behavior with Spring, that you can disable with useTrailingSlashMatch
(see javadoc).
So using rewrite/redirect rules on the front-end server could a solution; but again, I don't know your constraints (maybe you could elaborate on this and we could figure out other solutions?).
Solution 2
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 :
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.1//EN" "http://www.tuckey.org/res/dtds/urlrewrite3.1.dtd">
<urlrewrite>
<rule match-type="regex">
<note>Remove trailing slash</note>
<from>^(.*)/$</from>
<to type="redirect">$1</to>
</rule>
</urlrewrite>
In the web.xml of your application, add :
<filter>
<filter-name>UrlRewriteFilter</filter-name>
<filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
<init-param>
<param-name>confPath</param-name>
<param-value>/WEB-INF/urlrewrite.xml</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>UrlRewriteFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
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.
Solution 3
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.
Solution 4
This usually works for me with URLRewriteFilter in Spring.
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.2//EN"
"http://www.tuckey.org/res/dtds/urlrewrite3.2.dtd">
<urlrewrite>
<rule>
<note>Remove trailing slash for SEO purposes</note>
<from>/**/</from>
<to type="permanent-redirect">%{context-path}/$1</to>
</rule>
</urlrewrite>
Randomize
Just a random developer that does NOT believe in software development and people
Updated on July 09, 2022Comments
-
Randomize almost 2 years
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?