实用中间件模式25例
1. 基础增强模式
请求属性扩展
javascript
function extendRequest() {
return (req, res, next) => {
req.getClientLanguage = () => {
return req.headers['accept-language']?.split(',')[0] || 'en';
};
next();
};
}
响应时间头
javascript
function responseTime() {
return (req, res, next) => {
const start = Date.now();
res.on('finish', () => {
res.setHeader('X-Response-Time', `${Date.now() - start}ms`);
});
next();
};
}
2. 安全相关中间件
CSRF防护
javascript
function csrfProtection() {
return (req, res, next) => {
if (['POST', 'PUT', 'DELETE'].includes(req.method)) {
const csrfToken = req.headers['x-csrf-token'];
if (!csrfToken || csrfToken !== req.session.csrfToken) {
return res.status(403).send('Invalid CSRF token');
}
}
next();
};
}
CORS配置
javascript
function cors(options = {}) {
return (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', options.origin || '*');
res.setHeader('Access-Control-Allow-Methods', options.methods || 'GET,POST,PUT,DELETE');
res.setHeader('Access-Control-Allow-Headers', options.headers || 'Content-Type,Authorization');
options.credentials && res.setHeader('Access-Control-Allow-Credentials', 'true');
req.method === 'OPTIONS' ? res.sendStatus(200) : next();
};
}
3. 数据转换中间件
请求体格式化
javascript
function formatBody() {
return (req, res, next) => {
if (req.body) {
// 去除字符串两端的空格
Object.keys(req.body).forEach(key => {
if (typeof req.body[key] === 'string') {
req.body[key] = req.body[key].trim();
}
});
}
next();
};
}
响应数据包装
javascript
function wrapResponse() {
return (req, res, next) => {
const originalSend = res.send;
res.send = function(data) {
const wrapped = {
status: 'success',
data: data,
timestamp: new Date().toISOString()
};
originalSend.call(this, wrapped);
};
next();
};
}
高级组合技巧
1. 中间件条件执行
javascript
function when(predicate, middleware) {
return (req, res, next) => {
predicate(req) ? middleware(req, res, next) : next();
};
}
// 使用示例
app.use(when(
req => req.path.startsWith('/api'),
helmet()
));
2. 中间件并行执行
javascript
function parallel(middlewares) {
return (req, res, next) => {
let completed = 0;
const done = () => ++completed === middlewares.length && next();
middlewares.forEach(mw => {
mw(req, res, done);
});
};
}
// 使用示例
app.use(parallel([
requestLogger,
responseTime,
bodyParser.json()
]));
3. 中间件管道
javascript
function pipe(...middlewares) {
return (req, res, next) => {
const run = i => i < middlewares.length
? middlewares[i](req, res, () => run(i + 1))
: next();
run(0);
};
}
性能优化中间件
1. 缓存中间件
javascript
function cache(duration) {
const cacheStore = new Map();
return (req, res, next) => {
const key = req.originalUrl;
const cached = cacheStore.get(key);
if (cached && cached.expiry > Date.now()) {
return res.send(cached.data);
}
const originalSend = res.send;
res.send = function(body) {
cacheStore.set(key, {
data: body,
expiry: Date.now() + duration
});
originalSend.call(this, body);
};
next();
};
}
2. 压缩中间件
javascript
const zlib = require('zlib');
function compression() {
return (req, res, next) => {
const acceptEncoding = req.headers['accept-encoding'] || '';
const originalSend = res.send;
res.send = function(body) {
if (acceptEncoding.includes('gzip')) {
res.setHeader('Content-Encoding', 'gzip');
zlib.gzip(Buffer.from(body), (err, result) => {
if (err) return originalSend.call(this, body);
originalSend.call(this, result);
});
} else {
originalSend.call(this, body);
}
};
next();
};
}
调试与错误处理
1. 调试中间件
javascript
function debugMiddleware() {
return (req, res, next) => {
console.log('--- Request Start ---');
console.log(`Method: ${req.method}`);
console.log(`Path: ${req.path}`);
console.log('Headers:', req.headers);
console.log('Query:', req.query);
console.log('Body:', req.body);
const originalSend = res.send;
res.send = function(body) {
console.log('--- Response ---');
console.log(`Status: ${res.statusCode}`);
console.log('Body:', body);
originalSend.call(this, body);
};
next();
};
}
2. 错误处理增强
javascript
function errorHandler() {
return (err, req, res, next) => {
console.error(err.stack);
const status = err.status || 500;
const message = status === 500 ? 'Internal Server Error' : err.message;
res.status(status).json({
error: {
message: message,
code: err.code,
timestamp: new Date().toISOString(),
path: req.path
}
});
};
}
实战项目推荐
- API网关:组合各种验证、限流、日志中间件
- 文件处理管道:创建文件上传处理链
- A/B测试框架:基于中间件的流量分配
- 多租户系统:通过中间件识别租户
下节将带来以上更加详尽的项目实践。