MST

星途 面试题库

面试题:Node.js Express框架中间件的深度应用

假设你正在开发一个基于Node.js Express的电商应用,需要实现用户认证、日志记录以及错误处理功能,阐述如何合理地使用Express中间件来完成这些功能,并且说明中间件的执行顺序对这些功能实现的影响。
45.8万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

用户认证

  1. 实现方式
    • 创建一个自定义中间件,例如authMiddleware。在这个中间件中,通过检查请求头(如Authorization头)中的令牌(token)来验证用户身份。可以使用流行的库如jsonwebtoken来验证JWT令牌。
    const jwt = require('jsonwebtoken');
    const authMiddleware = (req, res, next) => {
        const token = req.headers['authorization'];
        if (!token) {
            return res.status(401).json({ message: 'No token provided' });
        }
        try {
            const decoded = jwt.verify(token, 'your_secret_key');
            req.user = decoded;
            next();
        } catch (err) {
            return res.status(401).json({ message: 'Invalid token' });
        }
    };
    
    • 然后在需要认证的路由前使用这个中间件,例如:
    const express = require('express');
    const app = express();
    const productRouter = express.Router();
    productRouter.get('/products', authMiddleware, (req, res) => {
        // 只有认证通过才能访问这个路由
        res.json({ products: [] });
    });
    app.use('/api', productRouter);
    
  2. 中间件执行顺序影响:认证中间件应该在需要认证的路由处理函数之前执行。如果顺序错误,例如先执行路由处理函数再认证,那么未认证的用户也可能访问到受保护的资源。

日志记录

  1. 实现方式
    • 可以使用morgan库,它是一个广泛使用的HTTP请求日志记录中间件。安装morgan后,在应用中使用它:
    const express = require('express');
    const morgan = require('morgan');
    const app = express();
    app.use(morgan('dev'));
    
    • 如果想自定义日志记录,也可以创建自己的中间件。例如:
    const customLogger = (req, res, next) => {
        console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
        next();
    };
    app.use(customLogger);
    
  2. 中间件执行顺序影响:日志记录中间件一般放在应用或路由级别的开头,这样可以记录所有的请求。如果放在后面,可能会遗漏一些请求的记录,特别是在中间件提前结束响应(如认证失败直接返回401)的情况下。

错误处理

  1. 实现方式
    • Express有内置的错误处理机制。创建一个全局错误处理中间件,它有四个参数(err, req, res, next)
    const errorHandler = (err, req, res, next) => {
        console.error(err.stack);
        res.status(500).json({ message: 'Something went wrong!' });
    };
    app.use(errorHandler);
    
    • 在路由处理函数或其他中间件中,如果发生错误,可以调用next(err)将错误传递给这个全局错误处理中间件。例如:
    const productRouter = express.Router();
    productRouter.get('/products', (req, res, next) => {
        try {
            // 可能会抛出错误的代码
            throw new Error('Simulated error');
            res.json({ products: [] });
        } catch (err) {
            next(err);
        }
    });
    
  2. 中间件执行顺序影响:错误处理中间件必须放在所有其他中间件和路由处理函数之后。如果放在前面,它可能无法捕获到后续中间件和路由处理函数中抛出的错误。

整体中间件执行顺序建议

  1. 首先使用日志记录中间件,以便记录所有请求。
  2. 然后是认证中间件,确保只有认证用户可以访问受保护路由。
  3. 接着是路由处理函数,处理具体的业务逻辑。
  4. 最后是错误处理中间件,捕获并处理整个应用中发生的错误。