You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为/api下不同子路由配置不同Express中间件(无需逐个设置)?

问题

希望在/api路径下的不同路由使用不同的中间件处理器,让不同API路由支持不同认证方式。尝试将不同API路由嵌套在两个带有不同中间件的Router中,代码如下:

const express = require("express");

const app = express();
const port = 4000;

const one = express.Router();
one.use((req, res, next) => {
  console.log("one");
  next();
});
one.get("/api/one", (req, res) => {
  console.log("/api/one");
  res.send("one");
});

// ---

const two = express.Router();
two.use((req, res, next) => {
  console.log("two");
  next();
});
two.get("/api/two", (req, res) => {
  console.log("/api/two");
  res.send("two");
});

// ---

app.get("/", (req, res) => {
  res.send("Hello World!");
});
app.use(one);
app.use(two);

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

期望访问/api/one时仅打印"one",访问/api/two时仅打印"two",但实际访问/api/two时两个中间件都执行了:

Example app listening on port 4000
one
/api/one
one
two
/api/two

请问是否有办法实现需求且无需为每个API路由单独列出不同中间件?

解决方案

问题根源在于你给子Router定义了完整的/api/xxx路由,同时直接将Router挂载到根路径。Express中,当你用app.use(one)挂载Router时,它会匹配所有请求,接着检查Router内部的路由是否匹配,不匹配就会继续向下传递,导致多个Router的中间件被触发。

方法一:给子Router指定挂载前缀

给每个子Router设置挂载前缀,同时子Router内部使用相对路径:

const express = require("express");

const app = express();
const port = 4000;

const one = express.Router();
one.use((req, res, next) => {
  console.log("one");
  next();
});
// 内部路由写相对路径,对应挂载后的/api/one
one.get("/", (req, res) => {
  console.log("/api/one");
  res.send("one");
});

const two = express.Router();
two.use((req, res, next) => {
  console.log("two");
  next();
});
two.get("/", (req, res) => {
  console.log("/api/two");
  res.send("two");
});

app.get("/", (req, res) => {
  res.send("Hello World!");
});
// 只有请求路径匹配前缀时,才会触发对应Router的中间件
app.use("/api/one", one);
app.use("/api/two", two);

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

这样修改后,访问/api/one仅触发one的中间件,访问/api/two仅触发two的中间件,无需为单个路由单独配置中间件。

方法二:使用层级Router(适合多API路由场景)

先创建一个根/api Router,再将不同子Router挂载到它下面,结构更清晰:

const express = require("express");

const app = express();
const port = 4000;

// 根API Router
const apiRouter = express.Router();

const one = express.Router();
one.use((req, res, next) => {
  console.log("one");
  next();
});
one.get("/", (req, res) => {
  console.log("/api/one");
  res.send("one");
});

const two = express.Router();
two.use((req, res, next) => {
  console.log("two");
  next();
});
two.get("/", (req, res) => {
  console.log("/api/two");
  res.send("two");
});

// 挂载子Router到根API Router
apiRouter.use("/one", one);
apiRouter.use("/two", two);

// 将根API Router挂载到/app路径
app.use("/api", apiRouter);

app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

这种方式的层级结构更易于维护,尤其适合API路由较多的项目。

内容的提问来源于stack exchange,提问作者Stuart K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 17:57:02