可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am using Node.js and Express and I have the following routing :
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 Disqus widget on my lessons pages and I have noticed a strange behavior that when going to myapp.com/lessons
and 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).
Is there a way to "canonize" all of my urls to be without trailing slashes ? I have tried to add the strict routing
flag to express but the results were the same
Thanks
回答1:
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(); });
回答2:
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.
回答3:
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
回答4:
I'm adding this answer because I had too many issues with other solutions.
router.use(function(req, res, next) { if (req.originalUrl != req.baseUrl + req.url) { res.redirect(301, req.baseUrl + req.url); } else next(); });
This will translate:
/page ==> /page/ /page?query=value ==> /page/?query=value
回答5:
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 str