【问题标题】:NodeJS - Wrong Express route being triggeredNodeJS - 触发了错误的 Express 路由
【发布时间】:2019-08-24 01:53:02
【问题描述】:

我有以下路线可用于后端...

admin.js

router.get('/contents', ...);  // GET /admin/contents

router.get('/:adminID', ...);  // GET /admin/[adminID]

router.put('/:adminID', ...);  // PUT /admin/[adminID]

router.get('/', ...);  // GET /admin

router.post('/', ...);  // POST /admin

.. 但在测试中,如下:

PUT /admin/contents

触发PUT /admin/[adminID] 路由。但“内容”不是 ID。我理解为什么会发生这种情况(即它符合模式),但我不确定最好/常见的解决方案是什么?理想情况下,我希望它能够识别“内容”不是 ID,实际上只是尝试使用不可用的端点。

我可以使用类似...

router.use('/contents', require('./admin-contents'));

但我更愿意将每个顶级端点限制为单个文件,而不是将其分散到这么多文件中。

在最坏的情况下,它将查找 ID 为“contents”的管理员,并返回“找不到管理员”,但我希望它返回 404,因为这不是/admin 的可用端点.

编辑#1

澄清一下,adminID 是字母和数字的混合体,它们都出现在字符串的任何位置。正则表达式不起作用。

另外,/admin/contents 的唯一路径是GET。必须为所有其他方法(PUTPATCHDELETE 等)实现空白路由也不理想。

【问题讨论】:

  • A regex will not work。如果 adminId 至少包含一个数字和一个字母,那么正则表达式肯定会起作用。
  • 好的,我知道了。是啊,你说得对。如果您想修改下面的答案以进行类似检查(即在已知长度的 ID 字符串中查找任何数字),我会给您金牌

标签: node.js rest api express routes


【解决方案1】:

您可以在路由中的参数名称之后提供regex,以避免这种情况。

router.put('/:adminID(\\d+)', (req, res) => {
   console.log(req.params.adminID); // I'm a number
});

现在adminID必须是数字,否则不会进入路由。

虽然 express routing 上没有直接记录,但由于 express 使用 path-to-regexp,我们可以查看他们的文档:

它记录在Custom Matching Parameters

const regexpNumbers = pathToRegexp('/icon-:foo(\\d+).png')
// keys = [{ name: 'foo', ... }]

regexpNumbers.exec('/icon-123.png')
//=> ['/icon-123.png', '123']

regexpNumbers.exec('/icon-abc.png')
//=> null

更新

您建议只检查一个已知长度的数字 字符串应该可以工作,

app.put('/:adminID((?:\\w+(?<=\\d+)(?:\\w+)?))', (req, res) => {
   // I have at least 1 number
   // I can have or not alpha-numeric characters
   res.send(req.params.adminID);
});

正则表达式使用Postive lookbehind assertions,自Node.js 9.11.2 以来没有任何标志支持。因此,如果您使用的是旧版本,请升级或使用 --harmony 标志来运行它。

【讨论】:

  • ID 是字符串,包含数字和字母
  • 然后为您的完全匹配构建正则表达式,或在您的问题中提供完整示例。不过,这是您正在寻找的解决方案。我给你工具。
  • 那么,请给我们一个您需要匹配的 ID 示例?
  • 将它们视为 YouTube 链接。一个字符串,长度为 x 个字符,其中任何字符可以是任何数字或字母(大写和小写)。从技术上讲,ID 可能是用于路由的真正 x 字符串,但这不太可能
  • 所以它可能是:aaa bb22 bAc22222 根本没有模式?如果它可能是用于路由的 x 字符串,则您可能会发生冲突,并且您的路由是错误的。
【解决方案2】:

您可以利用节点按顺序解释处理程序的事实:

app.put('/admin/contents',  (req, res) => res.send('contents'))
app.put('/admin/:adminId',  (req, res) => res.send('id'))

当您输入admin/contents时,返回contents,对于任何其他url admin/whatever返回id

【讨论】:

  • 但是PUT /admin/contents 不是我需要的路线。对于/admin/contents,只有GET 路由。你建议的方式意味着我需要包括 PUTPOSTPATCH 等等,一直在列表中
  • 那么router.get('/admin/contents', ...); router.get('/admin/:adminID', ...); 有什么问题?
  • 这只是防止不良行为的又一步。 /admin/contents 是一条路线,只是不适用于 PUT 方法。我想确保这样识别不可用的方法,以便我可以返回正确的错误。返回“不可用的端点”将比“不可用的管理员 ID”提供更多信息(也更正确)。当有人试图找出错误所指的 ID 时,后者可能特别令人困惑。
  • 好的,我现在明白了。我认为你应该重新考虑你的 API 更加面向资源 - /admin/admins/userId 应该负责管理员管理,/admin/contents 应该提供内容资源。
  • 您还可以创建以下处理程序顺序: 1. get('/admin/contents', ...) 2. all('/admin/contents',(req, res) =&gt; res.status(404).send('Not found')) 3. //rest of handlers - 您当然需要手动处理 404,但您可以摆脱疯狂和难以维护正则表达式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 2014-10-03
  • 1970-01-01
相关资源
最近更新 更多