你可能会想象,我很熟悉Express,但这是我第一次使用Fastify。
我想访问Fastify请求的未修改体,以验证Webhook的签名 - 也就是说,我希望看到原始请求,未经任何中间件修改。在Express中,通常通过访问request.rawBody
来实现此操作。
如何访问Fastify请求的原始主体?
你可能会想象,我很熟悉Express,但这是我第一次使用Fastify。
我想访问Fastify请求的未修改体,以验证Webhook的签名 - 也就是说,我希望看到原始请求,未经任何中间件修改。在Express中,通常通过访问request.rawBody
来实现此操作。
如何访问Fastify请求的原始主体?
您还可以查看此社区插件: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
访问原始正文。
注意:Fastify 请求只能有 req.body
,不能像其他网络服务器(例如 Express)一样同时具有 req.body
和 req.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);
}
}
);
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))
})
})
req.rawBody
,而是用未解析的正文替换body
。 - mikemaccana 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,
);
}