应用级中间件 #

一、应用级中间件概述 #

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