ExpressJS - 中间件
Express.js - 理解中间件
Section titled “Express.js - 理解中间件”中间件(Middleware)函数是 Express.js 的核心。它们是能够访问请求对象(req)、响应对象(res)以及应用程序请求-响应周期中的 next 函数的函数。中间件可以执行任何代码,修改请求和响应对象,终止请求-响应周期,或者调用堆栈中的下一个中间件。
可以将中间件想象成请求必须通过的一系列检查点。在每个检查点,您都可以检查、修改甚至拒绝请求。
中间件的类型
Section titled “中间件的类型”Express 中间件可以分为以下几种类型:
- 应用级中间件: 使用
app.use()或app.METHOD()绑定到应用程序对象app上。 - 路由级中间件: 工作方式与应用级中间件相同,但绑定到
express.Router()实例上。 - 错误处理中间件: 具有
(err, req, res, next)的特殊签名,用于处理错误。 - 内置中间件: Express 包含的标准中间件函数,例如
express.json()和express.static()。 - 第三方中间件: 可作为
npm包使用的中间件,如helmet或morgan。
创建自定义中间件
Section titled “创建自定义中间件”让我们创建一个简单的日志中间件,用于打印每个传入请求的时间戳和方法。
示例:一个简单的请求日志记录器
Section titled “示例:一个简单的请求日志记录器”import express from 'express';
const app = express();const PORT = 3000;
// Custom logger middlewareconst requestLogger = (req, res, next) => { const timestamp = new Date().toISOString(); console.log(`[${timestamp}] ${req.method} ${req.originalUrl}`);
// 这个函数调用至关重要!它将控制权传递给下一个中间件。 // 如果没有它,请求将一直挂起。 next();};
// Apply the middleware to all routesapp.use(requestLogger);
app.get('/', (req, res) => { res.send('Hello World!');});
app.get('/about', (req, res) => { res.send('This is the about page.');});
app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`);});当您运行此服务器并访问 http://localhost:3000/ 时,您的控制台将显示:
Server is running on http://localhost:3000[2023-10-27T10:30:00.123Z] GET /路径特定中间件
Section titled “路径特定中间件”您可以通过将路径作为 app.use() 的第一个参数来将中间件应用于特定路由或一组路由。
const adminAuth = (req, res, next) => { // 在实际应用中,您会检查身份验证凭据 console.log('Admin auth check passed!'); next();};
// 此中间件仅对 /admin 及其子路由的请求运行app.use('/admin', adminAuth);
app.get('/admin/dashboard', (req, res) => { res.send('Welcome to the Admin Dashboard');});中间件的顺序很重要
Section titled “中间件的顺序很重要”中间件函数按顺序执行,因此您包含它们的顺序至关重要。请求将逐一通过它们。
// 中间件 1:第一个执行app.use((req, res, next) => { console.log('First Middleware: Setting request time'); req.requestTime = Date.now(); next();});
// 中间件 2:第二个执行app.use((req, res, next) => { console.log('Second Middleware: Logging request time'); console.log(`Request received at: ${new Date(req.requestTime).toLocaleTimeString()}`); next();});
app.get('/', (req, res) => { res.send(`Request was processed.`);});如果一个中间件函数不调用 next(),它必须自行终止请求-响应周期(例如,通过调用 res.send() 或 res.json())。否则,请求将挂起。
内置和常用第三方中间件
Section titled “内置和常用第三方中间件”Express 带有功能强大的内置中间件,而 npm 生态系统为常见任务提供了无数更多的中间件。
内置:express.json() 和 express.urlencoded()
Section titled “内置:express.json() 和 express.urlencoded()”以前,需要 body-parser 包来解析传入的请求体。此功能现在已直接内置于 Express 中。
// 用于解析 JSON 格式的请求体app.use(express.json());
// 用于解析 URL 编码的请求体(例如,来自 HTML 表单)app.use(express.urlencoded({ extended: true }));
app.post('/api/users', (req, res) => { // req.body 现在填充了已解析的数据 const newUser = req.body; console.log(newUser); res.status(201).json(newUser);});第三方:cookie-parser
Section titled “第三方:cookie-parser”此中间件解析 Cookie 头,并使用以 cookie 名称为键的对象填充 req.cookies。
# 安装npm install cookie-parser
# 使用import cookieParser from 'cookie-parser';app.use(cookieParser());
app.get('/set-cookie', (req, res) => { res.cookie('username', 'john.doe', { httpOnly: true }); res.send('Cookie has been set!');});
app.get('/read-cookie', (req, res) => { // 从 req.cookies 访问 cookie const username = req.cookies.username; res.send(`Hello, ${username}!`);});第三方:morgan
Section titled “第三方:morgan”morgan 是一个流行的 HTTP 请求日志中间件。它比我们自定义的日志记录器更强大,并且高度可配置,适用于生产环境。
# 安装npm install morgan
# 使用import morgan from 'morgan';
// 在开发过程中使用 'dev' 格式以获取简洁、带有颜色编码的日志app.use(morgan('dev'));