Express路由中间件在Server类外部无法生效的解决方案咨询
Express类外部路由无法触发中间件的问题解决
在Express项目中,将路由注册在Server类外部时,请求该路由会跳过已配置的中间件,但类内部注册的路由能正常触发中间件。以下是复现问题的代码:
const express = require("express"); const cors = require("cors"); const axios = require("axios"); class Server { constructor() { this.app = express(); } loadMiddlewares() { this.app.use(cors()); this.app.use((req, res, next) => { console.log("MIDDLEWARE WORKING!"); next(); }); this.app.use(express.json()); } init() { this.loadMiddlewares(); this.app.post("/post", function (req, res) { /* MIDDLEWARES WORKS */ res .status(200) .send(`WORKING: Here is your body ${JSON.stringify(req.body)}`); }); this.app.listen(3001); console.log("Server runinng"); } } const server = new Server(); server.app.post("/post2", function (req, res) { /* MIDDLEWARES NOT WORKING */ res .status(200) .send(`NOT WORKING: Here is your body 2 ${JSON.stringify(req.body)}`); }); server.init(); setTimeout(() => { axios({ url: "https://6uiyik.sse.codesandbox.io/post", method: "post", data: { hi: "HIII!!" } }).then((res) => console.log(res.data)); axios({ url: "https://6uiyik.sse.codesandbox.io/post2", method: "post", data: { hi: "HIII!!" } }).then((res) => console.log(res.data)); }, 1000);
问题原因
核心问题是中间件与路由的注册顺序:
- 外部的
/post2路由在server.init()调用前就完成了注册 init()方法内部才执行loadMiddlewares()加载中间件,相当于中间件是在/post2路由之后注册的- Express按注册顺序匹配执行逻辑,请求
/post2时会先匹配到已注册的路由并直接处理,不会再执行后续注册的中间件
解决方案
方案1:调整注册顺序,先加载中间件再注册外部路由
将外部路由的注册代码移到server.init()之后,确保中间件先完成加载:
const express = require("express"); const cors = require("cors"); const axios = require("axios"); class Server { constructor() { this.app = express(); } loadMiddlewares() { this.app.use(cors()); this.app.use((req, res, next) => { console.log("MIDDLEWARE WORKING!"); next(); }); this.app.use(express.json()); } init() { this.loadMiddlewares(); this.app.post("/post", function (req, res) { res.status(200).send(`WORKING: Here is your body ${JSON.stringify(req.body)}`); }); this.app.listen(3001); console.log("Server running"); } } const server = new Server(); server.init(); // 先初始化加载中间件 // 再注册外部路由 server.app.post("/post2", function (req, res) { res.status(200).send(`WORKING NOW: Here is your body 2 ${JSON.stringify(req.body)}`); }); setTimeout(() => { axios({ url: "http://localhost:3001/post", method: "post", data: { hi: "HIII!!" } }).then((res) => console.log(res.data)); axios({ url: "http://localhost:3001/post2", method: "post", data: { hi: "HIII!!" } }).then((res) => console.log(res.data)); }, 1000);
方案2:在Server类中添加路由注册方法
封装一个安全的路由注册方法,确保外部路由始终在中间件加载后添加:
const express = require("express"); const cors = require("cors"); const axios = require("axios"); class Server { constructor() { this.app = express(); } loadMiddlewares() { this.app.use(cors()); this.app.use((req, res, next) => { console.log("MIDDLEWARE WORKING!"); next(); }); this.app.use(express.json()); } // 新增路由注册方法 addRoute(method, path, handler) { this.app[method](path, handler); } init() { this.loadMiddlewares(); this.app.post("/post", function (req, res) { res.status(200).send(`WORKING: Here is your body ${JSON.stringify(req.body)}`); }); this.app.listen(3001); console.log("Server running"); } } const server = new Server(); server.init(); // 通过类方法添加外部路由 server.addRoute("post", "/post2", function (req, res) { res.status(200).send(`WORKING NOW: Here is your body 2 ${JSON.stringify(req.body)}`); });
方案3:使用Express Router模块
将外部路由封装成独立的Router模块,在Server类的init方法中挂载:
const express = require("express"); const cors = require("cors"); const axios = require("axios"); // 外部路由模块(可单独拆分为独立文件) const externalRouter = express.Router(); externalRouter.post("/post2", function (req, res) { res.status(200).send(`WORKING NOW: Here is your body 2 ${JSON.stringify(req.body)}`); }); class Server { constructor() { this.app = express(); } loadMiddlewares() { this.app.use(cors()); this.app.use((req, res, next) => { console.log("MIDDLEWARE WORKING!"); next(); }); this.app.use(express.json()); } init() { this.loadMiddlewares(); this.app.post("/post", function (req, res) { res.status(200).send(`WORKING: Here is your body ${JSON.stringify(req.body)}`); }); // 挂载外部路由模块 this.app.use(externalRouter); this.app.listen(3001); console.log("Server running"); } } const server = new Server(); server.init();
内容的提问来源于stack exchange,提问作者Franco
相关产品推荐
相关产品推荐

