LabHub
学习 学习路径 课程

Node.js 后端 — 框架藏起来的东西

路由器就是一张表

在 LabHub 中继续学习

一句话总结

框架的路由器并不是魔法,而只是一张表:以方法和路径为键,以处理程序为值进行查找。这张表区分哪些情况,决定了 API 的行为特征。

概念图: 一张表 · 先收集所有路径匹配的规则 · 注册顺序 · 模式的覆盖范围

为什么需要它——404 和 405 是两种不同的事件

假设向 /items 发送 DELETE 请求。路径存在,只是该路径不接受这个方法。如果返回 404,客户端会理解成“没有这个资源”,转而怀疑路径;如果返回 405,客户端会理解成“资源存在,但不允许执行这个操作”。调试所需的时间就在这里产生差异。

使用框架时,这种区分通常免费就能得到。也正因为如此,如果从未亲手实现过,甚至可能不知道两者本来就需要区分。

如何组织这张表

const routes = [
  { method: 'GET',  path: /^\/healthz$/,     handler: health },
  { method: 'GET',  path: /^\/items$/,       handler: listItems },
  { method: 'POST', path: /^\/items$/,       handler: createItem },
  { method: 'GET',  path: /^\/items\/(\d+)$/, handler: getItem },
];

查找过程分成两步:先收集所有路径匹配的规则,再从中选择方法匹配的规则。没有任何路径匹配时返回 404;路径匹配但没有对应方法时返回 405。如果一次性按 method + path 查找,这种区分就会消失。

在实际项目中

无论 Nest 还是 Express,都只是通过装饰器或 app.get() 来填充这张表,底层结构并没有不同。因此,路由失效时要检查的地方也一样:注册顺序模式的覆盖范围。如果把宽泛的模式(/*)放在前面,后面的规则将永远无法到达。这个陷阱与 Envoy 实验中看到的完全相同,也是实际工作中最常见的故障报告之一。

第一次阅读一个框架时,可以先从路由器开始,因为它展示了这个框架如何划分世界。