自定义中间件开发

1. 中间件概念回顾

在深入自定义中间件开发之前,我们先回顾一下中间件的基本概念。中间件是 Express.js 中的一个核心概念,它是一个函数,可以访问请求对象 (req)、响应对象 (res) 以及应用程序的请求-响应周期中的下一个中间件函数 (next)。

中间件可以执行以下任务:

  • 执行任何代码。
  • 修改请求和响应对象。
  • 结束请求-响应周期。
  • 调用堆栈中的下一个中间件。

2. 创建第一个自定义中间件

2.1 基本结构

自定义中间件的基本结构如下:

function customMiddleware(req, res, next) {
    // 执行一些操作
    console.log('This is a custom middleware');
    
    // 调用 next() 以继续处理请求
    next();
}

2.2 使用自定义中间件

在 Express.js 应用中使用自定义中间件非常简单。你可以在路由中使用它,或者将其应用到整个应用程序。

const express = require('express');
const app = express();

// 定义自定义中间件
function customMiddleware(req, res, next) {
    console.log('This is a custom middleware');
    next();
}

// 将中间件应用到整个应用
app.use(customMiddleware);

// 定义一个简单的路由
app.get('/', (req, res) => {
    res.send('Hello World!');
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

2.3 实践练习

练习: 创建一个自定义中间件,记录每个请求的 URL 和时间戳,并将这些信息打印到控制台。

function logRequest(req, res, next) {
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
    next();
}

app.use(logRequest);

3. 中间件的顺序

中间件的顺序非常重要。如果一个中间件没有调用 next(),请求-响应周期将在该中间件处终止。

app.use((req, res, next) => {
    console.log('Middleware 1');
    next();
});

app.use((req, res, next) => {
    console.log('Middleware 2');
    next();
});

app.get('/', (req, res) => {
    res.send('Hello World!');
});

在这个例子中,当访问根路径时,控制台将依次输出 Middleware 1 和 Middleware 2。

4. 中间件的参数

有时,你可能希望将一些参数传递给中间件。你可以通过闭包来实现这一点。

function createMiddleware(message) {
    return function(req, res, next) {
        console.log(message);
        next();
    };
}

app.use(createMiddleware('Custom message'));

5. 错误处理中间件

错误处理中间件与其他中间件略有不同。它有四个参数:err, req, res, next。

app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something broke!');
});

6. 实践项目:用户认证中间件

项目目标: 创建一个简单的用户认证中间件,检查请求头中的 Authorization 字段,并根据预定义的用户列表验证用户。

6.1 定义用户列表

const users = [
    { username: 'admin', password: 'admin123' },
    { username: 'user', password: 'user123' }
];

6.2 创建认证中间件

function authenticate(req, res, next) {
    const authHeader = req.headers.authorization;
    if (!authHeader) {
        return res.status(401).send('Authorization required');
    }

    const [username, password] = Buffer.from(authHeader.split(' ')[1], 'base64').toString().split(':');
    const user = users.find(u => u.username === username && u.password === password);

    if (!user) {
        return res.status(403).send('Invalid credentials');
    }

    req.user = user;
    next();
}

6.3 使用认证中间件

app.get('/protected', authenticate, (req, res) => {
    res.send(`Welcome, ${req.user.username}!`);
});

6.4 测试

使用 curl 或其他工具测试认证中间件:

curl -H "Authorization: Basic YWRtaW46YWRtaW4xMjM=" http://localhost:3000/protected

7. 总结

自定义中间件是 Express.js 中非常强大的工具,可以帮助你实现各种功能,如日志记录、认证、错误处理等。通过本教程,你应该已经掌握了如何创建和使用自定义中间件。继续探索和实践,你将能够构建更复杂和功能丰富的应用程序。

8. 进一步学习

  • 第三方中间件集成: 学习如何使用和集成流行的第三方中间件,如 morgan 用于日志记录,helmet 用于安全增强。
  • 身份认证中间件: 深入学习如何使用 Passport.js 实现更复杂的身份认证。
  • 文件上传处理: 学习如何使用 multer 处理文件上传。

通过这些进一步的学习,你将能够构建更强大和安全的 Express.js 应用程序。