Express 如何避免已匹配路由仍触发全局404,仅未匹配请求走404处理
问题根因
- 原代码将前后置日志中间件挂载在Router全局层级,会对所有进入该Router的请求生效,而非仅对/foo这类已匹配的有效路由生效,直接引发两个异常:
- 未匹配的请求也会触发前后置日志,和预期输出不符
- 只要链路在中间件中没有主动终止,就会一路传递到app层级的
app.get("*")404路由,哪怕/foo已经完成响应处理
- /foo路由处理中
res.send()后主动调用next()的写法,会将控制权持续向下传递,若后续中间件未主动终止链路,就会误触发404逻辑。
调整方案
把全局挂载的前后置中间件,从Router根层移到/foo路由的专属处理链上,同时在后置日志中间件执行完后主动终止链路,避免请求继续向下传递到404路由。
调整后的核心代码结构:
app = express(); router = express.Router(); // 将前后置中间件绑定为/foo路由的专属处理链 router.get('/foo', // 前置日志 (req, res, next) => { console.log("my middleware before"); next(); }, // 核心路由处理 (req, res, next) => { console.log("My route"); res.send("<h1>Hello</h1>"); next(); // 传递到后置日志逻辑 }, // 后置日志 (req, res, next) => { console.log("my middleware after"); // 不调用next(),直接终止当前链路,避免传到后续404路由 } ); app.use("/", router); app.get("*", (req, res, next) => { console.log("page not found"); throw new Error("Not Found"); }); app.use((err, req, res, next) => { console.log("Error occure"); res.send("<h1>Error</h1>"); }); app.listen(3000);
效果说明
- 请求/foo时:按顺序打印前置日志、路由日志、后置日志,返回Hello页面,链路在后置中间件处终止,不会触发404逻辑,完全匹配预期
- 请求任意未定义路径时:因没有匹配到/foo路由,Router层没有匹配的处理逻辑,请求直接传递到app层的404路由,打印404日志,进入错误处理流程,返回错误页面,不会触发前后置日志,完全匹配预期。
内容的提问来源于stack exchange,提问作者damjuve
相关产品推荐
相关产品推荐

