具有不同参数的多个路由,调用相同的资源
Posted
技术标签:
【中文标题】具有不同参数的多个路由,调用相同的资源【英文标题】:multiple routes with differents params, calling the same ressource 【发布时间】:2014-04-08 05:31:11 【问题描述】:expressjs 是否可以有多个路由调用同一个资源,类似这样:
app.get('/users/:user_id', users.getOne)
app.get('/users/:username', users.getOne)
我希望能够调用 users.getOne 获取请求中使用的任何参数(:user_id 或 :username)。
在 users.getOne 函数中,我如何确定使用了哪一个并根据它构建我的查询?
exports.getOne = function(req, res)
var queryParams = ? // I need help here
Users
.find(queryParams)
...
谢谢!
可能相关:express.js - single routing handler for multiple routes in a single line
【问题讨论】:
如果有人选择的用户名与您的某个用户 ID 冲突怎么办? 用户名限制为 16 个字符。而 user_id 是 mongoDB 生成的 hash 希望是 24 个字符。 【参考方案1】:在 express 看来,这两个路由都将匹配同一组请求 URL。您只需要其中一个,您可以将其命名为更有意义:
app.get('/users/:key', users.getOne);
//...
// http://***.com/a/20988824/266795
var OBJECT_ID_RE = /^[a-f\d]24$/i;
exports.getOne = function(req, res)
var conditions = _id: req.params.key;
if (!OBJECT_ID_RE.test(req.params.key))
conditions = username: req.params.key;
Users.find(conditions)...
如果您最终在整个代码库中的许多路线中都需要这种模式,您可以将其提取到 /users/:user
参数中并按照 @alex 的回答使用 app.param
,但封装代码以定位用户并粘贴它转到req.user
,因此实际的路由处理程序可以假设在执行时已正确找到并加载用户,并且404处理也可以集中处理。
【讨论】:
感谢您的解决方案,它正在工作,但我想知道是否存在完全不同的解决方法。我的意思是,首先,我是否以正确的方式解决问题?这是一个想法吗?如果你想实现这样的目标,你真的会怎么做? @inwpitrust 不,两次创建完全相同的路线不是正确的方法。彼得展示了一个好方法。 是的,不,我的意思是,忘记我的代码,但是在设计 RESTful API 时,Peter 的解决方案是您解决这个问题的方式吗?通过 :id 或 :username 检索用户数据,您认为我应该启用此功能吗? RESTful 意味着 ID 进入 URL,而不是用户名。但我会毫不犹豫地违反 REST 约定,因为我个人认为它们充其量只是 meh。通过其他字段查找内容是一种搜索,应该使用查询字符串恕我直言,但我是老派,因为我认为查询字符串实际上是一个好主意,我不觉得有必要将其重新实现为 URL 路径参数让我的网址“干净”。【参考方案2】:在 express 看来,实际上是同一条路线。
不,他们不是。一条路由有:user_id
参数,另一条有:username
。
这将是一个适当的解决方案:
var OBJECT_ID_RE = /^[a-f\d]24$/i;
app.param('user_id', function(req, res, next, value, name)
if (OBJECT_ID_RE.test(value))
next()
else
next('route')
)
app.get('/users/:user_id', users.getOne)
app.get('/users/:username', users.getOne)
app.param
设置要调用的路由的先决条件。这样当 user_id 匹配一个模式时,第一个路由被调用,否则第二个。
【讨论】:
好的,澄清一下,它们都匹配相同的 URL,因此需要next('route')
,恕我直言,这是一种代码味道,您可能正试图对您的路由过于花哨。我不喜欢花哨的路由。我喜欢非常简单、明显、非魔法、易于调试的路由。也就是说,您的解决方案确实非常适合 express。
next('route')
是忽略中间件中特定路由的标准方式。唯一的缺点是调用依赖于排序,但很容易修复。以上是关于具有不同参数的多个路由,调用相同的资源的主要内容,如果未能解决你的问题,请参考以下文章
Laravel中的路由问题,带有多个控制器和具有相同名称的不同路由[关闭]