diff --git a/lib/index.js b/lib/index.js index 5db2afe..d611a31 100755 --- a/lib/index.js +++ b/lib/index.js @@ -288,6 +288,11 @@ internals.Parser.prototype.multipart = function (source, contentType) { next = Hoek.once(next); // Modify next() for async events this.next = next; + // Set stream timeout + + const clientTimeout = this.settings.timeout; + let clientTimeoutId = null; + const dispenser = new Pez.Dispenser(contentType); const onError = (err) => { @@ -301,6 +306,7 @@ internals.Parser.prototype.multipart = function (source, contentType) { let data = {}; const finalize = () => { + clearTimeout(clientTimeoutId); dispenser.removeListener('error', onError); dispenser.removeListener('part', onPart); dispenser.removeListener('field', onField); @@ -314,6 +320,15 @@ internals.Parser.prototype.multipart = function (source, contentType) { return next(); }; + if (clientTimeout && + clientTimeout > 0) { + + clientTimeoutId = setTimeout(() => { + + return next(Boom.clientTimeout()); + }, clientTimeout); + } + const set = (name, value) => { arrayFields = arrayFields || (name.indexOf('[') !== -1); diff --git a/test/index.js b/test/index.js index ddaa9ef..fe26ac1 100755 --- a/test/index.js +++ b/test/index.js @@ -1467,4 +1467,40 @@ describe('parse()', () => { }); }); }); + + it('will timeout correctly for a multipart payload with output as stream', (done) => { + + const path = Path.join(__dirname, './file/image.jpg'); + const fileStream = Fs.createReadStream(path); + + const form = new FormData(); + form.append('my_file', fileStream); + form.headers = form.getHeaders(); + + Subtext.parse(form, null, { parse: true, output: 'stream', timeout: 1 }, (err, parsed) => { + + expect(err).to.exist(); + expect(err.message).to.equal('Request Timeout'); + expect(err.output.statusCode).to.equal(408); + done(); + }); + }); + + it('will timeout correctly for a multipart payload with output file', (done) => { + + const path = Path.join(__dirname, './file/image.jpg'); + const fileStream = Fs.createReadStream(path); + + const form = new FormData(); + form.append('my_file', fileStream); + form.headers = form.getHeaders(); + + Subtext.parse(form, null, { parse: true, output: 'file', timeout: 1 }, (err, parsed) => { + + expect(err).to.exist(); + expect(err.message).to.equal('Request Timeout'); + expect(err.output.statusCode).to.equal(408); + done(); + }); + }); });