具有不同参数的多个路由,调用相同的资源

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 REST 路由

Laravel中的路由问题,带有多个控制器和具有相同名称的不同路由[关闭]

使用具有不同片段字段的相同中继根查询的多个 react-router-relay 路由

Symfony:具有不同参数的多个路由,默认为空

查询参数更改时,路由未更新

具有相同路由前缀 ASP.NET Web Api 的多个控制器类型