在express中全局重定向所有尾部斜杠

Mic*_*ael 39 disqus node.js express

我正在使用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);
Run Code Online (Sandbox Code Playgroud)

我有一个Disqus我的教训网页插件,我注意到一个奇怪的行为是要当myapp.com/lessonsmyapp.com/lessons/我得到两个不同的网页(对他们都有我以前在Disqus增加,而另一个没有评论评论).

有没有办法"管理"我的所有网址没有拖尾斜线?我试图添加strict routing标志来表达,但结果是一样的

谢谢

Aks*_*lén 79

答案托尔加Akyüz是鼓舞人心的,但如果有斜杠之后的任何字符不起作用.例如http://example.com/api/?q=a,重定向到http://example.com/api而不是http://example.com/api?q=a.

以下是提议的中间件的改进版本,通过将原始查询添加到重定向目标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();
    }
});
Run Code Online (Sandbox Code Playgroud)

注意:正如jamesk所述并在RFC 1738中说明,只有在域之后没有任何内容时才能省略尾部斜杠.因此,http://example.com?q=a无效的URL http://example.com/?q=a是有效的URL .在这种情况下,不应该进行重定向.幸运的是,表达式req.path.length > 1可以解决这个问题.例如,给定url http://example.com/?q=a,路径req.path等于/,因此避免重定向.


Tol*_*yüz 55

尝试为此添加中间件;

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();
});
Run Code Online (Sandbox Code Playgroud)

  • 请注意,使用此中间件时,如果斜杠后面有任何内容,则重定向不起作用.例如``http://example.com/lessons/?`即使`http:// example.com/lessons /`也不会被重定向. (7认同)
  • 这有效.我更喜欢`req.url.slice(0,-1)`到`req.url.substring(0,req.url.length-1)`,但这只是风格问题. (6认同)
  • @TolgaAkyüz我怀疑你的意思是`res.redirect`而不是`req.redirect`? (2认同)

小智 24

connect-slashes中间件专为满足这一需求而设计:https: //npmjs.org/package/connect-slashes

安装它:

$ npm install connect-slashes

阅读完整文档:https: //github.com/avinoamr/connect-slashes

  • 谢谢!适用于Express v4. (2认同)

Sho*_*use 10

我正在添加这个答案,因为我对其他解决方案有太多问题.

/**
 * @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);
Run Code Online (Sandbox Code Playgroud)

这将翻译:

/page ==> /page/
/page?query=value ==> /page/?query=value
Run Code Online (Sandbox Code Playgroud)


Ron*_*eva 5

一班轮:

router.get('\\S+\/$', function (req, res) {
  return res.redirect(301, req.path.slice(0, -1) + req.url.slice(req.path.length));
});
Run Code Online (Sandbox Code Playgroud)

这只会捕获需要重定向的网址,而忽略其他网址。

结果示例:

/         ==> /
/a        ==> /a
/a/       ==> /a
/a/b      ==> /a/b
/a/b/     ==> /a/b
/a/b/?c=d ==> /a/b?c=d
Run Code Online (Sandbox Code Playgroud)