在Express.js框架中,中间件(middleware)是一种功能强大的机制,它允许你在请求-响应循环中的不同阶段执行代码。中间件函数可以访问请求对象(req)、响应对象(res)以及应用程序的请求-响应循环中的下一个中间件函数(next)。根据中间件的功能和用途,我们可以将它们大致分为以下几类:
- 应用级别的中间件
- 路由的中间件
- 错误级别的中间件
- Express内置的中间件
- 第三方的中间件
- 响应处理中间件
- 请求处理中间件
应用级别的中间件:这些中间件绑定到Express应用程序的实例上,并且对每个请求和响应都有效。
const express = require('express');
const app = express();
// 应用程序级中间件:记录每个请求的日志
// 全局中间件
app.use((req, res, next) => {
console.log(`Request Method: ${req.method}, URL: ${req.url}`);
next(); // 调用next()以继续处理下一个中间件或路由
});
// 局部中间件
const middleware = (req, res, next)=>{
next();
}
app.get('/', middleware, (req, res) => {
res.send('Hello, World!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
路由级中间件:路由级中间件绑定到特定的路由上,仅对与该路由匹配的请求有效。
const express = require('express');
const app = express();
// 写法一
const router = express.Router();
router.use((req, res, next)=>{
console.log('路由中间件');
next();
})
// 写法二
const authenticate = (req, res, next) => {
// 假设这里有一个简单的身份验证逻辑
if (req.headers['auth-token'] === 'valid-token') {
next(); // 验证通过,继续处理下一个中间件或路由处理程序
} else {
res.status(401).send('Unauthorized'); // 验证失败,发送401响应
}
};
// 路由级中间件:身份验证
app.get('/protected', authenticate, (req, res) => {
res.send('You have accessed the protected route!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
错误处理中间件:错误处理中间件捕获并处理应用程序中发生的错误。注意:错误级别的中间件要放在路由之后。
const express = require('express');
const app = express();
// 一个会引发错误的路由处理程序
app.get('/error', (req, res, next) => {
throw new Error('This is a deliberate error');
});
// 错误处理中间件,必须包含四个参数
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
内置中间件和第三方中间件:内置中间件和第三方中间件通常通过app.use()或特定路由的use方法引入。在下面的例子中,express.json()和express.static()是Express的内置中间件,而body-parser是一个第三方中间件。
const express = require('express');
const app = express();
const bodyParser = require('body-parser'); // 第三方中间件
// 使用内置的express.json()中间件解析JSON请求体
app.use(express.json());
// 使用第三方body-parser中间件解析URL编码的请求体
app.use(bodyParser.urlencoded({ extended: true }));
// 使用静态文件中间件提供静态文件服务
app.use(express.static('public'));
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
请求处理和响应处理中间件:请求处理和响应处理中间件通常是对请求对象或响应对象进行操作的中间件。
在下面例子中,第一个中间件是请求处理中间件,它记录了请求的开始时间。第二个中间件虽然在这里作为响应处理中间件的示例,但实际上它只是在响应发送完成后记录了一个日志。在实际应用中,你可以在next()调用之前修改响应对象。
const express = require('express');
const app = express();
// 请求处理中间件:修改请求对象
app.use((req, res, next) => {
req.startTime = Date.now(); // 记录请求开始时间
next();
});
// 路由处理程序
app.get('/', (req, res) => {
const duration = Date.now() - req.startTime; // 计算请求处理时间
res.send(`Hello, World! Request took ${duration}ms.`);
});
// 响应处理中间件:修改响应对象
app.use((req, res, next) => {
res.on('finish', () => {
console.log(`Response sent for URL: ${req.url}`);
});
// 注意:在这个例子中,我们实际上没有在发送响应之前修改它,但可以在这里添加逻辑来修改响应头或体
next();
});
app.listen(3000, () => {
console.log('Server is running on port 3000');
});