我如何访问Fastify请求的原始正文?

4

你可能会想象,我很熟悉Express,但这是我第一次使用Fastify。

我想访问Fastify请求的未修改体,以验证Webhook的签名 - 也就是说,我希望看到原始请求,未经任何中间件修改。在Express中,通常通过访问request.rawBody来实现此操作。

如何访问Fastify请求的原始主体?

4个回答

5

您还可以查看此社区插件:https://github.com/Eomm/fastify-raw-body

如果您正在使用Typescript和fastify/autoload,请将此内容放入plugins/rawbody.ts中:

import fp from "fastify-plugin";

import rawbody, { RawBodyPluginOptions } from "fastify-raw-body";

export default fp<RawBodyPluginOptions>(async (fastify) => {
  fastify.register(rawbody, {
    field: "rawBody", // change the default request.rawBody property name
    global: false, // add the rawBody to every request. **Default true**
    encoding: "utf8", // set it to false to set rawBody as a Buffer **Default utf8**
    runFirst: true, // get the body before any preParsing hook change/uncompress it. **Default false**
    routes: [], // array of routes, **`global`** will be ignored, wildcard routes not supported
  });
});

由于 global:false,我们需要在特定的处理程序中进行配置:

  fastify.post<{ Body: any }>(
    "/api/stripe_webhook",
    {
      config: {
        // add the rawBody to this route. if false, rawBody will be disabled when global is true
        rawBody: true,
      },
    },

    async function (request, reply) {
...

然后,您可以在处理程序中使用request.rawBody访问原始正文。


2
谢谢@fatihpense!你的回答更简单,更符合Fastify社区的要求,比我两年前的旧回答好多了,恭喜恭喜,我会将其设为被采纳的答案。 - mikemaccana
@mikemaccana 感谢您的夸奖。我很高兴这对你有用。 - fatihpense

4

注意:Fastify 请求只能有 req.body,不能像其他网络服务器(例如 Express)一样同时具有 req.bodyreq.rawBody。这是因为 addContentTypeParser() 只返回修改后的 body,无法在请求中添加其他内容。

相反,在内容类型解析器中我们只向一个路由添加:

  • req.body.parsed(对象,与通常在 req.body 中的内容相同)
  • req.body.raw(字符串)

请参阅GitHub addContentTypeParser() 文档了解更多信息。

  server.addContentTypeParser(
    "application/json",
    { parseAs: "string" },
    function (req, body, done) {
      try {
        var newBody = {
          raw: body,
          parsed: JSON.parse(body),
        };
        done(null, newBody);
      } catch (error) {
        error.statusCode = 400;
        done(error, undefined);
      }
    }
  );

2

GitHub上有一个关于rawBody支持的问题

还有一个模块:"raw-body"。要在Fastify中使用此模块:

const rawBody = require('raw-body')

fastify.addContentTypeParser('*', (req, done) => {
    rawBody(req, {
        length: req.headers['content-length'],
        limit: '1mb',
        encoding: 'utf8', // Remove if you want a buffer
    }, (err, body) => {
        if (err) return done(err)
        done(null, parse(body))
    })
})

我希望我能帮到你,我在fastify上也是新手。

更新:我不确定这是否有效-它解析原始正文,但不添加req.rawBody,而是用未解析的正文替换body - mikemaccana

1
根据文档 https://docs.nestjs.com/faq/raw-body,在 main.ts 文件中。
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(),
    {
      rawBody: true,
    },
  );

然后在你的控制器中
  async handleStripeEvent(
    @Headers('stripe-signature') signature: string,
    @Req() request: RawBodyRequest<FastifyRequest>,
  ) {
    if (!signature) {
      throw new BadRequestException('Missing stripe-signature header');
    }

    const event = await this.webhooksService.handleStripePaymentWebhook(
      signature,
      request.rawBody,
    );
  }


1
谢谢你提供的更新答案!我将这个答案设为官方答案,因为其他答案(包括我的)现在有点过时了。另外,我在代码中添加了一个缺失的大括号。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接