nest: rawBody:true does not work whilst also increasing the request size limit
Is there an existing issue for this?
- I have searched the existing issues
Current behavior
With an app boostrapped like so:
async function bootstrap() {
const app = await NestFactory.create(AppModule, {
rawBody: true,
});
app.use(json({limit: '50mb'}));
app.use(urlencoded({limit: '50mb'}));
app.setGlobalPrefix('api');
await app.listen(3000);
}
bootstrap();
and a controller like so:
Controller('customerwebhook')
export class CustomerWebhookController {
constructor(private readonly configService: ConfigService, private readonly customerWebhookService: CustomerWebhookService) {}
@Post()
async customerWebhook(
@Body() payload: XeroWebhookPayload,
@Req() request: RawBodyRequest<any>,
@Headers('x-xero-signature') signature: string,
@Res({ passthrough: true }) response: any,
): Promise<void> {
//handle verification
}
I get the issue that the request is not actually a raw request, therefore I cannot verify the webhook correctly. This is solved if I remove the two app.use() calls in the bootstrap but I require this as my webhook requests can be in excession of 10kb (the default)
Is there a workaround / am I using this wrong, I believe these two things should be able to work in conjunction.
Minimum reproduction code
https://codesandbox.io/s/cocky-violet-bfj8pw?file=/src/customer-webhook.controller.ts
Steps to reproduce
No response
Expected behavior
The request should still be a raw request and also the request size limit respected.
Package
- I don’t know. Or some 3rd-party package
-
@nestjs/common -
@nestjs/core -
@nestjs/microservices -
@nestjs/platform-express -
@nestjs/platform-fastify -
@nestjs/platform-socket.io -
@nestjs/platform-ws -
@nestjs/testing -
@nestjs/websockets - Other (see below)
Other package
No response
NestJS version
9.0.0
Packages versions
{
"name": "hidden",
"version": "0.0.1",
"description": "",
"author": "",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^9.0.0",
"@nestjs/config": "^2.2.0",
"@nestjs/core": "^9.0.0",
"@nestjs/platform-express": "^9.0.0",
"@nestjs/throttler": "^3.1.0",
"@prisma/client": "^4.5.0",
"object-sha": "^2.0.7",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
"xero-node": "^4.28.1"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
"@types/express": "^4.17.13",
"@types/jest": "28.1.8",
"@types/node": "^16.18.2",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "28.1.3",
"prettier": "^2.3.2",
"prisma": "^4.5.0",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "28.0.8",
"ts-loader": "^9.2.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "4.1.0",
"typescript": "^4.8.4"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
Node.js version
16.10.0
In which operating systems have you tested?
- macOS
- Windows
- Linux
Other
No response
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 26 (8 by maintainers)
So I have actually managed to work around this like so:
@Karman40 you’re not using the newly added functions that fixes this issue.
Guys, I have just found this thread, wonderful work. Thank you for that. One last thing: could you please update also https://docs.nestjs.com/faq/raw-body and mention this in the page? It would help immensely as people like me wouldn’t be forced to find this github issue and read the whole thread in order to find out how to fix this issue.
@tolgap
If I use the following code instead of
app.use(json({ limit: configService.get<string>('LIMIT') }));, the problem is solved (also for old versions):If I remove the next line
app.use(json({ limit: configService.get<string>('LIMIT') }));, the value of the raw body is correct.You are right. Discard my comments please. I probably misunderstood those sections when reading it first time and I didn’t notice those methods are different from what we use. Sorry for not paying better attention.
I found a flexible solution:
Then:
By this the controller that binds
/some-urlhas available therawBodyproperty with the buffer.It works fine for me, congratulations!!
Oh, have to use
NestExpressApplicationNo need to cast. The function is generic.
I will update the example above to show this.
@kamilmysliwiec This is a tricky one 😞 .
The adapter has no idea that the
rawBodyoption was passed once we’re past the creation of theNestApplication.I can think of multiple solutions.
NestApplicationOptions.bodyParser: booleanoption tobodyParser: boolean | BodyParserOptionsand introduce a type that can enable/disablerawBodyand include other body parser options as wellenableRawBody(contentType: string, bodyParserOptions: object)that we can call viaapp.enableRawBody(...)I’ll try to implement each solution and report back.
cc @tolgap 🤔 I think this might actually be the expected behavior since
rawBodyconfigures internal express middleware so if someone provides their own implementation,rawBodyis ignored. Perhaps we should log a warning in this case?