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