multiparty
Advanced tools
Comparing version 4.2.1 to 4.2.2
93
index.js
@@ -20,3 +20,2 @@ /*! | ||
var StringDecoder = require('string_decoder').StringDecoder; | ||
var fdSlicer = require('fd-slicer'); | ||
@@ -55,3 +54,3 @@ var START = 0; | ||
var self = this; | ||
stream.Writable.call(self); | ||
stream.Writable.call(self, { emitClose: false }) | ||
@@ -97,2 +96,4 @@ self.error = null; | ||
self.on('close', onClosed) | ||
if (cb) { | ||
@@ -190,6 +191,10 @@ // if the user supplies a callback, this implies autoFields and autoFiles | ||
function onClosed () { | ||
req.removeListener('aborted', onReqAborted) | ||
} | ||
function onReqAborted() { | ||
waitend = false; | ||
self.emit('aborted'); | ||
handleError(new Error("Request aborted")); | ||
handleError(new Error('Request aborted')) | ||
} | ||
@@ -366,3 +371,3 @@ | ||
} | ||
} else if (index - 1 === boundaryLength) { | ||
} else if (index - 1 === boundaryLength) { | ||
if (self.partBoundaryFlag) { | ||
@@ -405,3 +410,3 @@ index = 0; | ||
} else if (index > 1) { | ||
return self.handleError(new Error("Parser has invalid state.")); | ||
return self.handleError(new Error('Parser has invalid state.')) | ||
} | ||
@@ -413,3 +418,3 @@ index++; | ||
default: | ||
self.handleError(new Error("Parser has invalid state.")); | ||
self.handleError(new Error('Parser has invalid state.')) | ||
return; | ||
@@ -527,3 +532,3 @@ } | ||
self.boundary.length - LAST_BOUNDARY_SUFFIX_LEN) : | ||
undefined; | ||
undefined; | ||
@@ -539,2 +544,28 @@ if (self.destStream.filename == null && self.autoFields) { | ||
util.inherits(LimitStream, stream.Transform) | ||
function LimitStream (limit) { | ||
stream.Transform.call(this) | ||
this.bytes = 0 | ||
this.limit = limit | ||
} | ||
LimitStream.prototype._transform = function _transform (chunk, encoding, callback) { | ||
var length = !Buffer.isBuffer(chunk) | ||
? Buffer.byteLength(chunk, encoding) | ||
: chunk.length | ||
this.bytes += length | ||
if (this.bytes > this.limit) { | ||
var err = new Error('maximum file length exceeded') | ||
err.code = 'ETOOBIG' | ||
callback(err) | ||
} else { | ||
this.push(chunk) | ||
this.emit('progress', this.bytes, length) | ||
callback() | ||
} | ||
} | ||
function flushWriteCbs(self) { | ||
@@ -569,3 +600,3 @@ self.writeCbs.forEach(function(cb) { | ||
// will help us figure it out. | ||
self.handleError(new Error("unexpected endFlush")); | ||
self.handleError(new Error('unexpected endFlush')) | ||
return; | ||
@@ -608,3 +639,3 @@ } | ||
function holdEmitQueue(self, eventEmitter) { | ||
var item = {cb: null, ee: eventEmitter, err: null}; | ||
var item = { cb: null, ee: eventEmitter, err: null } | ||
self.emitQueue.push(item); | ||
@@ -668,4 +699,6 @@ return function(cb) { | ||
publicFile: publicFile, | ||
ws: null | ||
ls: null, | ||
ws: fs.createWriteStream(publicFile.path, { flags: 'wx' }) | ||
}; | ||
self.openedFiles.push(internalFile) | ||
beginFlush(self); // flush to write stream | ||
@@ -676,17 +709,12 @@ var emitAndReleaseHold = holdEmitQueue(self, fileStream); | ||
}); | ||
fs.open(publicFile.path, 'wx', function(err, fd) { | ||
if (err) return self.handleError(err); | ||
var slicer = fdSlicer.createFromFd(fd, {autoClose: true}); | ||
internalFile.ws.on('error', function (err) { | ||
self.handleError(err) | ||
}) | ||
internalFile.ws.on('open', function () { | ||
// end option here guarantees that no more than that amount will be written | ||
// or else an error will be emitted | ||
internalFile.ws = slicer.createWriteStream({end: self.maxFilesSize - self.totalFileSize}); | ||
internalFile.ls = new LimitStream(self.maxFilesSize - self.totalFileSize) | ||
internalFile.ls.pipe(internalFile.ws) | ||
// if an error ocurred while we were waiting for fs.open we handle that | ||
// cleanup now | ||
self.openedFiles.push(internalFile); | ||
if (self.error) return cleanupOpenFiles(self); | ||
var prevByteCount = 0; | ||
internalFile.ws.on('error', function(err) { | ||
internalFile.ls.on('error', function (err) { | ||
self.handleError(err.code === 'ETOOBIG' | ||
@@ -696,9 +724,7 @@ ? createError(413, err.message, { code: err.code }) | ||
}); | ||
internalFile.ws.on('progress', function() { | ||
publicFile.size = internalFile.ws.bytesWritten; | ||
var delta = publicFile.size - prevByteCount; | ||
self.totalFileSize += delta; | ||
prevByteCount = publicFile.size; | ||
internalFile.ls.on('progress', function (totalBytes, chunkBytes) { | ||
publicFile.size = totalBytes | ||
self.totalFileSize += chunkBytes | ||
}); | ||
slicer.on('close', function() { | ||
internalFile.ws.on('close', function () { | ||
if (self.error) return; | ||
@@ -710,3 +736,3 @@ emitAndReleaseHold(function() { | ||
}); | ||
fileStream.pipe(internalFile.ws); | ||
fileStream.pipe(internalFile.ls) | ||
}); | ||
@@ -752,5 +778,5 @@ } | ||
self.headerFieldDecoder = new StringDecoder(self.encoding); | ||
self.headerField = ""; | ||
self.headerField = '' | ||
self.headerValueDecoder = new StringDecoder(self.encoding); | ||
self.headerValue = ""; | ||
self.headerValue = '' | ||
} | ||
@@ -790,7 +816,6 @@ | ||
if (!m) { | ||
m = headerValue.match(/\bfilename\*=utf-8\'\'(.*?)($|; )/i); | ||
m = headerValue.match(/\bfilename\*=utf-8''(.*?)($|; )/i) | ||
if (m) { | ||
m[1] = decodeURI(m[1]); | ||
} | ||
else { | ||
} else { | ||
return; | ||
@@ -797,0 +822,0 @@ } |
{ | ||
"name": "multiparty", | ||
"description": "multipart/form-data parser which supports streaming", | ||
"version": "4.2.1", | ||
"version": "4.2.2", | ||
"author": "Andrew Kelley <superjoe30@gmail.com>", | ||
@@ -20,19 +20,19 @@ "contributors": [ | ||
"dependencies": { | ||
"fd-slicer": "1.1.0", | ||
"http-errors": "~1.7.0", | ||
"safe-buffer": "5.1.2", | ||
"http-errors": "~1.8.0", | ||
"safe-buffer": "5.2.1", | ||
"uid-safe": "2.1.5" | ||
}, | ||
"devDependencies": { | ||
"eslint": "2.13.1", | ||
"istanbul": "0.4.5", | ||
"mkdirp": "0.5.1", | ||
"mocha": "3.5.3", | ||
"eslint": "7.5.0", | ||
"eslint-plugin-markdown": "1.0.2", | ||
"mkdirp": "0.5.5", | ||
"mocha": "7.2.0", | ||
"nyc": "15.1.0", | ||
"pend": "1.2.0", | ||
"require-all": "3.0.0", | ||
"rimraf": "2.5.4", | ||
"superagent": "1.8.5" | ||
"rimraf": "2.6.3", | ||
"superagent": "2.3.0" | ||
}, | ||
"files": [ | ||
"CHANGELOG.md", | ||
"HISTORY.md", | ||
"LICENSE", | ||
@@ -46,7 +46,7 @@ "README.md", | ||
"scripts": { | ||
"lint": "eslint .", | ||
"test": "mocha --reporter spec --bail --check-leaks --no-exit test/", | ||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks --no-exit test/", | ||
"test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks --no-exit test/" | ||
"lint": "eslint --plugin markdown --ext js,md .", | ||
"test": "mocha --reporter spec --bail --check-leaks test/", | ||
"test-ci": "nyc --reporter=text npm test", | ||
"test-cov": "nyc --reporter=html --reporter=text npm test" | ||
} | ||
} |
# multiparty | ||
[![NPM Version][npm-image]][npm-url] | ||
[![NPM Downloads][downloads-image]][downloads-url] | ||
[![NPM Version][npm-version-image]][npm-url] | ||
[![NPM Downloads][npm-downloads-image]][npm-url] | ||
[![Node.js Version][node-version-image]][node-version-url] | ||
@@ -42,5 +42,5 @@ [![Build Status][travis-image]][travis-url] | ||
form.parse(req, function(err, fields, files) { | ||
res.writeHead(200, {'content-type': 'text/plain'}); | ||
res.writeHead(200, { 'content-type': 'text/plain' }); | ||
res.write('received upload:\n\n'); | ||
res.end(util.inspect({fields: fields, files: files})); | ||
res.end(util.inspect({ fields: fields, files: files })); | ||
}); | ||
@@ -52,3 +52,3 @@ | ||
// show a file upload form | ||
res.writeHead(200, {'content-type': 'text/html'}); | ||
res.writeHead(200, { 'content-type': 'text/html' }); | ||
res.end( | ||
@@ -68,2 +68,4 @@ '<form action="/upload" enctype="multipart/form-data" method="post">'+ | ||
<!-- eslint-disable no-unused-vars --> | ||
```js | ||
@@ -227,2 +229,7 @@ var form = new multiparty.Form(options) | ||
Emitted when a chunk of data is received for the form. The `bytesReceived` | ||
argument contains the total count of bytes received for this form so far. The | ||
`bytesExpected` argument contains the total expected bytes if known, otherwise | ||
`null`. | ||
#### 'close' | ||
@@ -242,3 +249,3 @@ | ||
listener, multiparty automatically sets `form.autoFiles` to `true` and will | ||
stream uploads to disk for you. | ||
stream uploads to disk for you. | ||
@@ -264,11 +271,10 @@ **The max bytes accepted per request can be specified with `maxFilesSize`.** | ||
[npm-image]: https://img.shields.io/npm/v/multiparty.svg | ||
[coveralls-image]: https://badgen.net/coveralls/c/github/pillarjs/multiparty/master | ||
[coveralls-url]: https://coveralls.io/r/pillarjs/multiparty?branch=master | ||
[node-version-image]: https://badgen.net/npm/node/multiparty | ||
[node-version-url]: https://nodejs.org/en/download | ||
[npm-downloads-image]: https://badgen.net/npm/dm/multiparty | ||
[npm-url]: https://npmjs.org/package/multiparty | ||
[node-version-image]: https://img.shields.io/node/v/multiparty.svg | ||
[node-version-url]: https://nodejs.org/en/download/ | ||
[travis-image]: https://img.shields.io/travis/pillarjs/multiparty/master.svg | ||
[npm-version-image]: https://badgen.net/npm/v/multiparty | ||
[travis-image]: https://badgen.net/travis/pillarjs/multiparty/master | ||
[travis-url]: https://travis-ci.org/pillarjs/multiparty | ||
[coveralls-image]: https://img.shields.io/coveralls/pillarjs/multiparty/master.svg | ||
[coveralls-url]: https://coveralls.io/r/pillarjs/multiparty?branch=master | ||
[downloads-image]: https://img.shields.io/npm/dm/multiparty.svg | ||
[downloads-url]: https://npmjs.org/package/multiparty |
3
712
275
39183
9
+ Addedhttp-errors@1.8.1(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsetprototypeof@1.2.0(transitive)
+ Addedtoidentifier@1.0.1(transitive)
- Removedfd-slicer@1.1.0
- Removedfd-slicer@1.1.0(transitive)
- Removedhttp-errors@1.7.3(transitive)
- Removedpend@1.2.0(transitive)
- Removedsafe-buffer@5.1.2(transitive)
- Removedsetprototypeof@1.1.1(transitive)
- Removedtoidentifier@1.0.0(transitive)
Updatedhttp-errors@~1.8.0
Updatedsafe-buffer@5.2.1