web-dev-qa-db-fra.com

Rediriger toutes les barres obliques de fin dans le monde entier dans express

J'utilise Node.js et Express et j'ai le routage suivant:

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);

J'ai un widget Disqus sur mes pages de leçons et j'ai remarqué un comportement étrange qui indique que lorsque je passe à myapp.com/lessons et myapp.com/lessons/, deux pages différentes (un commentaire que j'avais précédemment ajouté dans Disqus et l'autre ne t avoir un commentaire).

Existe-t-il un moyen de "canoniser" toutes mes URL sans les slash? J'ai essayé d'ajouter le drapeau strict routing à exprimer, mais les résultats étaient les mêmes

Merci 

29
Michael

Essayez d'ajouter un middleware pour cela;

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();
});
52
Tolga Akyüz

La réponse de Tolga Akyüz est inspirante mais ne fonctionne pas s'il y a des caractères après la barre oblique. Par exemple, http://example.com/api/?q=a est redirigé vers http://example.com/api au lieu de http://example.com/api?q=a.

Voici une version améliorée du middleware proposé qui résout le problème en ajoutant la requête d'origine à la fin de l'URL de destination de la redirection:

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();
    }
});

Remarque: Comme indiqué par jamesk et indiqué dans RFC 1738 , la barre oblique finale ne peut être omise que lorsqu'il n'y a rien après le domaine. Par conséquent, http://example.com?q=a est une URL non valide, où http://example.com/?q=a est valide. Dans ce cas, aucune redirection ne doit être effectuée. Heureusement, l'expression req.path.length > 1 s'en occupe. Par exemple, étant donné l'URL http://example.com/?q=a, le chemin req.path est égal à / et la redirection est donc évitée.

70
Akseli Palén

Le middleware connect-slashes a été conçu spécifiquement pour ce besoin: https://npmjs.org/package/connect-slashes

Installez-le avec:

$ npm install connect-slashes

Lisez la documentation complète: https://github.com/avinoamr/connect-slashes

23
Roi Avinoam

J'ajoute cette réponse car j'avais trop de problèmes avec d'autres solutions.

router.use(function(req, res, next) {
    if (req.originalUrl != req.baseUrl + req.url) {
        res.redirect(301, req.baseUrl + req.url);
    }
    else
        next();
});

Cela traduira:

/page ==> /page/
/page?query=value ==> /page/?query=value
5
ShortFuse

Bon mot:

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

Cela ne fera que capturer les URL qui doivent être redirigées et ignorer les autres. 

Exemple de résultats:

/         ==> /
/a        ==> /a
/a/       ==> /a
/a/b      ==> /a/b
/a/b/     ==> /a/b
/a/b/?c=d ==> /a/b?c=d
3
Ronen Teva

Les réponses ci-dessus fonctionnent dans de nombreux cas, mais les opérateurs GET peuvent rencontrer des problèmes et si vous placiez cela dans un autre middleware express, sa dépendance sur req.path causera un problème et sa dépendance sur req.url peut également avoir des effets secondaires indésirables . Si vous êtes à la recherche d'une solution plus étroite, le problème est résolu:

// 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);
});

Il est toujours satisfait des variables GET et ne casse pas si vous le placiez dans un middleware.

0
user2687646