From 0ee64bdafcffe9cab2748198fb96db4c89978953 Mon Sep 17 00:00:00 2001 From: Eran Hammer Date: Mon, 16 Sep 2019 12:46:46 -0700 Subject: [PATCH] Change multipart to false by default. Closes #3920 --- API.md | 6 ++++-- lib/config.js | 4 +++- test/payload.js | 41 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/API.md b/API.md index 9072f8cd8..9dc68af25 100755 --- a/API.md +++ b/API.md @@ -3198,11 +3198,13 @@ cause the server to run out of memory. #### `route.options.payload.multipart` -Default value: none. +Default value: `false`. Overrides payload processing for multipart requests. Value can be one of: -- `false` - disable multipart processing. +- `false` - disable multipart processing (this is the default value). + +- `true` - enable multipart processing using the [`output`](#route.options.payload.output) value. - an object with the following required options: diff --git a/lib/config.js b/lib/config.js index 98ad04497..e76ff10a4 100755 --- a/lib/config.js +++ b/lib/config.js @@ -143,7 +143,9 @@ internals.routeBase = Joi.object({ multipart: Joi.object({ output: Joi.valid('data', 'stream', 'file', 'annotated').required() }) - .allow(false), + .default(false) + .allow(true, false) + .when('.', { is: true, then: Joi.object().strip() }), allow: Joi.array().items(Joi.string()).single(), override: Joi.string(), protoAction: Joi.valid('error', 'remove', 'ignore').default('error'), diff --git a/test/payload.js b/test/payload.js index b803fc24b..98675577a 100755 --- a/test/payload.js +++ b/test/payload.js @@ -575,7 +575,7 @@ describe('Payload', () => { }; const server = Hapi.server(); - server.route({ method: 'POST', path: '/echo', handler }); + server.route({ method: 'POST', path: '/echo', handler, options: { payload: { multipart: true } } }); const res = await server.inject({ method: 'POST', url: '/echo', payload: multipartPayload, headers: { 'content-type': 'multipart/form-data; boundary=AaB03x' } }); expect(Object.keys(res.result).length).to.equal(3); @@ -698,10 +698,47 @@ describe('Payload', () => { '--AaB03x--\r\n'; const server = Hapi.server(); - server.route({ method: 'POST', path: '/echo', options: { handler: () => 'result', payload: { output: 'data', parse: true, maxBytes: 5 } } }); + server.route({ method: 'POST', path: '/echo', options: { handler: () => 'result', payload: { output: 'data', parse: true, maxBytes: 5, multipart: true } } }); const res = await server.inject({ method: 'POST', url: '/echo', payload: multipartPayload, simulate: { split: true }, headers: { 'content-length': null, 'content-type': 'multipart/form-data; boundary=AaB03x' } }); expect(res.statusCode).to.equal(400); expect(res.payload.toString()).to.equal('{"statusCode":400,"error":"Bad Request","message":"Invalid multipart payload format"}'); }); + + it('errors if multipart disabled (default)', async () => { + + const multipartPayload = + '--AaB03x\r\n' + + 'content-disposition: form-data; name="x"\r\n' + + '\r\n' + + 'First\r\n' + + '--AaB03x\r\n' + + 'content-disposition: form-data; name="x"\r\n' + + '\r\n' + + 'Second\r\n' + + '--AaB03x\r\n' + + 'content-disposition: form-data; name="x"\r\n' + + '\r\n' + + 'Third\r\n' + + '--AaB03x\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + + 'Joe Blow\r\nalmost tricked you!\r\n' + + '--AaB03x\r\n' + + 'content-disposition: form-data; name="field1"\r\n' + + '\r\n' + + 'Repeated name segment\r\n' + + '--AaB03x\r\n' + + 'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' + + 'Content-Type: text/plain\r\n' + + '\r\n' + + '... contents of file1.txt ...\r\r\n' + + '--AaB03x--\r\n'; + + const server = Hapi.server(); + server.route({ method: 'POST', path: '/echo', options: { handler: () => 'result', payload: { output: 'data', parse: true, maxBytes: 5 } } }); + + const res = await server.inject({ method: 'POST', url: '/echo', payload: multipartPayload, simulate: { split: true }, headers: { 'content-length': null, 'content-type': 'multipart/form-data; boundary=AaB03x' } }); + expect(res.statusCode).to.equal(415); + }); });