您现在的位置是:网站首页 > 内置中间件与第三方中间件文章详情
内置中间件与第三方中间件
陈川
【
Node.js
】
36527人已围观
4308字
Express框架提供了丰富的中间件机制,开发者可以通过内置中间件快速实现基础功能,也能借助第三方中间件扩展能力。中间件的灵活组合是Express的核心优势之一。
内置中间件的类型与用法
Express内置了多个常用的中间件,这些中间件通过express
对象直接调用,无需额外安装。最典型的是处理JSON和URL编码数据的中间件:
const express = require('express');
const app = express();
// JSON解析中间件
app.use(express.json());
// URL编码解析中间件
app.use(express.urlencoded({ extended: true }));
// 静态文件服务中间件
app.use(express.static('public'));
express.json()
会解析Content-Type为application/json的请求体,将结果挂载到req.body。express.urlencoded()
则处理表单提交的application/x-www-form-urlencoded数据。extended参数决定使用querystring库(false)还是qs库(true)进行解析。
静态文件中间件express.static()
特别适合托管前端资源:
// 多目录静态资源托管
app.use(express.static('public'));
app.use(express.static('uploads'));
// 虚拟路径前缀
app.use('/static', express.static('public'));
第三方中间件的生态系统
npm上有超过两千个Express中间件,覆盖各种场景。常用中间件包括:
- morgan - HTTP请求日志记录
const morgan = require('morgan');
app.use(morgan('combined'));
- helmet - 安全相关HTTP头设置
const helmet = require('helmet');
app.use(helmet());
- cors - 跨域资源共享支持
const cors = require('cors');
app.use(cors({
origin: ['https://example.com', 'http://localhost:3000']
}));
- compression - 响应压缩
const compression = require('compression');
app.use(compression({ level: 6 }));
中间件的执行顺序原理
中间件按照app.use()的调用顺序执行,典型处理流程如下:
app.use((req, res, next) => {
console.log('First middleware');
next();
});
app.use('/api', (req, res, next) => {
console.log('API route middleware');
next();
});
app.get('/api/users', (req, res) => {
res.json([{id: 1, name: 'Alice'}]);
});
错误处理中间件需要四个参数:
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
自定义中间件开发实践
开发自定义中间件可以封装通用逻辑。例如实现一个简单的请求时间记录器:
function requestTime(req, res, next) {
req.requestTime = Date.now();
next();
}
app.use(requestTime);
app.get('/', (req, res) => {
res.send(`Requested at ${req.requestTime}`);
});
更复杂的权限验证中间件示例:
function authMiddleware(role) {
return (req, res, next) => {
if (!req.user || req.user.role !== role) {
return res.status(403).send('Forbidden');
}
next();
};
}
// 使用方式
app.get('/admin', authMiddleware('admin'), (req, res) => {
res.send('Admin dashboard');
});
中间件的性能优化策略
不当的中间件使用会影响性能,需要注意:
- 按需加载中间件
// 仅开发环境使用日志中间件
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'));
}
- 避免全局中间件处理特定路由
// 不推荐
app.use(compression());
// 推荐
app.get('/api/large-data', compression(), (req, res) => {
// 返回大数据量响应
});
- 使用路由级中间件
const router = express.Router();
router.use(bodyParser.json());
router.get('/users', getUserList);
app.use('/api', router);
中间件的错误处理模式
完善的错误处理需要分层设计:
// 业务逻辑错误
app.get('/error', (req, res, next) => {
try {
throw new Error('Something went wrong');
} catch (err) {
next(err); // 传递给错误处理中间件
}
});
// 异步错误处理
app.get('/async-error', async (req, res, next) => {
try {
await someAsyncOperation();
} catch (err) {
next(err);
}
});
// 最终错误处理器
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
error: {
message: err.message
}
});
});
中间件的测试方法
使用supertest测试中间件行为:
const request = require('supertest');
const app = require('../app');
describe('Auth Middleware', () => {
it('should block unauthorized access', async () => {
const res = await request(app)
.get('/protected')
.expect(401);
});
it('should allow access with valid token', async () => {
const res = await request(app)
.get('/protected')
.set('Authorization', 'Bearer valid-token')
.expect(200);
});
});
中间件的组合技巧
通过app.use()
可以组合多个中间件:
const middlewares = [
helmet(),
compression(),
cors(),
express.json()
];
app.use(middlewares);
也可以创建可配置的中间件组合:
function createMiddlewareStack(options) {
const stack = [];
if (options.logging) {
stack.push(morgan('dev'));
}
if (options.auth) {
stack.push(passport.initialize());
}
return stack;
}
app.use(createMiddlewareStack({
logging: true,
auth: true
}));
上一篇: 中间件的基本概念与工作原理
下一篇: 自定义中间件的开发方法