From 0e5c11d68618ffd69cd38471acaf1a4c14d09e50 Mon Sep 17 00:00:00 2001 From: id_minaev Date: Wed, 14 May 2025 01:17:01 +0400 Subject: [PATCH 1/2] feat: add per route busboy configuration --- index.js | 2 +- types/index.d.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 4e2d1b33..27a73736 100644 --- a/index.js +++ b/index.js @@ -72,7 +72,7 @@ function fastifyMultipart (fastify, options, done) { return } - for await (const part of req.parts()) { + for await (const part of req.parts(req.routeOptions.config.multipart_options)) { req.body = part.fields if (part.file) { diff --git a/types/index.d.ts b/types/index.d.ts index 6d65f0a8..f2dfdd4e 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -35,6 +35,10 @@ declare module 'fastify' { interface FastifyInstance { multipartErrors: MultipartErrors; } + + interface FastifyContextConfig { + multipart_options?: Omit + } } type FastifyMultipartPlugin = FastifyPluginCallback< From 9fa4a211f93fa3c0bf9ffd76fb87257f2fa21356 Mon Sep 17 00:00:00 2001 From: id_minaev Date: Wed, 14 May 2025 14:40:48 +0400 Subject: [PATCH 2/2] test: add test for per route config with attachFieldsToBody --- index.js | 2 +- test/multipart-fileLimit.test.js | 124 +++++++++++++++++++++++++++++++ types/index.d.ts | 2 +- 3 files changed, 126 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 27a73736..6a3b209c 100644 --- a/index.js +++ b/index.js @@ -72,7 +72,7 @@ function fastifyMultipart (fastify, options, done) { return } - for await (const part of req.parts(req.routeOptions.config.multipart_options)) { + for await (const part of req.parts(req.routeOptions.config.multipartOptions)) { req.body = part.fields if (part.file) { diff --git a/test/multipart-fileLimit.test.js b/test/multipart-fileLimit.test.js index e4880749..b4710fff 100644 --- a/test/multipart-fileLimit.test.js +++ b/test/multipart-fileLimit.test.js @@ -316,3 +316,127 @@ test('should NOT throw fileSize limitation error when throwFileSizeLimit is glob t.error(error, 'request') } }) + +test('should throw fileSize limitation error when used alongside attachFieldsToBody and set request config', async function (t) { + t.plan(1) + + const fastify = Fastify() + t.teardown(fastify.close.bind(fastify)) + + fastify.register(multipart, { + attachFieldsToBody: true + }) + + const randomFileBuffer = Buffer.alloc(2_000_000) + crypto.randomFillSync(randomFileBuffer) + + fastify.post('/', { + config: { + multipartOptions: { + limits: { + fileSize: 1_000_000 + } + } + } + }, async function (req, reply) { + t.fail('it should throw') + + reply.status(200).send() + }) + + await fastify.listen({ port: 0 }) + + // request + const form = new FormData() + const opts = { + hostname: '127.0.0.1', + port: fastify.server.address().port, + path: '/', + headers: form.getHeaders(), + method: 'POST' + } + + const tmpFile = 'test/random-file' + fs.writeFileSync(tmpFile, randomFileBuffer) + + const req = http.request(opts) + form.append('upload', fs.createReadStream(tmpFile)) + + form.pipe(req) + + try { + const [res] = await once(req, 'response') + t.equal(res.statusCode, 413) + res.resume() + await once(res, 'end') + + fs.unlinkSync(tmpFile) + } catch (error) { + t.error(error, 'request') + } +}) + +test('should not throw fileSize limitation error when used alongside attachFieldsToBody and set request config', async function (t) { + t.plan(4) + + const fastify = Fastify() + t.teardown(fastify.close.bind(fastify)) + + fastify.register(multipart, { + attachFieldsToBody: true + }) + + const randomFileBuffer = Buffer.alloc(900_000) + crypto.randomFillSync(randomFileBuffer) + + fastify.post('/', { + config: { + multipartOptions: { + limits: { + fileSize: 1_000_000 + } + } + } + }, async function (req, reply) { + t.ok(req.isMultipart()) + + t.same(Object.keys(req.body), ['upload']) + + const content = await req.body.upload.toBuffer() + + t.equal(content.toString(), randomFileBuffer.toString()) + + reply.status(200).send() + }) + + await fastify.listen({ port: 0 }) + + // request + const form = new FormData() + const opts = { + hostname: '127.0.0.1', + port: fastify.server.address().port, + path: '/', + headers: form.getHeaders(), + method: 'POST' + } + + const tmpFile = 'test/random-file' + fs.writeFileSync(tmpFile, randomFileBuffer) + + const req = http.request(opts) + form.append('upload', fs.createReadStream(tmpFile)) + + form.pipe(req) + + try { + const [res] = await once(req, 'response') + t.equal(res.statusCode, 200) + res.resume() + await once(res, 'end') + + fs.unlinkSync(tmpFile) + } catch (error) { + t.error(error, 'request') + } +}) diff --git a/types/index.d.ts b/types/index.d.ts index f2dfdd4e..67f7cbc0 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -37,7 +37,7 @@ declare module 'fastify' { } interface FastifyContextConfig { - multipart_options?: Omit + multipartOptions?: Omit } }