diff --git a/README.md b/README.md index 5eecb174..ae21552a 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,20 @@ fastify.post('/', async function (req, reply) { }) ``` +Or to a route options when `attachFieldsToBody` is used. +```js +fastify.post('/', { + config: { + multipartOptions: { + limits: { fileSize: 1000 } + } + } +}, async function (req, reply) { + const buffer = req.body.file.toBuffer(); + reply.send() +}) +``` + ## Handle multiple file streams ```js diff --git a/index.js b/index.js index 4e2d1b33..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()) { + 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 ddf6c352..6aed6a5e 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.assert.ifError(error) } }) + +test('should throw fileSize limitation error when used alongside attachFieldsToBody and set request config', async function (t) { + t.plan(1) + + const fastify = Fastify() + t.after(() => fastify.close()) + + 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.assert.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.assert.equal(res.statusCode, 413) + res.resume() + await once(res, 'end') + + fs.unlinkSync(tmpFile) + } catch (error) { + t.assert.ifError(error) + } +}) + +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.after(() => fastify.close()) + + 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.assert.ok(req.isMultipart()) + + t.assert.deepStrictEqual(Object.keys(req.body), ['upload']) + + const content = await req.body.upload.toBuffer() + + t.assert.strictEqual(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.assert.equal(res.statusCode, 200) + res.resume() + await once(res, 'end') + + fs.unlinkSync(tmpFile) + } catch (error) { + t.assert.ifError(error) + } +}) diff --git a/types/index.d.ts b/types/index.d.ts index 6d65f0a8..67f7cbc0 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -35,6 +35,10 @@ declare module 'fastify' { interface FastifyInstance { multipartErrors: MultipartErrors; } + + interface FastifyContextConfig { + multipartOptions?: Omit + } } type FastifyMultipartPlugin = FastifyPluginCallback< diff --git a/types/index.test-d.ts b/types/index.test-d.ts index 7d33e365..b4fe66e5 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -179,6 +179,22 @@ const runServer = async () => { reply.send() }) + app.post('/upload/files', { + config: { + multipartOptions: {} + } + }, async function (req, reply) { + req.routeOptions.config.multipartOptions + expectType>(req.routeOptions.config.multipartOptions) + reply.send() + }) + + app.post('/upload/files', async function (req, reply) { + req.routeOptions.config.multipartOptions + expectError>(req.routeOptions.config?.multipartOptions) + reply.send() + }) + await app.ready() }