diff --git a/lib/index.js b/lib/index.js index 8ba3c1d..500e89d 100755 --- a/lib/index.js +++ b/lib/index.js @@ -19,8 +19,12 @@ const internals = {}; parameter = token "=" ( token / quoted-string ) */ -// 1: type/subtype 2: "b" 3: b -internals.contentTypeRegex = /^([^\/\s]+\/[^\s;]+)(?:(?:\s*;\s*boundary=(?:"([^"]+)"|([^;"\s]+)))|(?:\s*;[^=]+=(?:(?:"(?:[^"]+)")|(?:[^;"\s]+))))*$/i; +// 1: type/subtype 2: params +internals.contentTypeRegex = /^([^\/\s]+\/[^\s;]+)(.*)?$/; + +// 1: "b" 2: b +internals.paramsRegex = /;\s*boundary=(?:"([^"]+)"|([^;"\s]+))/i; + exports.type = function (header) { @@ -29,15 +33,25 @@ exports.type = function (header) { return Boom.badRequest('Invalid content-type header'); } - const mime = match[1].toLowerCase(); - const boundary = match[2] || match[3]; - if (mime.indexOf('multipart/') === 0 && - !boundary) { + const result = { + mime: match[1].toLowerCase() + }; - return Boom.badRequest('Invalid content-type header: multipart missing boundary'); + if (result.mime.indexOf('multipart/') === 0) { + const params = match[2]; + if (params) { + const param = params.match(internals.paramsRegex); + if (param) { + result.boundary = param[1] || param[2]; + } + } + + if (!result.boundary) { + return Boom.badRequest('Invalid content-type header: multipart missing boundary'); + } } - return { mime, boundary }; + return result; }; diff --git a/test/index.js b/test/index.js index 89c76fc..07b20c4 100755 --- a/test/index.js +++ b/test/index.js @@ -40,34 +40,59 @@ describe('type()', () => { done(); }); - it('parses header (boundary)', (done) => { + it('parses header (not multipart)', (done) => { + + const type = Content.type('application/json'); + expect(type.isBoom).to.not.exist(); + expect(type.mime).to.equal('application/json'); + expect(type.boundary).to.not.exist(); + done(); + }); + + it('parses header (not multipart with boundary)', (done) => { const type = Content.type('application/json; boundary=abcdefghijklm'); expect(type.isBoom).to.not.exist(); expect(type.mime).to.equal('application/json'); + expect(type.boundary).to.not.exist(); + done(); + }); + + it('parses header (boundary)', (done) => { + + const type = Content.type('multipart/form-data; boundary=abcdefghijklm'); + expect(type.isBoom).to.not.exist(); + expect(type.mime).to.equal('multipart/form-data'); expect(type.boundary).to.equal('abcdefghijklm'); done(); }); it('parses header (quoted boundary)', (done) => { - const type = Content.type('application/json; boundary="abcdefghijklm"'); + const type = Content.type('multipart/form-data; boundary="abcdefghijklm"'); expect(type.isBoom).to.not.exist(); - expect(type.mime).to.equal('application/json'); + expect(type.mime).to.equal('multipart/form-data'); expect(type.boundary).to.equal('abcdefghijklm'); done(); }); - it('errors on invalid header', (done) => { + it('errors on multipart missing boundary', (done) => { - const type = Content.type('application/json; some'); + const type = Content.type('multipart/form-data'); expect(type.isBoom).to.exist(); done(); }); - it('errors on multipart missing boundary', (done) => { + it('errors on multipart missing boundary (with params)', (done) => { - const type = Content.type('multipart/form-data'); + const type = Content.type('multipart/form-data; some=thing'); + expect(type.isBoom).to.exist(); + done(); + }); + + it('errors on invalid header', (done) => { + + const type = Content.type('multipart'); expect(type.isBoom).to.exist(); done(); });