From 83762e051d5e34d9e43caebd6275780da05c6a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E0=A4=95=E0=A4=BE=E0=A4=B0=E0=A4=A4=E0=A5=8B=E0=A4=AB?= =?UTF-8?q?=E0=A5=8D=E0=A4=AB=E0=A5=87=E0=A4=B2=E0=A4=B8=E0=A5=8D=E0=A4=95?= =?UTF-8?q?=E0=A5=8D=E0=A4=B0=E0=A4=BF=E0=A4=AA=E0=A5=8D=E0=A4=9F=E2=84=A2?= Date: Wed, 18 Oct 2023 21:52:15 +0200 Subject: [PATCH] fix(core): Handle gzip and deflate compressed request payloads (#7461) NODE-870 --- packages/cli/src/middlewares/bodyParser.ts | 19 ++++++++- .../middlewares/bodyParser.test.ts | 40 +++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 packages/cli/test/integration/middlewares/bodyParser.test.ts diff --git a/packages/cli/src/middlewares/bodyParser.ts b/packages/cli/src/middlewares/bodyParser.ts index 538302c44fe49..2f2efe709e134 100644 --- a/packages/cli/src/middlewares/bodyParser.ts +++ b/packages/cli/src/middlewares/bodyParser.ts @@ -1,4 +1,6 @@ import getRawBody from 'raw-body'; +import { type Readable } from 'stream'; +import { createGunzip, createInflate } from 'zlib'; import type { Request, RequestHandler } from 'express'; import { parse as parseQueryString } from 'querystring'; import { Parser as XmlParser } from 'xml2js'; @@ -20,8 +22,21 @@ export const rawBodyReader: RequestHandler = async (req, res, next) => { req.readRawBody = async () => { if (!req.rawBody) { - req.rawBody = await getRawBody(req, { - length: req.headers['content-length'], + let stream: Readable = req; + let contentLength: string | undefined; + const contentEncoding = req.headers['content-encoding']; + switch (contentEncoding) { + case 'gzip': + stream = req.pipe(createGunzip()); + break; + case 'deflate': + stream = req.pipe(createInflate()); + break; + default: + contentLength = req.headers['content-length']; + } + req.rawBody = await getRawBody(stream, { + length: contentLength, limit: `${String(payloadSizeMax)}mb`, }); req._body = true; diff --git a/packages/cli/test/integration/middlewares/bodyParser.test.ts b/packages/cli/test/integration/middlewares/bodyParser.test.ts new file mode 100644 index 0000000000000..d17c3fcb11fb1 --- /dev/null +++ b/packages/cli/test/integration/middlewares/bodyParser.test.ts @@ -0,0 +1,40 @@ +import { createServer } from 'http'; +import { gzipSync, deflateSync } from 'zlib'; +import type { Request, Response } from 'express'; +import request from 'supertest'; +import { rawBodyReader, bodyParser } from '@/middlewares/bodyParser'; + +describe('bodyParser', () => { + const server = createServer((req: Request, res: Response) => { + rawBodyReader(req, res, async () => { + bodyParser(req, res, () => res.end(JSON.stringify(req.body))); + }); + }); + + it('should handle uncompressed data', async () => { + const response = await request(server).post('/').send({ hello: 'world' }).expect(200); + expect(response.text).toEqual('{"hello":"world"}'); + }); + + it('should handle gzip data', async () => { + const response = await request(server) + .post('/') + .set('content-encoding', 'gzip') + // @ts-ignore + .serialize((d) => gzipSync(JSON.stringify(d))) + .send({ hello: 'world' }) + .expect(200); + expect(response.text).toEqual('{"hello":"world"}'); + }); + + it('should handle deflate data', async () => { + const response = await request(server) + .post('/') + .set('content-encoding', 'deflate') + // @ts-ignore + .serialize((d) => deflateSync(JSON.stringify(d))) + .send({ hello: 'world' }) + .expect(200); + expect(response.text).toEqual('{"hello":"world"}'); + }); +});