应用级中间件 #
一、应用级中间件概述 #
1.1 什么是应用级中间件? #
应用级中间件是绑定到Express应用实例(app)上的中间件。使用 app.use() 或 app.METHOD() 方法绑定。
1.2 基本语法 #
javascript
app.use(path, callback)
| 参数 | 说明 |
|---|---|
| path | 可选,匹配路径 |
| callback | 中间件函数 |
二、app.use() #
2.1 全局中间件 #
不指定路径,匹配所有请求:
javascript
const express = require('express');
const app = express();
app.use((req, res, next) => {
console.log('所有请求都会经过这里');
next();
});
app.get('/', (req, res) => {
res.send('首页');
});
app.listen(3000);
2.2 路径匹配 #
指定路径前缀:
javascript
app.use('/api', (req, res, next) => {
console.log('API请求');
next();
});
app.get('/api/users', (req, res) => {
res.json({ users: [] });
});
app.get('/other', (req, res) => {
res.send('不会经过上面的中间件');
});
2.3 多个中间件 #
javascript
app.use(
(req, res, next) => {
console.log('中间件1');
next();
},
(req, res, next) => {
console.log('中间件2');
next();
},
(req, res, next) => {
console.log('中间件3');
next();
}
);
2.4 中间件数组 #
javascript
const middleware1 = (req, res, next) => {
console.log('中间件1');
next();
};
const middleware2 = (req, res, next) => {
console.log('中间件2');
next();
};
app.use([middleware1, middleware2]);
三、常见应用级中间件 #
3.1 日志中间件 #
javascript
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.originalUrl} ${res.statusCode} - ${duration}ms`);
});
next();
});
3.2 请求体解析 #
javascript
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.raw());
app.use(express.text());
3.3 静态文件服务 #
javascript
app.use(express.static('public'));
app.use('/static', express.static('public'));
3.4 CORS处理 #
javascript
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});
3.5 安全头设置 #
javascript
app.use((req, res, next) => {
res.removeHeader('X-Powered-By');
res.header('X-Content-Type-Options', 'nosniff');
res.header('X-Frame-Options', 'DENY');
res.header('X-XSS-Protection', '1; mode=block');
next();
});
四、请求增强 #
4.1 添加请求属性 #
javascript
app.use((req, res, next) => {
req.requestTime = new Date().toISOString();
req.id = generateRequestId();
next();
});
app.get('/', (req, res) => {
res.json({
requestId: req.id,
requestTime: req.requestTime
});
});
4.2 解析用户信息 #
javascript
app.use((req, res, next) => {
const token = req.headers['authorization']?.split(' ')[1];
if (token) {
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.user = decoded;
} catch (error) {
req.user = null;
}
}
next();
});
4.3 请求上下文 #
javascript
app.use((req, res, next) => {
req.context = {
user: null,
session: null,
startTime: Date.now()
};
next();
});
五、响应增强 #
5.1 统一响应格式 #
javascript
app.use((req, res, next) => {
res.success = (data, message = '成功') => {
res.json({
success: true,
data,
message
});
};
res.error = (message, code = 400) => {
res.status(code).json({
success: false,
error: message
});
};
res.paginate = (data, total, page, limit) => {
res.json({
success: true,
data,
pagination: {
total,
page,
limit,
totalPages: Math.ceil(total / limit)
}
});
};
next();
});
app.get('/users', (req, res) => {
res.success({ users: [] }, '获取用户列表成功');
});
app.get('/error', (req, res) => {
res.error('出错了', 400);
});
5.2 响应时间头 #
javascript
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
res.set('X-Response-Time', `${duration}ms`);
});
next();
});
六、第三方中间件 #
6.1 morgan(日志) #
bash
npm install morgan
javascript
const morgan = require('morgan');
app.use(morgan('dev'));
app.use(morgan('combined'));
app.use(morgan('tiny'));
6.2 helmet(安全) #
bash
npm install helmet
javascript
const helmet = require('helmet');
app.use(helmet());
6.3 cors(跨域) #
bash
npm install cors
javascript
const cors = require('cors');
app.use(cors());
app.use(cors({
origin: 'https://example.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
6.4 compression(压缩) #
bash
npm install compression
javascript
const compression = require('compression');
app.use(compression());
6.5 rate-limit(限流) #
bash
npm install express-rate-limit
javascript
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
message: '请求过于频繁'
});
app.use('/api', limiter);
七、中间件顺序 #
7.1 推荐顺序 #
javascript
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const morgan = require('morgan');
const app = express();
app.use(helmet());
app.use(cors());
app.use(morgan('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));
app.use('/api', routes);
app.use(notFoundHandler);
app.use(errorHandler);
7.2 顺序说明 #
| 顺序 | 中间件 | 说明 |
|---|---|---|
| 1 | helmet | 安全头设置 |
| 2 | cors | 跨域处理 |
| 3 | morgan | 日志记录 |
| 4 | body-parser | 请求体解析 |
| 5 | static | 静态文件 |
| 6 | routes | 业务路由 |
| 7 | 404 | 未找到处理 |
| 8 | error | 错误处理 |
八、完整示例 #
8.1 基础配置 #
javascript
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const morgan = require('morgan');
const rateLimit = require('express-rate-limit');
const compression = require('compression');
const app = express();
app.set('trust proxy', true);
app.use(helmet());
app.use(cors({
origin: process.env.CORS_ORIGIN || '*',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
app.use(morgan('dev'));
app.use(compression());
const limiter = rateLimit({
windowMs: 15 * 60 * 1000,
max: 100,
standardHeaders: true,
legacyHeaders: false
});
app.use('/api', limiter);
app.use(express.json({ limit: '10kb' }));
app.use(express.urlencoded({ extended: true, limit: '10kb' }));
app.use(express.static('public'));
app.use((req, res, next) => {
req.requestTime = new Date().toISOString();
next();
});
app.get('/api/health', (req, res) => {
res.json({
status: 'ok',
timestamp: req.requestTime
});
});
app.use((req, res) => {
res.status(404).json({ error: '路由未找到' });
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: '服务器错误' });
});
module.exports = app;
8.2 开发/生产环境区分 #
javascript
const express = require('express');
const morgan = require('morgan');
const helmet = require('helmet');
const cors = require('cors');
const app = express();
if (process.env.NODE_ENV === 'development') {
app.use(morgan('dev'));
} else {
app.use(morgan('combined'));
}
if (process.env.NODE_ENV === 'production') {
app.use(helmet());
}
app.use(cors());
module.exports = app;
九、中间件调试 #
9.1 请求追踪 #
javascript
app.use((req, res, next) => {
console.log('=== 请求开始 ===');
console.log('Method:', req.method);
console.log('URL:', req.originalUrl);
console.log('Headers:', req.headers);
console.log('Body:', req.body);
console.log('Query:', req.query);
console.log('Params:', req.params);
next();
});
9.2 响应追踪 #
javascript
app.use((req, res, next) => {
const originalSend = res.send;
res.send = function(data) {
console.log('响应数据:', data);
return originalSend.call(this, data);
};
next();
});
十、总结 #
应用级中间件要点:
| 方法 | 说明 |
|---|---|
| app.use() | 挂载中间件 |
| app.use(path) | 路径匹配 |
| app.use([fn1, fn2]) | 多个中间件 |
| app.METHOD() | 路由特定中间件 |
下一步,让我们学习路由级中间件!
最后更新:2026-03-28