中间件

Express框架中,中间件用于拦截所有或部分请求,并对这部分请求和响应上下文进行统一处理。中间件的概念类似Java中的拦截器或过滤器,常用于实现日志记录、身份验证、请求解析等通用功能。

中间件的基本概念

中间件本质上是一个函数,它可以访问请求对象req、响应对象res以及next函数。中间件可以执行以下操作:

  • 执行代码逻辑
  • 修改请求和响应对象
  • 结束请求响应循环
  • 调用下一个中间件

下面是一个最简单的中间件示例。

const myMiddleware = (req, res, next) => {
  console.log("middleware handled");
  next();
};

注意:中间件中如果需要将请求继续向下一个处理函数传递,必须调用next()方法;如果是实现类似登录拦截的功能,则直接响应请求即可,无需调用next()

注册中间件

全局中间件

使用app.use()可以注册全局中间件,它会拦截所有请求。

import express from "express";

const app = express();

// 注册全局中间件
app.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
});

app.listen(3000);

路径前缀中间件

中间件中可以指定路径前缀,此时只会匹配该前缀开头的请求。

app.use("/api", (req, res, next) => {
  console.log("API request");
  next();
});

注意:使用app.use()注册中间件时,指定的路径是前缀匹配的。

路由级中间件

中间件也可以只应用于特定路由,下面例子代码中,authMiddleware只对/protected生效。

const authMiddleware = (req, res, next) => {
  if (req.headers.authorization) {
    next();
  } else {
    res.status(401).json({ error: "Unauthorized" });
  }
};

app.get("/protected", authMiddleware, (req, res) => {
  res.json({ message: "Protected data" });
});

中间件执行顺序

中间件按照注册顺序依次执行。

import express from "express";

const app = express();

app.use((req, res, next) => {
  console.log("First middleware");
  next();
});

app.use((req, res, next) => {
  console.log("Second middleware");
  next();
});

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

app.listen(3000);

内置中间件

Express框架包含了几个实用的内置中间件。

解析请求体中间件

Express提供了解析JSON和URL编码请求体的内置中间件。

import express from "express";

const app = express();

// 解析 JSON 请求体
app.use(express.json());

// 解析 URL 编码的请求体
app.use(express.urlencoded({ extended: true }));

app.post("/data", (req, res) => {
  console.log(req.body);
  res.json({ received: req.body });
});

app.listen(3000);

静态资源中间件

静态资源中间件可以指定一个路径,其中的文件会以静态资源的方式提供。

import express from "express";
import path from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const app = express();

app.use("/static", express.static(path.join(__dirname, "static")));

app.listen(3000);

其中/static是路径前缀,比如服务器上指定文件夹里有一个1.txt文件,那么它的URL路径就是/static/1.txt

注意:在ESM模块中,__dirname不能直接使用,需要通过import.meta.url手动计算获取。

错误处理中间件

Express支持一个特殊的错误处理中间件,它需要4个参数:errreqresnext

import express from "express";

const app = express();

app.get("/error", (req, res, next) => {
  const err = new Error("Something went wrong");
  next(err);
});

// 错误处理中间件(必须有4个参数)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: err.message });
});

app.listen(3000);

Express框架会自动捕捉HTTP请求处理中的异常,交给错误处理中间件进行处理,注意错误处理中间件应该在路由之后注册。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。