【问题标题】: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 个字符。

标签: node.js rest express mongoose


【解决方案1】:

在 express 看来,这两个路由都将匹配同一组请求 URL。您只需要其中一个,您可以将其命名为更有意义:

app.get('/users/:key', users.getOne);

//...
// http://stackoverflow.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') 是忽略中间件中特定路由的标准方式。唯一的缺点是调用依赖于排序,但很容易修复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-15
  • 2019-10-26
  • 2018-01-07
  • 1970-01-01
  • 2021-05-26
  • 2021-04-21
  • 2018-02-18
相关资源
最近更新 更多