Fastify 的拦截器(hooks)机制详解

Fastify 是 Node.js 中一款快速、低开销且功能强大的 web 框架。其中,拦截器(hooks)机制是 Fastify 重要的特性之一。本文将详细介绍 Fastify 拦截器的概念、类型以及用法,并且包含示例代码。

拦截器(hooks)概念

Fastify 中的拦截器(hooks)是指在路由处理函数(handler)执行前或执行后,添加处理函数的中间件。Fastify 的拦截器机制能够让开发者增加、修改请求和响应的生命周期事件(lifecycle events),从而支持用户的自定义行为和控制。它的核心目的是促进代码复用和解耦,让开发者专注于路由处理函数的处理过程。

Fastify 中有四种类型的拦截器:

  1. onRequest:在每次请求事件触发时执行。
  2. preParsing:在消息正文解析之前执行。
  3. preValidation:在请求正式处理之前执行。
  4. preHandler:在路由处理函数执行之前执行。

拦截器(hooks)用法

接下来,我们将顺序介绍四种类型的拦截器的使用方法。

onRequest 拦截器

onRequest 拦截器在 Fastify 实例收到请求时执行。它适用于一些需要在请求正式处理之前执行的逻辑操作,例如将某些数据附加到请求上。它需要一个处理函数。

fastify.onRequest((request, reply, done) => {
  // 在请求完全初始化之前修改 request.url
  request.url = request.url.replace('/api/v1', '/');
  done();
});

需要注意的是,onRequest 拦截器的处理函数不需要返回任何值,而是使用回调参数 done 表示完成执行操作。例如在处理完请求后,必须用 reply.send 方法来发送响应。

fastify.onRequest((request, reply, done) => {
  // 日志记录
  console.log(request.method, request.url);
  done();
});

fastify.get('/', (request, reply) => {
  reply.send({ hello: 'world' });
});

preParsing 拦截器

preParsing 拦截器在消息正文解析之前执行。它适用于对请求正文的原始数据进行修改的情况。它将 FastifyContentTypeParserFastifyBodyParser 绑定在一起,以确保消息正文在传递给路由处理函数之前得到解析和格式化。

fastify.preParsing((request, reply, done) => {
  // 请求正文解析为 JSON 格式
  request.body = JSON.parse(request.body);
  done();
});

需要注意的是,preParsing 拦截器的处理函数中的响应必须在回调函数参数 done 中被处理。

preValidation 拦截器

preValidation 拦截器在请求正式处理之前执行。它适用于验证请求是否符合开发者的期望或者进行一些与验证相关的逻辑操作。例如,如果请求体为 JSON,它将验证 JSON 是否有效。

fastify.preValidation((request, reply, done) => {
  try {
    validateJSON(request.body);
    done();
  } catch (error) {
    reply.code(400).send({ code: 'INVALID_JSON', message: error.message });
  }
});

preHandler 拦截器

preHandler 拦截器在路由处理函数执行之前执行。它适用于修改或延迟路由处理函数执行的场景,例如在路由处理函数寻找数据之前设置数据库连接或加载用户权限。

fastify.preHandler((request, reply, done) => {
  try {
    request.userService = userService;
    done();
  } catch (error) {
    reply.code(500).send({ code: 'INTERNAL_ERROR', message: error.message });
  }
});

fastify.get('/:id', (request, reply) => {
  const user = request.userService.findById(request.params.id);
  reply.send(user);
});

需要注意的是,preHandler 拦截器的处理函数的返回值将直接传递给路由处理函数。

拦截器(hooks)指导意义

Fastify 拦截器机制是一种非常强大的工具,开发者可以使用它来自定义请求和响应的生命周期。拦截器的使用可以使路由处理函数更加专注于解决具体的业务问题,而不用考虑和处理和请求和响应相关的逻辑处理。还可以在拦截器中实现一些公共逻辑,例如身份验证和授权,数据缓存和日志记录等。

总结一下,拦截器在 Fastify 中具有以下特性:

  1. 提供请求和响应的生命周期时间点,促进代码复用和解耦。
  2. 拦截器机制可以实现开发者自定义的处理行为和控制。
  3. Fastify 提供了四种拦截器类型:onRequestpreParsingpreValidationpreHandler
  4. 开发人员可以在拦截器中编写自己的处理逻辑,如身份验证、授权、数据缓存和日志记录等。

示例代码

本文的代码示例基于 Fastify 3.x 版本。

const fastify = require('fastify')({
  logger: { level: 'info' },
});

// onRequest 拦截器
fastify.onRequest((request, reply, done) => {
  console.log(request.method, request.url);
  done();
});

// 带参数路由
fastify.get('/:id', (request, reply) => {
  const user = request.userService.findById(request.params.id);
  reply.send(user);
});

// preHandler 拦截器
fastify.decorateRequest('userService', null);
fastify.preHandler((request, reply, done) => {
  try {
    request.userService = userService;
    done();
  } catch (error) {
    reply.code(500).send({ code: 'INTERNAL_ERROR', message: error.message });
  }
});

// 启动服务器
fastify.listen(3000, (err) => {
  if (err) {
    fastify.log.error(err);
    process.exit(1);
  }
  fastify.log.info(`server listening on ${fastify.server.address().port}`);
});

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6595015beb4cecbf2d94389a


纠错反馈