node.js - 在 Nest.js 中访问 Stripe webhook 的原始主体
问题描述
我需要在我的 Nest.js 应用程序中访问来自 Stripe 的 webhook 请求的原始正文。
在这个示例之后,我将以下内容添加到具有需要原始主体的控制器方法的模块中。
function addRawBody(req, res, next) {
req.setEncoding('utf8');
let data = '';
req.on('data', (chunk) => {
data += chunk;
});
req.on('end', () => {
req.rawBody = data;
next();
});
}
export class SubscriptionModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(addRawBody)
.forRoutes('subscriptions/stripe');
}
}
在我使用的控制器中@Req() req
,然后req.rawBody
获取原始主体。我需要原始正文,因为 Stripe api 的constructEvent 正在使用它来验证请求。
问题是请求被卡住了。似乎 req.on 既不是为数据调用,也不是为结束事件调用。所以next()
在中间件中没有调用。
我也尝试过在这里使用raw-body
,但我得到了几乎相同的结果。在那种情况下, req.readable 总是错误的,所以我也被困在那里。
我想这是 Nest.js 的问题,但我不确定......
解决方案
对于任何寻求更优雅解决方案的人,请关闭bodyParser
in main.ts
。创建两个中间件函数,一个rawbody
用于json-parsed-body
.
json-body.middleware.ts
import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';
import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class JsonBodyMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => any) {
bodyParser.json()(req, res, next);
}
}
原始body.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';
@Injectable()
export class RawBodyMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => any) {
bodyParser.raw({type: '*/*'})(req, res, next);
}
}
将中间件功能应用于app.module.ts
.
app.module.ts
[...]
export class AppModule implements NestModule {
public configure(consumer: MiddlewareConsumer): void {
consumer
.apply(RawBodyMiddleware)
.forRoutes({
path: '/stripe-webhooks',
method: RequestMethod.POST,
})
.apply(JsonBodyMiddleware)
.forRoutes('*');
}
}
[...]
并调整 Nest 的初始化以关闭 bodyParser:
主要的.ts
[...]
const app = await NestFactory.create(AppModule, { bodyParser: false })
[...]
BTWreq.rawbody
从express
很久以前就被删除了。
推荐阅读
- python - Amazon S3 boto3 如何遍历存储桶中的对象?
- java - 模拟 File.createTempFile() 并返回我们模拟的 File 对象
- java - TextView.setView() 不更新文本
- mapbox - Mapbox - 从自动完成结果中获取区域
- javascript - 带有 ? 选项的 json 文件 404
- linq - Linq 条件 .ANY() 问题
- html - font-weight bold 打乱了输入框的对齐方式
- angular - Angular9 ReactiveForm 在提交时返回空值
- terraform - 具有嵌套动态块的 Terraform 资源 for_each 不断重新应用相同的更改
- java - JUnit。assertEquals(Array.toString(), output.toString())