这是我对在 NestJS 的处理程序中获取原始(文本)正文的看法:
- 使用
preserveRawBodyInRequest 配置应用程序,如 JSDoc 示例所示
- 在处理程序中使用
RawBody 装饰器来检索原始(文本)正文
原始请求.decorator.ts:
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
import { NestExpressApplication } from "@nestjs/platform-express";
import { json, urlencoded } from "express";
import type { Request } from "express";
import type http from "http";
export const HTTP_REQUEST_RAW_BODY = "rawBody";
/**
* make sure you configure the nest app with <code>preserveRawBodyInRequest</code>
* @example
* webhook(@RawBody() rawBody: string): Record<string, unknown> {
* return { received: true };
* }
* @see preserveRawBodyInRequest
*/
export const RawBody = createParamDecorator(
async (data: unknown, context: ExecutionContext) => {
const request = context
.switchToHttp()
.getRequest<Request>()
;
if (!(HTTP_REQUEST_RAW_BODY in request)) {
throw new Error(
`RawBody not preserved for request in handler: ${context.getClass().name}::${context.getHandler().name}`,
);
}
const rawBody = request[HTTP_REQUEST_RAW_BODY];
return rawBody;
},
);
/**
* @example
* const app = await NestFactory.create<NestExpressApplication>(
* AppModule,
* {
* bodyParser: false, // it is prerequisite to disable nest's default body parser
* },
* );
* preserveRawBodyInRequest(
* app,
* "signature-header",
* );
* @param app
* @param ifRequestContainsHeader
*/
export function preserveRawBodyInRequest(
app: NestExpressApplication,
...ifRequestContainsHeader: string[]
): void {
const rawBodyBuffer = (
req: http.IncomingMessage,
res: http.ServerResponse,
buf: Buffer,
): void => {
if (
buf?.length
&& (ifRequestContainsHeader.length === 0
|| ifRequestContainsHeader.some(filterHeader => req.headers[filterHeader])
)
) {
req[HTTP_REQUEST_RAW_BODY] = buf.toString("utf8");
}
};
app.use(
urlencoded(
{
verify: rawBodyBuffer,
extended: true,
},
),
);
app.use(
json(
{
verify: rawBodyBuffer,
},
),
);
}