I am using Node.js and Express and I have the following routing :
app.get(\'/\', function(req,res){
locals.date = new Date().toLocaleDateString();
r
The answers above will work in a lot of cases but GET vars can encounter issues and if you were to put that inside another express middleware its reliance on req.path
will cause a problem and its reliance on req.url
can also have unwanted side effects.
If you're looking for a tighter solution this will do the trick:
// Redirect non trailing slash to trailing slash
app.use(function(req, res, next){
// Find the query string
var qsi = req.originalUrl.indexOf('?');
// Get the path
var path = req.originalUrl;
if(qsi > -1) path = path.substr(0, qsi);
// Continue if the path is good or it's a static resource
if(path.substr(-1) === '/' || ~path.indexOf('.')) return next();
// Save just the query string
var qs = '';
if(qsi > -1) qs = req.originalUrl.substr(qsi);
// Save redirect path
var redirect = path + '/' + qs;
// Redirect client
res.redirect(301, redirect);
console.log('301 redirected ' + req.originalUrl + ' to ' + redirect);
});
It's always happy with GET variables and won't break if you were to put it inside middleware.
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();
});
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 fix the problem by adding the original query to the end of the redirect destination url:
app.use(function(req, res, next) {
if (req.path.substr(-1) == '/' && req.path.length > 1) {
var query = req.url.slice(req.path.length);
res.redirect(301, req.path.slice(0, -1) + query);
} else {
next();
}
});
Note: 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.
The connect-slashes middleware was designed specifically for this need: https://npmjs.org/package/connect-slashes
Install it with:
$ npm install connect-slashes
Read the full documentation: https://github.com/avinoamr/connect-slashes
/**
* @param {express.Request} req
* @param {express.Response} res
* @param {express.NextFunction} next
* @return {void}
*/
function checkTrailingSlash(req, res, next) {
if (req.path.slice(req.path.length-1) !== '/') {
res.redirect(301, req.path + '/' + req.url.slice(req.path.length));
} else {
next();
}
}
app.use(checkTrailingSlash);
Example results:
/ ==> /
/a ==> /a/
/a/ ==> /a/
/a/b ==> /a/b/
/a/b/ ==> /a/b/
/a/b?c=d ==> /a/b/?c=d
/a/b/?c=d ==> /a/b/?c=d
One liner:
router.get('\\S+\/$', function (req, res) {
return res.redirect(301, req.path.slice(0, -1) + req.url.slice(req.path.length));
});
This will only catch the url's that need to be redirected, and ignore the others.
Example results:
/ ==> /
/a ==> /a
/a/ ==> /a
/a/b ==> /a/b
/a/b/ ==> /a/b
/a/b/?c=d ==> /a/b?c=d