Node.js expressjs/nodejs常规路由与通配符冲突
Node.js expressjs/nodejs常规路由与通配符冲突,node.js,express,Node.js,Express,完整代码如下所示 /*/login[get]*/ app.get('/login',函数(req,res){ res.render(“登录”); 回来 }); app.get('/stats',requireLogin,函数(req,res){ findOne({u id:req.User.id}) .populate('当前') .exec(函数(错误、统计){ if(err)res.json(err) res.render('stats',stats); 回来 }) }); /*/用户名*/
完整代码如下所示
/*/login[get]*/
app.get('/login',函数(req,res){
res.render(“登录”);
回来
});
app.get('/stats',requireLogin,函数(req,res){
findOne({u id:req.User.id})
.populate('当前')
.exec(函数(错误、统计){
if(err)res.json(err)
res.render('stats',stats);
回来
})
});
/*/用户名*/
app.get('/:username',requireLogin,函数(req,res){
控制台日志(“sdf”);
使用者
.findOne({username:req.params.username},'friends')
.exec(函数(错误,用户){
console.log(用户)
})
转到/login会呈现登录页面,但也会触发控制台。来自下一条路线的sdf的日志由Express按顺序处理。因此,如果您将/stats
路线放在/:username
路线之前,并且您没有通过调用next()手动强制路线继续
,然后事情会对你有用。首先会找到并处理更具体的路线
但是,当您有冲突的URL时,这可能是一个糟糕的URL设计。如果一个用户被命名为“stats
”,那么他们的用户名URL将永远不会工作。如果您想要其他URL,例如/login
或/about
。所有这些都将与潜在的用户名冲突。这只是一个糟糕的设计
也许,您应该改成这样:
app.get('/user/:username', function(req, res) {...}
因此,没有任何用户名路由可以与您的/stats
路由或您选择的任何其他顶级路由冲突。这将保持您的顶级路径可用于将路由定向到类别中,这将是一个更好的URL设计
而且,正如我们在进一步的讨论中发现的那样,浏览器为页面请求favicon时也会点击您的/:username
路径。您可以为favicon创建一个特殊路径,或者您可以在页面中插入元标记以防止favicon请求,或者您可以停止使用捕获这些类型内容的顶级通配符路径。否te,您可能也会捕捉到类似机器人请求时的情况。路线由Express按顺序处理。因此,如果您将/stats
路线放在/:username
路线之前,并且您不会通过调用next()手动强制路线继续
,然后事情会对你有用。首先会找到并处理更具体的路线
但是,当您有冲突的URL时,这可能是一个糟糕的URL设计。如果一个用户被命名为“stats
”,那么他们的用户名URL将永远不会工作。如果您想要其他URL,例如/login
或/about
。所有这些都将与潜在的用户名冲突。这只是一个糟糕的设计
也许,您应该改成这样:
app.get('/user/:username', function(req, res) {...}
因此,没有任何用户名路由可以与您的/stats
路由或您选择的任何其他顶级路由冲突。这将保持您的顶级路径可用于将路由定向到类别中,这将是一个更好的URL设计
而且,正如我们在进一步的讨论中发现的那样,浏览器为页面请求favicon时也会点击您的/:username
路径。您可以为favicon创建一个特殊路径,或者您可以在页面中插入元标记以防止favicon请求,或者您可以停止使用捕获这些类型内容的顶级通配符路径。否此外,您可能还会捕捉到诸如当机器人请求时之类的信息/robots.txt
(/:username路由是代码中的最后一个路由)
如果您已将用户名路由放在所有其他路由的最后一个,则它应该可以工作。
如果希望用户名路由位于顶部,则可以在/:username路由中进行验证,但不建议这样做,而且设计不好
var reseredKeywords = ['stats', 'login'];
app.get('/:username', function(req, res, next) {
if (reseredKeywords.indexOf(req.param.username.toLowerCase())) {
next();
}
// else handle your username here
})
(/:username路由是代码中的最后一个路由)
如果您已将用户名路由放在所有其他路由的最后一个,则它应该可以工作。
如果希望用户名路由位于顶部,则可以在/:username路由中进行验证,但不建议这样做,而且设计不好
var reseredKeywords = ['stats', 'login'];
app.get('/:username', function(req, res, next) {
if (reseredKeywords.indexOf(req.param.username.toLowerCase())) {
next();
}
// else handle your username here
})
为什么你不能在路由之前添加一些上下文呢?比如/user/:username
?我希望它能像其他所有主要社交网络一样工作。为什么你不能在路由之前添加一些上下文呢?比如/user/:username
?我希望它能像其他所有主要社交网络一样工作。这确实不是一个好的总体设计。URL设计只是有缺陷,因为您可能希望在URL中使用的每个顶级路径组件都可能与用户名发生冲突。应该更改和修复URL设计,以避免这些冲突。@jfriend00,Twitter和Facebook如何处理它?@totalnoob您在Facebook.Yo中没有用户名作为设置或组你必须提供名字和姓氏。你的个人资料将是facebook.com/
etc@totalnoob-Facebook制造了一个混乱,他们被限制在URL中可以使用的顶级路径项上。不要复制。仅仅因为其他人以一种方式这样做并不意味着这是一个很好的设计。如果你想预先确定你想在你的URL中使用的所有顶级路径元素,然后阻止任何用户名被创建。一旦创建了用户名,你就永远不能将其作为顶级路径元素,然后继续,但在我看来,这是一个脆弱的设计,我永远不会重新推荐我只是说使用http://example.com/username
会造成难以维护的混乱,因为您可能希望在URL设计中使用的所有可能的顶级路径名都可能与用户名冲突。设计这样的冲突不是URL设计的良好起点。它会迫使您非常小心地在adv中保留请输入您需要的任何顶级路径名