node.js 在 express 中全局重定向所有尾部斜杠
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13442377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Redirect all trailing slashes globally in express
提问by Michael
I am using Node.js and Express and I have the following routing :
我正在使用 Node.js 和 Express,并且有以下路由:
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 Disquswidget on my lessons pages and I have noticed a strange behavior that when going to myapp.com/lessonsand 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).
我有一个Disqus小部件上我的课的网页,我注意到一个奇怪的行为是要当myapp.com/lessons和myapp.com/lessons/我得到两个不同的网页(对他们都有我以前在Disqus增加,而另一个没有评论评论)。
Is there a way to "canonize" all of my urls to be without trailing slashes ? I have tried to add the strict routingflag to express but the results were the same
有没有办法“规范化”我的所有网址,使其不带斜杠?我试图添加strict routing标志来表达,但结果是一样的
Thanks
谢谢
回答by Akseli Palén
The answerby Tolga Akyüzis inspiring but doesn't work if there is any characters after the slash. For example http://example.com/api/?q=ais redirected to http://example.com/apiinstead of http://example.com/api?q=a.
答案由托尔加Akyüz是鼓舞人心的,但如果有斜杠之后的任何字符不起作用。例如http://example.com/api/?q=a被重定向到http://example.com/api而不是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:
这是建议的中间件的改进版本,它通过将原始查询添加到重定向目标 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 jameskand stated in RFC 1738, the trailing slash can only be omitted when there is nothing after the domain. Therefore, http://example.com?q=ais an invalid url where http://example.com/?q=ais a valid one. In such case, no redirection should be done. Fortunately, the expression req.path.length > 1takes care of that. For example, given the url http://example.com/?q=a, the path req.pathequals to /and thus the redirection is avoided.
注意:正如jamesk所指出的和RFC 1738 中所述,只有在域之后没有任何内容时才能省略尾部斜杠。因此,http://example.com?q=a是一个无效的网址,哪里http://example.com/?q=a是一个有效的网址。在这种情况下,不应进行重定向。幸运的是,表达式解决req.path.length > 1了这个问题。例如,给定 url http://example.com/?q=a,路径req.path等于/,因此避免了重定向。
回答by Tolga Akyüz
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();
});
回答by Roi Avinoam
The connect-slashes middleware was designed specifically for this need: https://npmjs.org/package/connect-slashes
connect-slashes 中间件专为这种需求而设计:https: //npmjs.org/package/connect-slashes
Install it with:
安装它:
$ npm install connect-slashes
$ npm install connect-slashes
Read the full documentation: https://github.com/avinoamr/connect-slashes
回答by ShortFuse
I'm adding this answer because I had too many issues with other solutions.
我添加此答案是因为其他解决方案存在太多问题。
/**
* @param {express.Request} req
* @param {express.Response} res
* @param {express.NextFunction} next
* @return {void}
*/
function checkTrailingSlash(req, res, next) {
const trailingSlashUrl = req.baseUrl + req.url;
if (req.originalUrl !== trailingSlashUrl) {
res.redirect(301, trailingSlashUrl);
} else {
next();
}
}
router.use(checkTrailingSlash);
This will translate:
这将翻译:
/page ==> /page/
/page?query=value ==> /page/?query=value
回答by Ronen Teva
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.
这只会捕获需要重定向的 url,而忽略其他的。
Example results:
结果示例:
/ ==> /
/a ==> /a
/a/ ==> /a
/a/b ==> /a/b
/a/b/ ==> /a/b
/a/b/?c=d ==> /a/b?c=d
回答by user2687646
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.pathwill cause a problem and its reliance on req.urlcan also have unwanted side effects.
If you're looking for a tighter solution this will do the trick:
上面的答案在很多情况下都有效,但 GET vars 可能会遇到问题,如果您将其放入另一个 express 中间件,它的依赖req.path会导致问题,并且它的依赖req.url也会产生不必要的副作用。如果您正在寻找更严格的解决方案,这将解决问题:
// 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.
它总是对 GET 变量感到满意,如果你把它放在中间件中也不会中断。

