Appearance
中间件
什么是中间件
中间件是 Express 应用中的一个函数,它可以访问请求对象(req)、响应对象(res)以及应用的请求-响应循环中的下一个中间件函数(next)。中间件函数可以执行以下任务:
- 执行任何代码
- 修改请求和响应对象
- 结束请求-响应循环
- 调用下一个中间件函数
中间件的类型
1. 应用级中间件
应用级中间件绑定到 Express 应用实例上,使用 app.use() 和 app.METHOD() 方法。
javascript
// 应用于所有请求
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// 应用于特定路径
app.use('/users', (req, res, next) => {
console.log('Users route');
next();
});
// 应用于特定路径和方法
app.get('/users', (req, res, next) => {
console.log('GET /users');
next();
}, (req, res) => {
res.send('Users');
});2. 路由级中间件
路由级中间件与应用级中间件类似,但它绑定到 express.Router() 实例上。
javascript
const router = express.Router();
// 应用于所有路由
router.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// 应用于特定路由
router.use('/:id', (req, res, next) => {
console.log('User ID:', req.params.id);
next();
});
app.use('/users', router);3. 错误处理中间件
错误处理中间件有四个参数:err, req, res, next。
javascript
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});4. 内置中间件
Express 内置了以下中间件:
express.static():提供静态文件服务express.json():解析 JSON 请求体express.urlencoded():解析 URL 编码的请求体
javascript
// 提供静态文件服务
app.use(express.static('public'));
// 解析 JSON 请求体
app.use(express.json());
// 解析 URL 编码的请求体
app.use(express.urlencoded({ extended: true }));5. 第三方中间件
可以使用第三方中间件来扩展 Express 应用的功能。
bash
npm install morgan helmet corsjavascript
const morgan = require('morgan');
const helmet = require('helmet');
const cors = require('cors');
// 日志中间件
app.use(morgan('dev'));
// 安全中间件
app.use(helmet());
// 跨域中间件
app.use(cors());中间件的执行顺序
中间件的执行顺序取决于它们在代码中的定义顺序。
javascript
// 第一个执行
app.use((req, res, next) => {
console.log('Middleware 1');
next();
});
// 第二个执行
app.use((req, res, next) => {
console.log('Middleware 2');
next();
});
// 第三个执行
app.get('/', (req, res) => {
res.send('Hello World!');
});中间件链
可以将多个中间件函数链接在一起,形成一个中间件链。
javascript
app.get('/user/:id',
(req, res, next) => {
console.log('First middleware');
next();
},
(req, res, next) => {
console.log('Second middleware');
next();
},
(req, res) => {
res.send(`User ${req.params.id}`);
}
);中间件的错误处理
如果中间件函数中发生错误,应该调用 next(err) 将错误传递给错误处理中间件。
javascript
app.get('/user/:id', (req, res, next) => {
const id = parseInt(req.params.id);
if (isNaN(id)) {
const error = new Error('Invalid user ID');
error.status = 400;
return next(error);
}
next();
}, (req, res) => {
res.send(`User ${req.params.id}`);
});
// 错误处理中间件
app.use((err, req, res, next) => {
res.status(err.status || 500).send(err.message);
});中间件的最佳实践
1. 保持中间件简洁
- 每个中间件只负责一个功能
- 中间件代码应该简洁明了
- 避免在中间件中执行复杂的业务逻辑
2. 合理使用中间件
- 只使用必要的中间件
- 避免过多的中间件
- 合理安排中间件的顺序
3. 错误处理
- 正确处理中间件中的错误
- 使用统一的错误处理中间件
- 提供清晰的错误信息
4. 安全性
- 使用安全中间件(如 helmet)
- 验证用户输入
- 防止 XSS 和 CSRF 攻击
5. 性能优化
- 避免在中间件中执行 CPU 密集型操作
- 合理使用缓存
- 只在必要的路由上应用中间件
常用的第三方中间件
1. 日志中间件
- morgan:HTTP 请求日志
- winston:多传输日志
2. 安全中间件
- helmet:安全头设置
- cors:跨域资源共享
- express-rate-limit:请求速率限制
3. 认证中间件
- passport:认证框架
- express-jwt:JWT 认证
4. 验证中间件
- express-validator:请求验证
- joi:对象验证
5. 会话和 cookie 中间件
- express-session:会话管理
- cookie-parser:Cookie 解析
实践练习
- 创建自定义中间件
- 使用第三方中间件
- 构建中间件链
- 实现错误处理中间件
- 优化中间件性能