Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect all trailing slashes globally in express

I am using Node.js and Express and I have the following routing :

app.get('/', function(req,res){     locals.date = new Date().toLocaleDateString();      res.render('home.ejs', locals); });  function lessonsRouter (req, res, next) {     var lesson = req.params.lesson;     res.render('lessons/' + lesson + '.ejs', locals_lessons); }  app.get('/lessons/:lesson*', lessonsRouter);   function viewsRouter (req, res, next) {     var controllerName = req.params.controllerName;     res.render(controllerName + '.ejs', locals_lessons); } app.get('/:controllerName', viewsRouter); 

I have a Disqus widget on my lessons pages and I have noticed a strange behavior that when going to myapp.com/lessons and myapp.com/lessons/ I get two different pages (on of them had a comment I previously added in Disqus and the other one doesn't have a comment).

Is there a way to "canonize" all of my urls to be without trailing slashes ? I have tried to add the strict routing flag to express but the results were the same

Thanks

like image 543
Michael Avatar asked Nov 18 '12 17:11

Michael


People also ask

How do you fix trailing slash issues?

A 301 redirect is the best way to resolve duplicate content issues caused by trailing slashes. If you're just fixing one page, you'd redirect the duplicate copy to the version that matches your chosen URL structure. Most trailing slash issues however, affect many pages across a website.

What is return next (); in Express?

app. use((req, res, next) => { //next() or return next() }); In the function app. use((req, res, next), we have three callbacks i.e. request, response and next. So, if you want to use next() then simply write next() and if you want to use return next then simply write return next().

How do I reroute Express?

The res. redirect() function lets you redirect the user to a different URL by sending an HTTP response with status 302. The HTTP client (browser, Axios, etc.) will then "follow" the redirect and send an HTTP request to the new URL as shown below.

Do trailing slashes matter URL?

Historically, a trailing slash marked a directory and a URL without a trailing slash at the end used to mean that the URL was a file. Today, however, trailing slashes are purely conventional, and Google does not care whether you use them; as long as you're consistent.


2 Answers

The answer by Tolga Akyüz is inspiring but doesn't work if there is any characters after the slash. For example http://example.com/api/?q=a is redirected to http://example.com/api instead of http://example.com/api?q=a.

Here is an improved version of the proposed middleware that fixes the problem by adding the original query to the end of the redirect destination url. The version also has a few safety features described in the update notes.

app.use((req, res, next) => {   if (req.path.substr(-1) === '/' && req.path.length > 1) {     const query = req.url.slice(req.path.length)     const safepath = req.path.slice(0, -1).replace(/\/+/g, '/')     res.redirect(301, safepath + query)   } else {     next()   } }) 

Update 2016: As noted by jamesk and stated in RFC 1738, the trailing slash can only be omitted when there is nothing after the domain. Therefore, http://example.com?q=a is an invalid url where http://example.com/?q=a is a valid one. In such case, no redirection should be done. Fortunately, the expression req.path.length > 1 takes care of that. For example, given the url http://example.com/?q=a, the path req.path equals to / and thus the redirection is avoided.

Update 2021: As discovered by Matt, a double slash // in the beginning of the path causes a dangerous redirection. For example the url http://example.com//evil.com/ creates a redirect to //evil.com that is interpreted as http://evil.com or https://evil.com by the victim's browser. Also, noted by Van Quyet, there can be multiple trailing slashes that should be handled gracefully. Due to these findings, I added a line that safeguards the path by replacing all consequent slashes by a single /. I trust the performance overhead caused by the safeguard to be negligible because the regexp literals are only compiled once. Additionally, the code syntax was updated to ES6.

like image 76
Akseli Palén Avatar answered Oct 01 '22 13:10

Akseli Palén


Try adding a middleware for that;

app.use((req, res, next) => {   const test = /\?[^]*\//.test(req.url);   if (req.url.substr(-1) === '/' && req.url.length > 1 && !test)     res.redirect(301, req.url.slice(0, -1));   else     next(); }); 
like image 33
Tolga Akyüz Avatar answered Oct 01 '22 11:10

Tolga Akyüz