Suppose we have this URL:
learn.techseo.blog/url-trailing-slash-policy
Now, we may have configured our web application to redirect all requests to a certain router, which would also probably allow the following URL:
learn.techseo.blog/url-trailing-slash-policy/
Oops! We now have two different URLs for the same resource → Duplicate content?
This problem is present in many frameworks, such as Laravel or ExpressJS.
What is duplicate content?
Duplicate content generally refers to blocks of content within or across different domains that either completely match other content or are appreciably similar.
Of course, this could include malicious duplicate content, but in most cases, we will be our own enemy by displaying the same content in different URLs on our website.
Enforcing trailing slash in our URLs
One simple way to solve this problem is to redirect all traffic to the same URL, but with a trailing slash.
Force trailing slash in .htaccess
Using .htaccess
, we can get this done by adding these new rules:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
With this instructions, we are telling our Apache server to redirect everything (ignoring existing files) that doesn't have a trailing slash, to the same URL with a trailing slash. This way, this is what will happen to our first example:
GET https://learn.techseo.blog/url-trailing-slash-policy
Response: 301. Location: https://learn.techseo.blog/url-trailing-slash-policy/
Final request: https://learn.techseo.blog/url-trailing-slash-policy/
NOTE: When testing, you can just use [L,R] instead of [L,R=301] to use a temporary 302 redirection. 301 redirections will be cached by your browser.
Force trailing slash in NGINX
We will add a new rule to our NGINX configuration to enforce a trailing slash policy in our URLs:
server {
server_name example.com;
location ~ "^/(.*[^/])$" {
try_files $uri /$1/$is_args$args;
}
}
Trailing slash policy in Express using NodeJS
We could also configure our web application to perform the redirection, instead of relying directly on the web server. To do this in Express, we could add this simple middleware to our application:
app.use(function (req, res, next) {
if (req.path.substr(-1) !== '/' && req.path.length > 1) {
const query = req.url.slice(req.path.length)
res.redirect(301, req.path.slice + '/' + query)
} else {
next()
}
})
Forcing a non-trailing slash policy
We could also want to enforce a policy in which our URLs do not have a trailing slash.
Non-trailing slash policy in .htaccess
We could do this by changing the regular expression, writing these new rules in our .htaccess
file:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
This rule will redirect automatically unless we're requesting an actual directory.
NOTE: When testing, you can just use [L,R] instead of [L,R=301] to use a temporary 302 redirection. 301 redirections will be cached by your browser.
Non-trailing slash policy in NGINX
We will add a new rule to our NGINX configuration to enforce a non-trailing slash policy in our URLs:
server {
server_name example.com;
location ~ "^/(.*)/$" {
try_files $uri/ /$1$is_args$args;
}
}
Non-trailing slash policy in Express using NodeJS
We could also configure our web application to perform the redirection, instead of relying directly on the web server. To do this in Express, we could add this simple middleware to our application:
app.use(function (req, res, next) {
if (req.path.substr(-1) === '/' && req.path.length > 1) {
const query = req.url.slice(req.path.length)
res.redirect(301, req.path.slice(0, -1) + query)
} else {
next()
}
})
Summary
We've seen how we can configure our server to automatically redirect URLs to enforce a trailing or non-trailing slash policy, providing a solution for many duplicate content issues.