[Pkg-javascript-commits] [node-multiparty] 02/05: Imported Upstream version 4.1.2
Andrew Kelley
andrewrk-guest at moszumanska.debian.org
Sat May 16 17:30:49 UTC 2015
This is an automated email from the git hooks/post-receive script.
andrewrk-guest pushed a commit to branch master
in repository node-multiparty.
commit 9b66bc1409df6e72fd9a83dd868b4dc7d3456271
Author: Andrew Kelley <superjoe30 at gmail.com>
Date: Sat May 16 17:26:41 2015 +0000
Imported Upstream version 4.1.2
---
.gitignore | 4 +-
.npmignore | 4 +
.travis.yml | 6 +
CHANGELOG.md | 20 +
README.md | 20 +-
examples/azureblobstorage.js | 2 +-
examples/s3.js | 4 -
index.js | 96 +-
package.json | 15 +-
.../http/{no-filename => filename}/empty.http | 0
.../{no-filename => filename}/filename-name.http | 0
.../http/{no-filename => filename}/generic.http | 0
.../filename-name.http => filename/quotes.http} | 4 +-
test/fixture/js/{no-filename.js => filename.js} | 5 +
test/standalone/test-chunked.js | 43 -
test/standalone/test-connection-aborted-closed.js | 44 -
test/standalone/test-connection-aborted.js | 30 -
test/standalone/test-content-transfer-encoding.js | 52 -
test/standalone/test-emit-order.js | 61 -
test/standalone/test-epilogue-last-chunk.js | 44 -
test/standalone/test-error-listen-after-parse.js | 20 -
test/standalone/test-error-unpipe.js | 43 -
test/standalone/test-invalid.js | 35 -
test/standalone/test-issue-15.js | 76 --
test/standalone/test-issue-19.js | 44 -
test/standalone/test-issue-21.js | 85 --
test/standalone/test-issue-32.js | 38 -
test/standalone/test-issue-36.js | 38 -
test/standalone/test-issue-4.js | 53 -
test/standalone/test-max-fields.js | 52 -
test/standalone/test-max-files-size-exact.js | 42 -
test/standalone/test-max-files-size.js | 50 -
test/standalone/test-missing-boundary-end.js | 46 -
test/standalone/test-parse-type-error.js | 39 -
test/standalone/test-req-encoding.js | 39 -
test/standalone/test-stream-error.js | 36 -
test/test.js | 1284 +++++++++++++++++++-
37 files changed, 1372 insertions(+), 1102 deletions(-)
diff --git a/.gitignore b/.gitignore
index 07e6e47..4b173c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
-/node_modules
+node_modules/
+coverage/
+npm-debug.log
diff --git a/.npmignore b/.npmignore
index d457948..bc1e710 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,2 +1,6 @@
+coverage/
test/
examples/
+.jshintrc
+.travis.yml
+npm-debug.log
diff --git a/.travis.yml b/.travis.yml
index 6e5919d..da616f8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,3 +1,9 @@
language: node_js
node_js:
- "0.10"
+ - "0.12"
+sudo: false
+script:
+ - "npm run test-travis"
+after_script:
+ - "npm install coveralls at 2 && cat ./coverage/lcov.info | ./node_modules/.bin/coveralls"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index de6139c..b3d0414 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,23 @@
+### 4.1.2
+
+ * Douglas Christopher Wilson:
+ - Do not emit error on part prior to emitting part
+ - Fix filename with quotes truncating from certain clients
+
+### 4.1.1
+
+ * Douglas Christopher Wilson:
+ - Do not clobber existing temporary files
+
+### 4.1.0
+
+ * Douglas Christopher Wilson:
+ - Update dependencies to latest
+ - HTTP-related errors have a `statusCode` field
+
+ * Andrew Kelley:
+ - Refactor tests so that we can have a coverage badge
+
### 4.0.0
* Andrew Kelley:
diff --git a/README.md b/README.md
index f398ffb..02551f6 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# multiparty [![Build Status](https://travis-ci.org/andrewrk/node-multiparty.svg?branch=master)](https://travis-ci.org/andrewrk/node-multiparty) [![NPM version](https://badge.fury.io/js/multiparty.svg)](http://badge.fury.io/js/multiparty)
+# multiparty [![Build Status](https://travis-ci.org/andrewrk/node-multiparty.svg?branch=master)](https://travis-ci.org/andrewrk/node-multiparty) [![Coverage Status](https://img.shields.io/coveralls/andrewrk/node-multiparty.svg)](https://coveralls.io/r/andrewrk/node-multiparty)
Parse http requests with content-type `multipart/form-data`, also known as file uploads.
@@ -31,9 +31,9 @@ npm install multiparty
Parse an incoming `multipart/form-data` request.
```js
-var multiparty = require('multiparty')
- , http = require('http')
- , util = require('util')
+var multiparty = require('multiparty');
+var http = require('http');
+var util = require('util');
http.createServer(function(req, res) {
if (req.url === '/upload' && req.method === 'POST') {
@@ -110,15 +110,15 @@ form.on('part', function(part) {
// You *must* act on the part by reading it
// NOTE: if you want to ignore it, just call "part.resume()"
- if (part.filename === null) {
- // filename is "null" when this is a field and not a file
+ if (!part.filename) {
+ // filename is not defined when this is a field and not a file
console.log('got field named ' + part.name);
// ignore field's content
part.resume();
}
- if (part.filename !== null) {
- // filename is not "null" when this is a file
+ if (part.filename) {
+ // filename is defined when this is a file
count++;
console.log('got file named ' + part.name);
// ignore file's content here
@@ -188,6 +188,10 @@ multipart requests!
Only one 'error' event can ever be emitted, and if an 'error' event is
emitted, then 'close' will not be emitted.
+If the error would correspond to a certain HTTP response code, the `err` object
+will have a `statusCode` property with the value of the suggested HTTP response
+code to send back.
+
Note that an 'error' event will be emitted both from the `form` and from the
current `part`.
diff --git a/examples/azureblobstorage.js b/examples/azureblobstorage.js
index 273c332..3dcb86a 100644
--- a/examples/azureblobstorage.js
+++ b/examples/azureblobstorage.js
@@ -21,7 +21,7 @@ var server = http.createServer(function(req, res) {
form.on('part', function(part) {
if (!part.filename) return;
- var size = part.byteCount - part.byteOffset;
+ var size = part.byteCount;
var name = part.filename;
var container = 'blobContainerName';
diff --git a/examples/s3.js b/examples/s3.js
index a3b011d..d2b766d 100644
--- a/examples/s3.js
+++ b/examples/s3.js
@@ -56,10 +56,6 @@ var server = http.createServer(function(req, res) {
res.writeHead(404, {'content-type': 'text/plain'});
res.end('404');
}
-
- function onEnd() {
- throw new Error("no uploaded file");
- }
});
server.listen(PORT, function() {
console.info('listening on http://0.0.0.0:'+PORT+'/');
diff --git a/index.js b/index.js
index 88fc224..ea28502 100644
--- a/index.js
+++ b/index.js
@@ -5,7 +5,7 @@ var crypto = require('crypto');
var path = require('path');
var os = require('os');
var StringDecoder = require('string_decoder').StringDecoder;
-var FdSlicer = require('fd-slicer');
+var fdSlicer = require('fd-slicer');
var START = 0;
var START_BOUNDARY = 1;
@@ -151,13 +151,13 @@ Form.prototype.parse = function(req, cb) {
var contentType = req.headers['content-type'];
if (!contentType) {
- validationError(new Error('missing content-type header'));
+ validationError(createError(415, 'missing content-type header'));
return;
}
var m = CONTENT_TYPE_RE.exec(contentType);
if (!m) {
- validationError(new Error('unrecognized content-type: ' + contentType));
+ validationError(createError(415, 'unsupported content-type'));
return;
}
@@ -170,7 +170,7 @@ Form.prototype.parse = function(req, cb) {
}
if (!boundary) {
- validationError(new Error('content-type missing boundary: ' + require('util').inspect(m)));
+ validationError(createError(400, 'content-type missing boundary'));
return;
}
@@ -194,7 +194,7 @@ Form.prototype.parse = function(req, cb) {
req.removeListener('aborted', onReqAborted);
req.removeListener('end', onReqEnd);
if (self.destStream) {
- self.destStream.emit('error', err);
+ errorEventQueue(self, self.destStream, err);
}
}
@@ -242,11 +242,11 @@ Form.prototype._write = function(buffer, encoding, cb) {
state = CLOSE_BOUNDARY;
break;
} else if (index === boundaryLength - 2) {
- if (c !== CR) return self.handleError(new Error("Expected CR Received " + c));
+ if (c !== CR) return self.handleError(createError(400, 'Expected CR Received ' + c));
index++;
break;
} else if (index === boundaryLength - 1) {
- if (c !== LF) return self.handleError(new Error("Expected LF Received " + c));
+ if (c !== LF) return self.handleError(createError(400, 'Expected LF Received ' + c));
index = 0;
self.onParsePartBegin();
state = HEADER_FIELD_START;
@@ -274,7 +274,7 @@ Form.prototype._write = function(buffer, encoding, cb) {
if (c === COLON) {
if (index === 1) {
// empty header field
- self.handleError(new Error("Empty header field"));
+ self.handleError(createError(400, 'Empty header field'));
return;
}
self.onParseHeaderField(buffer.slice(self.headerFieldMark, i));
@@ -285,7 +285,7 @@ Form.prototype._write = function(buffer, encoding, cb) {
cl = lower(c);
if (cl < A || cl > Z) {
- self.handleError(new Error("Expected alphabetic character, received " + c));
+ self.handleError(createError(400, 'Expected alphabetic character, received ' + c));
return;
}
break;
@@ -304,11 +304,11 @@ Form.prototype._write = function(buffer, encoding, cb) {
}
break;
case HEADER_VALUE_ALMOST_DONE:
- if (c !== LF) return self.handleError(new Error("Expected LF Received " + c));
+ if (c !== LF) return self.handleError(createError(400, 'Expected LF Received ' + c));
state = HEADER_FIELD_START;
break;
case HEADERS_ALMOST_DONE:
- if (c !== LF) return self.handleError(new Error("Expected LF Received " + c));
+ if (c !== LF) return self.handleError(createError(400, 'Expected LF Received ' + c));
var err = self.onParseHeadersEnd(i + 1);
if (err) return self.handleError(err);
state = PART_DATA_START;
@@ -385,7 +385,7 @@ Form.prototype._write = function(buffer, encoding, cb) {
break;
case CLOSE_BOUNDARY:
- if (c !== HYPHEN) return self.handleError(new Error("Expected HYPHEN Received " + c));
+ if (c !== HYPHEN) return self.handleError(createError(400, 'Expected HYPHEN Received ' + c));
if (index === 1) {
self.onParsePartEnd();
state = END;
@@ -490,12 +490,12 @@ Form.prototype.onParseHeadersEnd = function(offset) {
case 'base64': break;
default:
- return new Error("unknown transfer-encoding: " + self.partTransferEncoding);
+ return createError(400, 'unknown transfer-encoding: ' + self.partTransferEncoding);
}
self.totalFieldCount += 1;
if (self.totalFieldCount > self.maxFields) {
- return new Error("maxFields " + self.maxFields + " exceeded.");
+ return createError(413, 'maxFields ' + self.maxFields + ' exceeded.');
}
self.destStream = new stream.PassThrough();
@@ -587,24 +587,47 @@ function cleanupOpenFiles(self) {
self.openedFiles = [];
}
-function holdEmitQueue(self) {
- var o = {cb: null};
- self.emitQueue.push(o);
+function holdEmitQueue(self, eventEmitter) {
+ var item = {cb: null, ee: eventEmitter, err: null};
+ self.emitQueue.push(item);
return function(cb) {
- o.cb = cb;
+ item.cb = cb;
flushEmitQueue(self);
};
}
+function errorEventQueue(self, eventEmitter, err) {
+ var items = self.emitQueue.filter(function (item) {
+ return item.ee === eventEmitter;
+ });
+
+ if (items.length === 0) {
+ eventEmitter.emit('error', err);
+ return;
+ }
+
+ items.forEach(function (item) {
+ item.err = err;
+ });
+}
+
function flushEmitQueue(self) {
while (self.emitQueue.length > 0 && self.emitQueue[0].cb) {
- self.emitQueue.shift().cb();
+ var item = self.emitQueue.shift();
+
+ // invoke the callback
+ item.cb();
+
+ if (item.err) {
+ // emit the delayed error
+ item.ee.emit('error', item.err);
+ }
}
}
function handlePart(self, partStream) {
beginFlush(self);
- var emitAndReleaseHold = holdEmitQueue(self);
+ var emitAndReleaseHold = holdEmitQueue(self, partStream);
partStream.on('end', function() {
endFlush(self);
});
@@ -627,17 +650,17 @@ function handleFile(self, fileStream) {
ws: null,
};
beginFlush(self); // flush to write stream
- var emitAndReleaseHold = holdEmitQueue(self);
+ var emitAndReleaseHold = holdEmitQueue(self, fileStream);
fileStream.on('error', function(err) {
self.handleError(err);
});
- fs.open(publicFile.path, 'w', function(err, fd) {
+ fs.open(publicFile.path, 'wx', function(err, fd) {
if (err) return self.handleError(err);
- var fdSlicer = new FdSlicer(fd, {autoClose: true});
+ var slicer = fdSlicer.createFromFd(fd, {autoClose: true});
// end option here guarantees that no more than that amount will be written
// or else an error will be emitted
- internalFile.ws = fdSlicer.createWriteStream({end: self.maxFilesSize - self.totalFileSize});
+ internalFile.ws = slicer.createWriteStream({end: self.maxFilesSize - self.totalFileSize});
// if an error ocurred while we were waiting for fs.open we handle that
// cleanup now
@@ -646,6 +669,10 @@ function handleFile(self, fileStream) {
var prevByteCount = 0;
internalFile.ws.on('error', function(err) {
+ if (err.code === 'ETOOBIG') {
+ err = createError(413, err.message);
+ err.code = 'ETOOBIG';
+ }
self.handleError(err);
});
internalFile.ws.on('progress', function() {
@@ -654,7 +681,7 @@ function handleFile(self, fileStream) {
self.totalFileSize += delta;
prevByteCount = publicFile.size;
});
- fdSlicer.on('close', function() {
+ slicer.on('close', function() {
if (self.error) return;
emitAndReleaseHold(function() {
self.emit('file', fileStream.name, publicFile);
@@ -670,7 +697,7 @@ function handleField(self, fieldStream) {
var decoder = new StringDecoder(self.encoding);
beginFlush(self);
- var emitAndReleaseHold = holdEmitQueue(self);
+ var emitAndReleaseHold = holdEmitQueue(self, fieldStream);
fieldStream.on('error', function(err) {
self.handleError(err);
});
@@ -680,7 +707,7 @@ function handleField(self, fieldStream) {
self.totalFieldSize += buffer.length;
if (self.totalFieldSize > self.maxFieldsSize) {
- self.handleError(new Error("maxFieldsSize " + self.maxFieldsSize + " exceeded"));
+ self.handleError(createError(413, 'maxFieldsSize ' + self.maxFieldsSize + ' exceeded'));
return;
}
value += decoder.write(buffer);
@@ -724,7 +751,7 @@ function setUpParser(self, boundary) {
beginFlush(self);
self.on('finish', function() {
if (self.state !== END) {
- self.handleError(new Error('stream ended unexpectedly'));
+ self.handleError(createError(400, 'stream ended unexpectedly'));
}
endFlush(self);
});
@@ -762,15 +789,22 @@ function parseFilename(headerValue) {
}
}
- var filename = m[1].substr(m[1].lastIndexOf('\\') + 1);
- filename = filename.replace(/%22/g, '"');
+ var filename = m[1];
+ filename = filename.replace(/%22|\\"/g, '"');
filename = filename.replace(/&#([\d]{4});/g, function(m, code) {
return String.fromCharCode(code);
});
- return filename;
+ return filename.substr(filename.lastIndexOf('\\') + 1);
}
function lower(c) {
return c | 0x20;
}
+function createError(status, message) {
+ var error = new Error(message);
+ Error.captureStackTrace(error, createError);
+ error.status = status;
+ error.statusCode = status;
+ return error;
+}
diff --git a/package.json b/package.json
index 58a6498..b32bc9c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "multiparty",
- "version": "4.0.0",
+ "version": "4.1.2",
"description": "multipart/form-data parser which supports streaming",
"repository": {
"type": "git",
@@ -14,21 +14,24 @@
"s3"
],
"devDependencies": {
+ "findit2": "~2.2.3",
+ "istanbul": "~0.3.4",
"mkdirp": "~0.5.0",
- "pend": "~1.1.3",
+ "pend": "~1.2.0",
"rimraf": "~2.2.8",
- "superagent": "~0.20.0",
- "findit2": "~2.2.2"
+ "superagent": "~0.21.0"
},
"scripts": {
- "test": "node test/test.js"
+ "test": "node test/test.js",
+ "test-cov": "istanbul cover test/test.js",
+ "test-travis": "istanbul cover test/test.js --report lcovonly"
},
"engines": {
"node": ">=0.10.0"
},
"license": "MIT",
"dependencies": {
- "fd-slicer": "~0.3.2"
+ "fd-slicer": "~1.0.0"
},
"bugs": {
"url": "https://github.com/andrewrk/node-multiparty/issues"
diff --git a/test/fixture/http/no-filename/empty.http b/test/fixture/http/filename/empty.http
similarity index 100%
rename from test/fixture/http/no-filename/empty.http
rename to test/fixture/http/filename/empty.http
diff --git a/test/fixture/http/no-filename/filename-name.http b/test/fixture/http/filename/filename-name.http
similarity index 100%
copy from test/fixture/http/no-filename/filename-name.http
copy to test/fixture/http/filename/filename-name.http
diff --git a/test/fixture/http/no-filename/generic.http b/test/fixture/http/filename/generic.http
similarity index 100%
rename from test/fixture/http/no-filename/generic.http
rename to test/fixture/http/filename/generic.http
diff --git a/test/fixture/http/no-filename/filename-name.http b/test/fixture/http/filename/quotes.http
similarity index 72%
rename from test/fixture/http/no-filename/filename-name.http
rename to test/fixture/http/filename/quotes.http
index 65261bd..5908f6d 100644
--- a/test/fixture/http/no-filename/filename-name.http
+++ b/test/fixture/http/filename/quotes.http
@@ -1,10 +1,10 @@
POST /upload HTTP/1.1
Host: localhost:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarytyE4wkKlZ5CQJVTG
-Content-Length: 209
+Content-Length: 211
------WebKitFormBoundarytyE4wkKlZ5CQJVTG
-Content-Disposition: form-data; filename="plain.txt"; name="upload"
+Content-Disposition: form-data; name="upload"; filename="foo \"bar\""
Content-Type: text/plain
I am a plain text file
diff --git a/test/fixture/js/no-filename.js b/test/fixture/js/filename.js
similarity index 68%
rename from test/fixture/js/no-filename.js
rename to test/fixture/js/filename.js
index 556710b..b37f667 100644
--- a/test/fixture/js/no-filename.js
+++ b/test/fixture/js/filename.js
@@ -10,3 +10,8 @@ module.exports['filename-name.http'] = [
{type: 'file', name: 'upload', filename: 'plain.txt', fixture: 'plain.txt',
sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
];
+
+module.exports['quotes.http'] = [
+ {type: 'file', name: 'upload', filename: 'foo "bar"', fixture: 'plain.txt',
+ sha1: 'b31d07bac24ac32734de88b3687dddb10e976872'},
+];
diff --git a/test/standalone/test-chunked.js b/test/standalone/test-chunked.js
deleted file mode 100644
index b2eda3f..0000000
--- a/test/standalone/test-chunked.js
+++ /dev/null
@@ -1,43 +0,0 @@
-var multiparty = require('../../')
- , assert = require('assert')
- , http = require('http')
- , net = require('net');
-
-var server = http.createServer(function(req, resp) {
- var form = new multiparty.Form();
-
- var partCount = 0;
- form.on('part', function(part) {
- part.resume();
- partCount++;
- assert.strictEqual(typeof part.byteCount, 'undefined');
- });
- form.on('close', function() {
- assert.strictEqual(partCount, 1);
- resp.end();
- });
-
- form.parse(req);
-});
-server.listen(function() {
- var socket = net.connect(server.address().port, 'localhost', function () {
- socket.write('POST / HTTP/1.1\r\n');
- socket.write('Host: localhost\r\n');
- socket.write('Connection: close\r\n');
- socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
- socket.write('Transfer-Encoding: chunked\r\n');
- socket.write('\r\n');
- socket.write('7\r\n');
- socket.write('--foo\r\n\r\n');
- socket.write('43\r\n');
- socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n\r\n');
- socket.write('12\r\n');
- socket.write('\r\nsome text here\r\n\r\n');
- socket.write('9\r\n');
- socket.write('--foo--\r\n\r\n');
- socket.write('0\r\n\r\n');
- socket.on('close', function () {
- server.close();
- });
- });
-});
diff --git a/test/standalone/test-connection-aborted-closed.js b/test/standalone/test-connection-aborted-closed.js
deleted file mode 100644
index 1c3bc2c..0000000
--- a/test/standalone/test-connection-aborted-closed.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var socket;
-var server = http.createServer(function (req, res) {
- var called = false;
- var form = new multiparty.Form();
-
- form.parse(req, function (err, fields, files) {
- assert.ok(!called);
- called = true;
-
- assert.ifError(err);
- assert.equal(Object.keys(fields).length, 1);
- socket.end();
- });
-});
-
-server.listen(0, 'localhost', function () {
- socket = net.connect(server.address().port, 'localhost', function () {
- socket.write('POST / HTTP/1.1\r\n');
- socket.write('Host: localhost\r\n');
- socket.write('Connection: close\r\n');
- socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
- socket.write('Transfer-Encoding: chunked\r\n');
- socket.write('\r\n');
- socket.write('7\r\n');
- socket.write('--foo\r\n\r\n');
- socket.write('2D\r\n');
- socket.write('Content-Disposition: form-data; name="data"\r\n\r\n');
- socket.write('12\r\n');
- socket.write('\r\nsome text here\r\n\r\n');
- socket.write('7\r\n');
- socket.write('--foo--\r\n');
- socket.write('2\r\n');
- socket.write('\r\n\r\n');
- socket.write('0\r\n\r\n');
- socket.on('close', function () {
- server.close();
- });
- });
-});
diff --git a/test/standalone/test-connection-aborted.js b/test/standalone/test-connection-aborted.js
deleted file mode 100644
index 6448e79..0000000
--- a/test/standalone/test-connection-aborted.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var server = http.createServer(function (req, res) {
- var form = new multiparty.Form();
- var aborted_received = false;
- form.on('aborted', function () {
- aborted_received = true;
- });
- form.on('error', function () {
- assert(aborted_received, 'Error event should follow aborted');
- server.close();
- });
- form.on('end', function () {
- throw new Error('Unexpected "end" event');
- });
- form.on('close', function () {
- throw new Error('Unexpected "close" event');
- });
- form.parse(req);
-}).listen(0, 'localhost', function () {
- var client = net.connect(server.address().port);
- client.write(
- "POST / HTTP/1.1\r\n" +
- "Content-Length: 70\r\n" +
- "Content-Type: multipart/form-data; boundary=foo\r\n\r\n");
- client.end();
-});
diff --git a/test/standalone/test-content-transfer-encoding.js b/test/standalone/test-content-transfer-encoding.js
deleted file mode 100644
index 35e5a1f..0000000
--- a/test/standalone/test-content-transfer-encoding.js
+++ /dev/null
@@ -1,52 +0,0 @@
-var assert = require('assert')
- , multiparty = require('../../')
- , http = require('http')
- , path = require('path')
- , TMP_PATH = path.join(__dirname, '..', 'tmp')
-
-var server = http.createServer(function(req, res) {
- var form = new multiparty.Form();
- form.uploadDir = TMP_PATH;
- form.on('close', function () {
- throw new Error('Unexpected "close" event');
- });
- form.on('end', function () {
- throw new Error('Unexpected "end" event');
- });
- form.on('error', function (e) {
- res.writeHead(500);
- res.end(e.message);
- });
- form.parse(req);
-});
-
-server.listen(0, function() {
- var body =
- '--foo\r\n' +
- 'Content-Disposition: form-data; name="file1"; filename="file1"\r\n' +
- 'Content-Type: application/octet-stream\r\n' +
- '\r\nThis is the first file\r\n' +
- '--foo\r\n' +
- 'Content-Type: application/octet-stream\r\n' +
- 'Content-Disposition: form-data; name="file2"; filename="file2"\r\n' +
- 'Content-Transfer-Encoding: unknown\r\n' +
- '\r\nThis is the second file\r\n' +
- '--foo--\r\n';
-
- var req = http.request({
- method: 'POST',
- port: server.address().port,
- headers: {
- 'Content-Length': body.length,
- 'Content-Type': 'multipart/form-data; boundary=foo'
- }
- });
- req.on('response', function (res) {
- assert.equal(res.statusCode, 500);
- res.on('data', function () {});
- res.on('end', function () {
- server.close();
- });
- });
- req.end(body);
-});
diff --git a/test/standalone/test-emit-order.js b/test/standalone/test-emit-order.js
deleted file mode 100644
index a20869c..0000000
--- a/test/standalone/test-emit-order.js
+++ /dev/null
@@ -1,61 +0,0 @@
-var http = require('http');
-var multiparty = require('../../');
-var assert = require('assert');
-var superagent = require('superagent');
-var path = require('path');
-var bigFile = path.join(__dirname, "..", "fixture", "file", "pf1y5.png");
-
-var server = http.createServer(function(req, res) {
- assert.strictEqual(req.url, '/upload');
- assert.strictEqual(req.method, 'POST');
-
- var fieldsInOrder = [
- 'a',
- 'b',
- 'myimage.png',
- 'c',
- ];
-
- var form = new multiparty.Form({
- autoFields: true,
- });
-
- form.on('error', function (err) {
- assert.ifError(err);
- });
-
- form.on('part', function(part) {
- assert.ok(part.filename);
- var expectedFieldName = fieldsInOrder.shift();
- assert.strictEqual(part.name, expectedFieldName);
- part.resume();
- });
-
- form.on('field', function(name, value) {
- var expectedFieldName = fieldsInOrder.shift();
- assert.strictEqual(name, expectedFieldName);
- });
-
- form.on('close', function() {
- assert.strictEqual(fieldsInOrder.length, 0);
- res.end("OK");
- });
-
- form.parse(req);
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- req.field('a', 'a-value');
- req.field('b', 'b-value');
- req.attach('myimage.png', bigFile);
- req.field('c', 'hello');
- req.on('error', function(err) {
- assert.ifError(err);
- });
- req.on('response', function(res) {
- assert.equal(res.statusCode, 200);
- server.close();
- });
- req.end();
-});
diff --git a/test/standalone/test-epilogue-last-chunk.js b/test/standalone/test-epilogue-last-chunk.js
deleted file mode 100644
index 4e7320f..0000000
--- a/test/standalone/test-epilogue-last-chunk.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var multiparty = require('../../')
- , assert = require('assert')
- , http = require('http')
- , net = require('net');
-
-var server = http.createServer(function(req, res) {
- var form = new multiparty.Form();
-
- var partCount = 0;
- form.on('part', function(part) {
- part.resume();
- partCount++;
- });
- form.on('close', function() {
- assert.strictEqual(partCount, 1);
- res.end();
- });
-
- form.parse(req);
-});
-server.listen(function() {
- var socket = net.connect(server.address().port, 'localhost', function () {
- socket.write('POST / HTTP/1.1\r\n');
- socket.write('Host: localhost\r\n');
- socket.write('Connection: close\r\n');
- socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
- socket.write('Transfer-Encoding: chunked\r\n');
- socket.write('\r\n');
- socket.write('7\r\n');
- socket.write('--foo\r\n\r\n');
- socket.write('43\r\n');
- socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n\r\n');
- socket.write('12\r\n');
- socket.write('\r\nsome text here\r\n\r\n');
- socket.write('7\r\n');
- socket.write('--foo--\r\n');
- socket.write('2\r\n');
- socket.write('\r\n\r\n');
- socket.write('0\r\n\r\n');
- socket.on('close', function () {
- server.close();
- });
- });
-});
diff --git a/test/standalone/test-error-listen-after-parse.js b/test/standalone/test-error-listen-after-parse.js
deleted file mode 100644
index 00e1469..0000000
--- a/test/standalone/test-error-listen-after-parse.js
+++ /dev/null
@@ -1,20 +0,0 @@
-var multiparty = require('../../');
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var stream = require('stream');
-
-var form = new multiparty.Form();
-var req = new stream.Readable();
-
-req.headers = {};
-req._read = function(){
- this.push(new Buffer('--foo!'));
-};
-
-form.parse(req);
-
-form.on('error', function(err){
- // verification that error emitter when attached after form.parse
- assert.ok(err);
-});
diff --git a/test/standalone/test-error-unpipe.js b/test/standalone/test-error-unpipe.js
deleted file mode 100644
index 0213f35..0000000
--- a/test/standalone/test-error-unpipe.js
+++ /dev/null
@@ -1,43 +0,0 @@
-var multiparty = require('../../');
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var Pend = require('pend');
-var stream = require('stream');
-
-var err = null;
-var form = new multiparty.Form();
-var pend = new Pend();
-var req = new stream.Readable();
-var unpiped = false;
-
-req.headers = {
- 'content-type': 'multipart/form-data; boundary=foo'
-};
-req._read = function(){
- this.push(new Buffer('--foo!'));
-};
-
-pend.go(function(){
- form.on('error', function(e){
- err = e;
- });
-});
-
-pend.go(function(){
- form.on('unpipe', function(){
- unpiped = true;
- });
-});
-
-pend.wait(function(){
- // verification that error event implies unpipe call
- assert.ok(err);
- assert.ok(unpiped, 'req was unpiped');
- assert.equal(req._readableState.flowing, false, 'req not flowing');
- assert.equal(req._readableState.pipesCount, 0, 'req has 0 pipes');
-})
-
-form.parse(req)
-assert.equal(req._readableState.flowing, true, 'req flowing');
-assert.equal(req._readableState.pipesCount, 1, 'req has 1 pipe');
diff --git a/test/standalone/test-invalid.js b/test/standalone/test-invalid.js
deleted file mode 100644
index ede541d..0000000
--- a/test/standalone/test-invalid.js
+++ /dev/null
@@ -1,35 +0,0 @@
-var superagent = require('superagent')
- , multiparty = require('../../')
- , http = require('http')
-
-var server = http.createServer(function(req, resp) {
- var form = new multiparty.Form();
-
- var errCount = 0;
- form.on('error', function(err) {
- errCount += 1;
- resp.end();
- });
- form.on('file', function(name, file) {
- });
- form.on('field', function(name, file) {
- });
-
- form.parse(req);
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/'
- var req = superagent.post(url)
- req.set('Content-Type', 'multipart/form-data; boundary=foo')
- req.write('--foo\r\n')
- req.write('Content-filename="foo.txt"\r\n')
- req.write('\r\n')
- req.write('some text here')
- req.write('Content-Disposition: form-data; name="text"; filename="bar.txt"\r\n')
- req.write('\r\n')
- req.write('some more text stuff')
- req.write('\r\n--foo--')
- req.end(function(err, resp) {
- server.close();
- });
-});
diff --git a/test/standalone/test-issue-15.js b/test/standalone/test-issue-15.js
deleted file mode 100644
index fdec5f6..0000000
--- a/test/standalone/test-issue-15.js
+++ /dev/null
@@ -1,76 +0,0 @@
-var http = require('http')
- , multiparty = require('../../')
- , assert = require('assert')
- , superagent = require('superagent')
- , path = require('path')
- , fs = require('fs')
-
-var server = http.createServer(function(req, res) {
- assert.strictEqual(req.url, '/upload');
- assert.strictEqual(req.method, 'POST');
-
- var form = new multiparty.Form({autoFields:true,autoFiles:true});
-
- form.on('error', function(err) {
- console.log(err);
- });
-
- form.on('close', function() {
- });
-
- var fileCount = 0;
- form.on('file', function(name, file) {
- fileCount += 1;
- fs.unlink(file.path, function () {});
- });
-
- form.parse(req, function(err, fields, files) {
- var objFileCount = 0;
- for (var file in files) {
- objFileCount += 1;
- }
- // multiparty does NOT try to do intelligent things based on
- // the part name.
- assert.strictEqual(fileCount, 2);
- assert.strictEqual(objFileCount, 1);
- res.end();
- });
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
- req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
-
- req.end(function(err, resp) {
- assert.ifError(err);
- resp.on('end', function() {
- server.close();
- });
- });
-
- // No space.
- createRequest('');
-
- // Single space.
- createRequest(' ');
-
- // Multiple spaces.
- createRequest(' ');
-});
-
-function createRequest(separator) {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
- req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
-
- req.end(function(err, resp) {
- assert.ifError(err);
- // We don't close the server, to allow other requests to pass.
- });
-}
-
-function fixture(name) {
- return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-issue-19.js b/test/standalone/test-issue-19.js
deleted file mode 100644
index d7da0cf..0000000
--- a/test/standalone/test-issue-19.js
+++ /dev/null
@@ -1,44 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var client;
-var server = http.createServer(function (req, res) {
- var form = new multiparty.Form({maxFields: 1});
- form.on('aborted', function () {
- throw new Error("did not expect aborted");
- });
- var first = true;
- form.on('error', function (err) {
- assert.ok(first);
- first = false;
- client.end();
- assert.ok(/maxFields/.test(err.message));
- server.close();
- });
- form.on('end', function () {
- throw new Error('Unexpected "end" event');
- });
- form.parse(req);
-});
-server.listen(function() {
- client = net.connect(server.address().port);
-
- client.write("POST /upload HTTP/1.1\r\n" +
- "Content-Length: 728\r\n" +
- "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "Content-Disposition: form-data; name=\"title\"\r\n" +
- "\r\n" +
- "foofoo" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
- "Content-Type: text/plain\r\n" +
- "\r\n" +
- "hi1\r\n" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n");
-});
diff --git a/test/standalone/test-issue-21.js b/test/standalone/test-issue-21.js
deleted file mode 100644
index ea0fddf..0000000
--- a/test/standalone/test-issue-21.js
+++ /dev/null
@@ -1,85 +0,0 @@
-var assert = require('assert');
-var fs = require('fs');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var client;
-var server = http.createServer(function(req, res) {
- var form = new multiparty.Form();
-
- form.parse(req, function(err, fields, files) {
- if (err) {
- console.error(err.stack);
- return;
- }
- var nameCount = 0;
- var name;
- for (name in fields) {
- assert.strictEqual(name, "title");
- nameCount += 1;
-
- var values = fields[name];
- assert.strictEqual(values.length, 1);
- assert.strictEqual(values[0], "foofoo");
- }
- assert.strictEqual(nameCount, 1);
-
- nameCount = 0;
- for (name in files) {
- assert.strictEqual(name, "upload");
- nameCount += 1;
-
- var filesList = files[name];
- assert.strictEqual(filesList.length, 4);
- filesList.forEach(function(file){
- assert.strictEqual(file.fieldName, "upload");
- fs.unlinkSync(file.path);
- });
- }
- assert.strictEqual(nameCount, 1);
-
- res.end();
- client.end();
- server.close();
- });
-});
-server.listen(function() {
- client = net.connect(server.address().port);
-
- client.write("POST /upload HTTP/1.1\r\n" +
- "Content-Length: 726\r\n" +
- "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "Content-Disposition: form-data; name=\"title\"\r\n" +
- "\r\n" +
- "foofoo" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
- "Content-Type: text/plain\r\n" +
- "\r\n" +
- "hi1\r\n" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "Content-Disposition: form-data; name=\"upload\"; filename=\"blah2.txt\"\r\n" +
- "Content-Type: text/plain\r\n" +
- "\r\n" +
- "hi2\r\n" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "Content-Disposition: form-data; name=\"upload\"; filename=\"blah3.txt\"\r\n" +
- "Content-Type: text/plain\r\n" +
- "\r\n" +
- "hi3\r\n" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "Content-Disposition: form-data; name=\"upload\"; filename=\"blah4.txt\"\r\n" +
- "Content-Type: text/plain\r\n" +
- "\r\n" +
- "hi4\r\n" +
- "\r\n" +
- "------WebKitFormBoundaryvfUZhxgsZDO7FXLF--\r\n"
- );
-});
diff --git a/test/standalone/test-issue-32.js b/test/standalone/test-issue-32.js
deleted file mode 100644
index 6e70c71..0000000
--- a/test/standalone/test-issue-32.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var assert = require('assert');
-var fs = require('fs');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var client;
-var server = http.createServer(function(req, res) {
- var form = new multiparty.Form();
-
- form.parse(req, function(err, fields, files) {
- if (err) {
- console.error(err.stack);
- return;
- }
- assert.strictEqual(files.image[0].originalFilename, "测试文档")
- fs.unlinkSync(files.image[0].path);
- res.end();
- client.end();
- server.close();
- });
-});
-server.listen(function() {
- client = net.connect(server.address().port);
-
- client.write(
- "POST /upload HTTP/1.1\r\n" +
- "Accept: */*\r\n" +
- "Content-Type: multipart/form-data; boundary=\"893e5556-f402-4fec-8180-c59333354c6f\"\r\n" +
- "Content-Length: 187\r\n" +
- "\r\n" +
- "--893e5556-f402-4fec-8180-c59333354c6f\r\n" +
- "Content-Disposition: form-data; name=\"image\"; filename*=utf-8''%E6%B5%8B%E8%AF%95%E6%96%87%E6%A1%A3\r\n" +
- "\r\n" +
- "\r\n" +
- "--893e5556-f402-4fec-8180-c59333354c6f--\r\n"
- );
-});
diff --git a/test/standalone/test-issue-36.js b/test/standalone/test-issue-36.js
deleted file mode 100644
index 3bacdda..0000000
--- a/test/standalone/test-issue-36.js
+++ /dev/null
@@ -1,38 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-var superagent = require('superagent');
-
-var client;
-var server = http.createServer(function(req, res) {
- var form = new multiparty.Form();
- var endCalled = false;
- form.on('part', function(part) {
- part.on('end', function() {
- endCalled = true;
- });
- part.resume();
- });
- form.on('close', function() {
- assert.ok(endCalled);
- res.end();
- });
- form.parse(req);
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/'
- var req = superagent.post(url)
- req.set('Content-Type', 'multipart/form-data; boundary=--WebKitFormBoundaryvfUZhxgsZDO7FXLF')
- req.set('Content-Length', '186')
- req.write('----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n');
- req.write('Content-Disposition: form-data; name="upload"; filename="blah1.txt"\r\n');
- req.write('Content-Type: plain/text\r\n');
- req.write('\r\n');
- req.write('hi1\r\n');
- req.write('\r\n');
- req.write('----WebKitFormBoundaryvfUZhxgsZDO7FXLF--\r\n');
- req.end(function(err, resp) {
- server.close();
- });
-});
diff --git a/test/standalone/test-issue-4.js b/test/standalone/test-issue-4.js
deleted file mode 100644
index de38125..0000000
--- a/test/standalone/test-issue-4.js
+++ /dev/null
@@ -1,53 +0,0 @@
-var http = require('http')
- , multiparty = require('../../')
- , assert = require('assert')
- , superagent = require('superagent')
- , path = require('path')
- , fs = require('fs')
-
-var server = http.createServer(function(req, res) {
- assert.strictEqual(req.url, '/upload');
- assert.strictEqual(req.method, 'POST');
-
- var form = new multiparty.Form({autoFields:true,autoFiles:true});
-
- form.on('error', function(err) {
- console.log(err);
- });
-
- form.on('close', function() {
- });
-
- var fileCount = 0;
- form.on('file', function(name, file) {
- fileCount += 1;
- fs.unlink(file.path, function () {});
- });
-
- form.parse(req, function(err, fields, files) {
- var objFileCount = 0;
- for (var file in files) {
- objFileCount += 1;
- }
- // multiparty does NOT try to do intelligent things based on
- // the part name.
- assert.strictEqual(fileCount, 2);
- assert.strictEqual(objFileCount, 1);
- res.end();
- });
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
- req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
- req.end(function(err, resp) {
- assert.ifError(err);
- resp.on('end', function() {
- server.close();
- });
- });
-});
-function fixture(name) {
- return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-max-fields.js b/test/standalone/test-max-fields.js
deleted file mode 100644
index 29f8b35..0000000
--- a/test/standalone/test-max-fields.js
+++ /dev/null
@@ -1,52 +0,0 @@
-var http = require('http')
- , multiparty = require('../../')
- , assert = require('assert')
- , superagent = require('superagent')
- , path = require('path')
- , fs = require('fs')
-
-var server = http.createServer(function(req, res) {
- assert.strictEqual(req.url, '/upload');
- assert.strictEqual(req.method, 'POST');
-
- var form = new multiparty.Form({autoFiles:true,maxFields:2});
-
- var first = true;
- form.on('error', function (err) {
- assert.ok(first);
- first = false;
- assert.ok(/maxFields/.test(err.message));
- });
-
- var fieldCount = 0;
- form.on('field', function() {
- fieldCount += 1;
- });
-
- form.parse(req, function(err, fields, files) {
- assert.ok(!first);
- assert.ok(fieldCount <= 2);
- res.statusCode = 413;
- res.end('too many fields');
- });
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- var val = new Buffer(10 * 1024);
- req.field('a', val);
- req.field('b', val);
- req.field('c', val);
- req.on('error', function(err) {
- assert.ifError(err);
- });
- req.end();
- req.on('response', function(res) {
- assert.equal(res.statusCode, 413);
- server.close();
- });
-});
-
-function fixture(name) {
- return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-max-files-size-exact.js b/test/standalone/test-max-files-size-exact.js
deleted file mode 100644
index 57892ec..0000000
--- a/test/standalone/test-max-files-size-exact.js
+++ /dev/null
@@ -1,42 +0,0 @@
-var http = require('http')
- , multiparty = require('../../')
- , assert = require('assert')
- , superagent = require('superagent')
- , path = require('path')
- , fs = require('fs')
-
-var server = http.createServer(function(req, res) {
- assert.strictEqual(req.url, '/upload');
- assert.strictEqual(req.method, 'POST');
-
- var form = new multiparty.Form({autoFiles:true,maxFilesSize:768323}); // exact size of pf1y5.png
-
- var fileCount = 0;
- form.on('file', function(name, file) {
- fileCount += 1;
- fs.unlink(file.path, function() {});
- });
-
- form.parse(req, function(err, fields, files) {
- assert.ifError(err);
- assert.ok(fileCount === 1);
- res.end('OK');
- });
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
- req.on('error', function(err) {
- assert.ifError(err);
- });
- req.end();
- req.on('response', function(res) {
- assert.equal(res.statusCode, 200);
- server.close();
- });
-});
-
-function fixture(name) {
- return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-max-files-size.js b/test/standalone/test-max-files-size.js
deleted file mode 100644
index 184f991..0000000
--- a/test/standalone/test-max-files-size.js
+++ /dev/null
@@ -1,50 +0,0 @@
-var http = require('http');
-var multiparty = require('../../');
-var assert = require('assert');
-var superagent = require('superagent');
-var path = require('path');
-var fs = require('fs');
-
-var server = http.createServer(function(req, res) {
- assert.strictEqual(req.url, '/upload');
- assert.strictEqual(req.method, 'POST');
-
- var form = new multiparty.Form({autoFiles:true,maxFilesSize:800*1024});
-
- var first = true;
- form.on('error', function (err) {
- assert.ok(first);
- first = false;
- assert.strictEqual(err.code, 'ETOOBIG');
- });
-
- var fileCount = 0;
- form.on('file', function(name, file) {
- fileCount += 1;
- fs.unlinkSync(file.path);
- });
-
- form.parse(req, function(err, fields, files) {
- assert.ok(fileCount <= 1);
- res.statusCode = 413;
- res.end('files too large');
- });
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
- req.attach('file1', fixture('pf1y5.png'), 'SOG2.JPG');
- req.on('error', function(err) {
- assert.ifError(err);
- });
- req.end();
- req.on('response', function(res) {
- assert.equal(res.statusCode, 413);
- server.close();
- });
-});
-
-function fixture(name) {
- return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-missing-boundary-end.js b/test/standalone/test-missing-boundary-end.js
deleted file mode 100644
index 3686413..0000000
--- a/test/standalone/test-missing-boundary-end.js
+++ /dev/null
@@ -1,46 +0,0 @@
-var superagent = require('superagent')
- , assert = require('assert')
- , multiparty = require('../../')
- , http = require('http')
-
-var server = http.createServer(function(req, resp) {
- var form = new multiparty.Form();
-
- var errCount = 0;
- form.on('error', function (err) {
- assert.ok(err);
- assert.equal(err.message, 'stream ended unexpectedly');
- errCount += 1;
- resp.end();
- });
- form.on('part', function (part) {
- part.resume();
- });
- form.on('close', function () {
- assert.equal(errCount, 1);
- })
-
- form.parse(req);
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/'
- var req = superagent.post(url)
- req.set('Content-Type', 'multipart/form-data; boundary=--WebKitFormBoundaryE19zNvXGzXaLvS5C')
- req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
- req.write('Content-Disposition: form-data; name="a[b]"\r\n');
- req.write('\r\n');
- req.write('3\r\n');
- req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
- req.write('Content-Disposition: form-data; name="a[c]"\r\n');
- req.write('\r\n');
- req.write('4\r\n');
- req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
- req.write('Content-Disposition: form-data; name="file"; filename="test.txt"\r\n');
- req.write('Content-Type: plain/text\r\n');
- req.write('\r\n');
- req.write('and\r\n');
- req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
- req.end(function(err, resp) {
- server.close();
- });
-});
diff --git a/test/standalone/test-parse-type-error.js b/test/standalone/test-parse-type-error.js
deleted file mode 100644
index 42437c8..0000000
--- a/test/standalone/test-parse-type-error.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var http = require('http')
- , multiparty = require('../../')
- , assert = require('assert')
- , superagent = require('superagent')
- , path = require('path');
-
-var server = http.createServer(function(req, res) {
- assert.strictEqual(req.url, '/upload');
- assert.strictEqual(req.method, 'POST');
-
- var form = new multiparty.Form();
-
- // this is invalid
- delete req.headers['content-type'];
-
- form.parse(req, function(err, fields, files) {
- assert.ok(err);
- assert.equal(err.message, 'missing content-type header');
- res.statusCode = 415;
- res.end();
- });
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
- req.on('error', function(err) {
- assert.ifError(err);
- });
- req.end();
- req.on('response', function(res) {
- assert.equal(res.statusCode, 415);
- server.close();
- });
-});
-
-function fixture(name) {
- return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-req-encoding.js b/test/standalone/test-req-encoding.js
deleted file mode 100644
index aebd935..0000000
--- a/test/standalone/test-req-encoding.js
+++ /dev/null
@@ -1,39 +0,0 @@
-var http = require('http')
- , multiparty = require('../../')
- , assert = require('assert')
- , superagent = require('superagent')
- , path = require('path');
-
-var server = http.createServer(function(req, res) {
- assert.strictEqual(req.url, '/upload');
- assert.strictEqual(req.method, 'POST');
-
- var form = new multiparty.Form();
-
- // this is invalid
- req.setEncoding('utf8');
-
- form.parse(req, function(err, fields, files) {
- assert.ok(err);
- assert.equal(err.message, 'request encoding must not be set');
- res.statusCode = 500;
- res.end();
- });
-});
-server.listen(function() {
- var url = 'http://localhost:' + server.address().port + '/upload';
- var req = superagent.post(url);
- req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
- req.on('error', function(err) {
- assert.ifError(err);
- });
- req.end();
- req.on('response', function(res) {
- assert.equal(res.statusCode, 500);
- server.close();
- });
-});
-
-function fixture(name) {
- return path.join(__dirname, '..', 'fixture', 'file', name)
-}
diff --git a/test/standalone/test-stream-error.js b/test/standalone/test-stream-error.js
deleted file mode 100644
index a9a9785..0000000
--- a/test/standalone/test-stream-error.js
+++ /dev/null
@@ -1,36 +0,0 @@
-var assert = require('assert');
-var http = require('http');
-var net = require('net');
-var multiparty = require('../../');
-
-var server = http.createServer(function (req, res) {
- var form = new multiparty.Form();
- var gotPartErr;
- form.on('part', function(part) {
- part.on('error', function(err) {
- gotPartErr = err;
- });
- part.resume();
- });
- form.on('error', function () {
- assert.ok(gotPartErr);
- server.close();
- });
- form.on('close', function () {
- throw new Error('Unexpected "close" event');
- });
- form.parse(req);
-}).listen(0, 'localhost', function () {
- var client = net.connect(server.address().port);
- client.write(
- "POST / HTTP/1.1\r\n" +
- "Content-Length: 186\r\n" +
- "Content-Type: multipart/form-data; boundary=--WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "\r\n" +
- "----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
- "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
- "Content-Type: plain/text\r\n" +
- "\r\n" +
- "hi1\r\n");
- client.end();
-});
diff --git a/test/test.js b/test/test.js
index 41ef5d6..1a7e788 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,4 +1,3 @@
-var spawn = require('child_process').spawn;
var crypto = require('crypto');
var findit = require('findit2');
var path = require('path');
@@ -7,19 +6,1249 @@ var rimraf = require('rimraf');
var fs = require('fs');
var http = require('http');
var net = require('net');
+var stream = require('stream');
var assert = require('assert');
var multiparty = require('../');
var mkdirp = require('mkdirp');
+var superagent = require('superagent');
var STANDALONE_PATH = path.join(__dirname, 'standalone');
var server = http.createServer();
var PORT = 13532;
var FIXTURE_PATH = path.join(__dirname, 'fixture');
var TMP_PATH = path.join(__dirname, 'tmp');
+var standaloneTests = [
+ {
+ name: 'chunked',
+ fn: function(cb) {
+ var server = http.createServer(function(req, resp) {
+ var form = new multiparty.Form();
+
+ var partCount = 0;
+ form.on('part', function(part) {
+ part.resume();
+ partCount++;
+ assert.strictEqual(typeof part.byteCount, 'undefined');
+ });
+ form.on('close', function() {
+ assert.strictEqual(partCount, 1);
+ resp.end();
+ });
+
+ form.parse(req);
+ });
+ server.listen(function() {
+ var socket = net.connect(server.address().port, 'localhost', function () {
+ socket.write('POST / HTTP/1.1\r\n');
+ socket.write('Host: localhost\r\n');
+ socket.write('Connection: close\r\n');
+ socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
+ socket.write('Transfer-Encoding: chunked\r\n');
+ socket.write('\r\n');
+ socket.write('7\r\n');
+ socket.write('--foo\r\n\r\n');
+ socket.write('43\r\n');
+ socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n\r\n');
+ socket.write('12\r\n');
+ socket.write('\r\nsome text here\r\n\r\n');
+ socket.write('9\r\n');
+ socket.write('--foo--\r\n\r\n');
+ socket.write('0\r\n\r\n');
+ socket.on('close', function () {
+ server.close(cb);
+ });
+ });
+ });
+ },
+ },
+ {
+ name: "connection aborted closed",
+ fn: function(cb) {
+ var socket;
+ var server = http.createServer(function (req, res) {
+ var called = false;
+ var form = new multiparty.Form();
+
+ form.parse(req, function (err, fields, files) {
+ assert.ok(!called);
+ called = true;
+
+ assert.ifError(err);
+ assert.equal(Object.keys(fields).length, 1);
+ socket.end();
+ });
+ });
+
+ server.listen(0, 'localhost', function () {
+ socket = net.connect(server.address().port, 'localhost', function () {
+ socket.write('POST / HTTP/1.1\r\n');
+ socket.write('Host: localhost\r\n');
+ socket.write('Connection: close\r\n');
+ socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
+ socket.write('Transfer-Encoding: chunked\r\n');
+ socket.write('\r\n');
+ socket.write('7\r\n');
+ socket.write('--foo\r\n\r\n');
+ socket.write('2D\r\n');
+ socket.write('Content-Disposition: form-data; name="data"\r\n\r\n');
+ socket.write('12\r\n');
+ socket.write('\r\nsome text here\r\n\r\n');
+ socket.write('7\r\n');
+ socket.write('--foo--\r\n');
+ socket.write('2\r\n');
+ socket.write('\r\n\r\n');
+ socket.write('0\r\n\r\n');
+ socket.on('close', function () {
+ server.close(cb);
+ });
+ });
+ });
+ },
+ },
+ {
+ name: "connection aborted",
+ fn: function(cb) {
+ var server = http.createServer(function (req, res) {
+ var form = new multiparty.Form();
+ var aborted_received = false;
+ form.on('aborted', function () {
+ aborted_received = true;
+ });
+ form.on('error', function () {
+ assert(aborted_received, 'Error event should follow aborted');
+ server.close(cb);
+ });
+ form.on('end', function () {
+ throw new Error('Unexpected "end" event');
+ });
+ form.on('close', function () {
+ throw new Error('Unexpected "close" event');
+ });
+ form.parse(req);
+ }).listen(0, 'localhost', function () {
+ var client = net.connect(server.address().port);
+ client.write(
+ "POST / HTTP/1.1\r\n" +
+ "Content-Length: 70\r\n" +
+ "Content-Type: multipart/form-data; boundary=foo\r\n\r\n");
+ client.end();
+ });
+ },
+ },
+ {
+ name: "content transfer encoding",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ var form = new multiparty.Form();
+ form.uploadDir = TMP_PATH;
+ form.on('close', function () {
+ throw new Error('Unexpected "close" event');
+ });
+ form.on('end', function () {
+ throw new Error('Unexpected "end" event');
+ });
+ form.on('error', function (e) {
+ res.writeHead(e.status || 500);
+ res.end(e.message);
+ });
+ form.parse(req);
+ });
+
+ server.listen(0, function() {
+ var body =
+ '--foo\r\n' +
+ 'Content-Disposition: form-data; name="file1"; filename="file1"\r\n' +
+ 'Content-Type: application/octet-stream\r\n' +
+ '\r\nThis is the first file\r\n' +
+ '--foo\r\n' +
+ 'Content-Type: application/octet-stream\r\n' +
+ 'Content-Disposition: form-data; name="file2"; filename="file2"\r\n' +
+ 'Content-Transfer-Encoding: unknown\r\n' +
+ '\r\nThis is the second file\r\n' +
+ '--foo--\r\n';
+
+ var req = http.request({
+ method: 'POST',
+ port: server.address().port,
+ headers: {
+ 'Content-Length': body.length,
+ 'Content-Type': 'multipart/form-data; boundary=foo'
+ }
+ });
+ req.on('response', function (res) {
+ assert.equal(res.statusCode, 400);
+ res.on('data', function () {});
+ res.on('end', function () {
+ server.close(cb);
+ });
+ });
+ req.end(body);
+ });
+ },
+ },
+ {
+ name: "emit order",
+ fn: function(cb) {
+ var bigFile = path.join(FIXTURE_PATH, "file", "pf1y5.png");
+
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var fieldsInOrder = [
+ 'a',
+ 'b',
+ 'myimage.png',
+ 'c',
+ ];
+
+ var form = new multiparty.Form({
+ autoFields: true,
+ });
+
+ form.on('error', function (err) {
+ assert.ifError(err);
+ });
+
+ form.on('part', function(part) {
+ assert.ok(part.filename);
+ var expectedFieldName = fieldsInOrder.shift();
+ assert.strictEqual(part.name, expectedFieldName);
+ part.resume();
+ });
+
+ form.on('field', function(name, value) {
+ var expectedFieldName = fieldsInOrder.shift();
+ assert.strictEqual(name, expectedFieldName);
+ });
+
+ form.on('close', function() {
+ assert.strictEqual(fieldsInOrder.length, 0);
+ res.end("OK");
+ });
+
+ form.parse(req);
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.field('a', 'a-value');
+ req.field('b', 'b-value');
+ req.attach('myimage.png', bigFile);
+ req.field('c', 'hello');
+ req.on('error', function(err) {
+ assert.ifError(err);
+ });
+ req.on('response', function(res) {
+ assert.equal(res.statusCode, 200);
+ server.close(cb);
+ });
+ req.end();
+ });
+ },
+ },
+ {
+ name: "epilogue last chunk",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ var form = new multiparty.Form();
+
+ var partCount = 0;
+ form.on('part', function(part) {
+ part.resume();
+ partCount++;
+ });
+ form.on('close', function() {
+ assert.strictEqual(partCount, 1);
+ res.end();
+ });
+
+ form.parse(req);
+ });
+ server.listen(function() {
+ var socket = net.connect(server.address().port, 'localhost', function () {
+ socket.write('POST / HTTP/1.1\r\n');
+ socket.write('Host: localhost\r\n');
+ socket.write('Connection: close\r\n');
+ socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
+ socket.write('Transfer-Encoding: chunked\r\n');
+ socket.write('\r\n');
+ socket.write('7\r\n');
+ socket.write('--foo\r\n\r\n');
+ socket.write('43\r\n');
+ socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n\r\n');
+ socket.write('12\r\n');
+ socket.write('\r\nsome text here\r\n\r\n');
+ socket.write('7\r\n');
+ socket.write('--foo--\r\n');
+ socket.write('2\r\n');
+ socket.write('\r\n\r\n');
+ socket.write('0\r\n\r\n');
+ socket.on('close', function () {
+ server.close(cb);
+ });
+ });
+ });
+ },
+ },
+ {
+ name: "error listen after parse",
+ fn: function(cb) {
+ var form = new multiparty.Form();
+ var req = new stream.Readable();
+
+ req.headers = {};
+ req._read = function(){
+ this.push(new Buffer('--foo!'));
+ };
+
+ form.parse(req);
+
+ form.on('error', function(err){
+ // verification that error emitter when attached after form.parse
+ assert.ok(err);
+ cb();
+ });
+ },
+ },
+ {
+ name: "error unpipe",
+ fn: function(cb) {
+ var err = null;
+ var form = new multiparty.Form();
+ var pend = new Pend();
+ var req = new stream.Readable();
+ var unpiped = false;
+
+ req.headers = {
+ 'content-type': 'multipart/form-data; boundary=foo'
+ };
+ req._read = function(){
+ this.push(new Buffer('--foo!'));
+ };
+
+ pend.go(function(cb){
+ form.on('error', function(e){
+ err = e;
+ cb();
+ });
+ });
+
+ pend.go(function(cb){
+ form.on('unpipe', function(){
+ unpiped = true;
+ cb();
+ });
+ });
+
+ pend.wait(function(){
+ // verification that error event implies unpipe call
+ assert.ok(err);
+ assert.ok(unpiped, 'req was unpiped');
+ assert.equal(req._readableState.flowing, false, 'req not flowing');
+ assert.equal(req._readableState.pipesCount, 0, 'req has 0 pipes');
+ cb();
+ })
+
+ form.parse(req)
+ assert.equal(req._readableState.flowing, true, 'req flowing');
+ assert.equal(req._readableState.pipesCount, 1, 'req has 1 pipe');
+ },
+ },
+ {
+ name: "invalid",
+ fn: function(cb) {
+ var server = http.createServer(function(req, resp) {
+ var form = new multiparty.Form();
+
+ var errCount = 0;
+ form.on('error', function(err) {
+ errCount += 1;
+ resp.end();
+ });
+ form.on('file', function(name, file) {
+ });
+ form.on('field', function(name, file) {
+ });
+
+ form.parse(req);
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/'
+ var req = superagent.post(url)
+ req.set('Content-Type', 'multipart/form-data; boundary=foo')
+ req.write('--foo\r\n')
+ req.write('Content-filename="foo.txt"\r\n')
+ req.write('\r\n')
+ req.write('some text here')
+ req.write('Content-Disposition: form-data; name="text"; filename="bar.txt"\r\n')
+ req.write('\r\n')
+ req.write('some more text stuff')
+ req.write('\r\n--foo--')
+ req.end(function(err, resp) {
+ server.close(cb);
+ });
+ });
+ },
+ },
+ {
+ name: "issue 15",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form({autoFields:true,autoFiles:true});
+
+ form.on('error', function(err) {
+ console.log(err);
+ });
+
+ form.on('close', function() {
+ });
+
+ var fileCount = 0;
+ form.on('file', function(name, file) {
+ fileCount += 1;
+ fs.unlink(file.path, function () {});
+ });
+
+ form.parse(req, function(err, fields, files) {
+ var objFileCount = 0;
+ for (var file in files) {
+ objFileCount += 1;
+ }
+ // multiparty does NOT try to do intelligent things based on
+ // the part name.
+ assert.strictEqual(fileCount, 2);
+ assert.strictEqual(objFileCount, 1);
+ res.end();
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
+ req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
+
+ req.end(function(err, resp) {
+ assert.ifError(err);
+ resp.on('end', function() {
+ server.close(cb);
+ });
+ });
+
+ // No space.
+ createRequest('');
+
+ // Single space.
+ createRequest(' ');
+
+ // Multiple spaces.
+ createRequest(' ');
+ });
+
+ function createRequest(separator) {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
+ req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
+
+ req.end(function(err, resp) {
+ assert.ifError(err);
+ // We don't close the server, to allow other requests to pass.
+ });
+ }
+
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "maxFields error",
+ fn: function(cb) {
+ var client;
+ var server = http.createServer(function (req, res) {
+ var form = new multiparty.Form({maxFields: 1});
+ form.on('aborted', function () {
+ throw new Error("did not expect aborted");
+ });
+ var first = true;
+ form.on('error', function (err) {
+ assert.ok(first);
+ first = false;
+ client.end();
+ assert.ok(/maxFields/.test(err.message));
+ assert.equal(err.status, 413);
+ server.close(cb);
+ });
+ form.on('end', function () {
+ throw new Error('Unexpected "end" event');
+ });
+ form.parse(req);
+ });
+ server.listen(function() {
+ client = net.connect(server.address().port);
+
+ client.write("POST /upload HTTP/1.1\r\n" +
+ "Content-Length: 728\r\n" +
+ "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"title\"\r\n" +
+ "\r\n" +
+ "foofoo" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "hi1\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n");
+ });
+ },
+ },
+ {
+ name: "maxFieldsSize error",
+ fn: function(cb) {
+ var client;
+ var server = http.createServer(function (req, res) {
+ var form = new multiparty.Form({maxFieldsSize: 8});
+ form.on('aborted', function () {
+ throw new Error("did not expect aborted");
+ });
+ var first = true;
+ form.on('error', function (err) {
+ assert.ok(first);
+ first = false;
+ client.end();
+ assert.ok(/maxFieldsSize/.test(err.message));
+ assert.equal(err.status, 413);
+ server.close(cb);
+ });
+ form.on('end', function () {
+ throw new Error('Unexpected "end" event');
+ });
+ form.on('field', function () {});
+ form.parse(req);
+ });
+ server.listen(function() {
+ client = net.connect(server.address().port);
+
+ client.write("POST /upload HTTP/1.1\r\n" +
+ "Content-Length: 678\r\n" +
+ "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"title\"\r\n" +
+ "\r\n" +
+ "foofoo" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"text\"\r\n" +
+ "\r\n" +
+ "hi1\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n");
+ });
+ },
+ },
+ {
+ name: "issue 21",
+ fn: function(cb) {
+ var client;
+ var server = http.createServer(function(req, res) {
+ var form = new multiparty.Form();
+
+ form.parse(req, function(err, fields, files) {
+ if (err) {
+ console.error(err.stack);
+ return;
+ }
+ var nameCount = 0;
+ var name;
+ for (name in fields) {
+ assert.strictEqual(name, "title");
+ nameCount += 1;
+
+ var values = fields[name];
+ assert.strictEqual(values.length, 1);
+ assert.strictEqual(values[0], "foofoo");
+ }
+ assert.strictEqual(nameCount, 1);
+
+ nameCount = 0;
+ for (name in files) {
+ assert.strictEqual(name, "upload");
+ nameCount += 1;
+
+ var filesList = files[name];
+ assert.strictEqual(filesList.length, 4);
+ filesList.forEach(assertAndUnlink);
+ }
+
+ assert.strictEqual(nameCount, 1);
+
+ res.end();
+ client.end();
+ server.close(cb);
+
+ function assertAndUnlink(file){
+ assert.strictEqual(file.fieldName, "upload");
+ fs.unlinkSync(file.path);
+ }
+ });
+ });
+ server.listen(function() {
+ client = net.connect(server.address().port);
+
+ client.write("POST /upload HTTP/1.1\r\n" +
+ "Content-Length: 726\r\n" +
+ "Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"title\"\r\n" +
+ "\r\n" +
+ "foofoo" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "hi1\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"upload\"; filename=\"blah2.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "hi2\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"upload\"; filename=\"blah3.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "hi3\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"upload\"; filename=\"blah4.txt\"\r\n" +
+ "Content-Type: text/plain\r\n" +
+ "\r\n" +
+ "hi4\r\n" +
+ "\r\n" +
+ "------WebKitFormBoundaryvfUZhxgsZDO7FXLF--\r\n"
+ );
+ });
+ },
+ },
+ {
+ name: "issue 32",
+ fn: function(cb) {
+ var client;
+ var server = http.createServer(function(req, res) {
+ var form = new multiparty.Form();
+
+ form.parse(req, function(err, fields, files) {
+ if (err) {
+ console.error(err.stack);
+ return;
+ }
+ assert.strictEqual(files.image[0].originalFilename, "测试文档")
+ fs.unlinkSync(files.image[0].path);
+ res.end();
+ client.end();
+ server.close(cb);
+ });
+ });
+ server.listen(function() {
+ client = net.connect(server.address().port);
+
+ client.write(
+ "POST /upload HTTP/1.1\r\n" +
+ "Accept: */*\r\n" +
+ "Content-Type: multipart/form-data; boundary=\"893e5556-f402-4fec-8180-c59333354c6f\"\r\n" +
+ "Content-Length: 187\r\n" +
+ "\r\n" +
+ "--893e5556-f402-4fec-8180-c59333354c6f\r\n" +
+ "Content-Disposition: form-data; name=\"image\"; filename*=utf-8''%E6%B5%8B%E8%AF%95%E6%96%87%E6%A1%A3\r\n" +
+ "\r\n" +
+ "\r\n" +
+ "--893e5556-f402-4fec-8180-c59333354c6f--\r\n"
+ );
+ });
+ },
+ },
+ {
+ name: "issue 36",
+ fn: function(cb) {
+ var client;
+ var server = http.createServer(function(req, res) {
+ var form = new multiparty.Form();
+ var endCalled = false;
+ form.on('part', function(part) {
+ part.on('end', function() {
+ endCalled = true;
+ });
+ part.resume();
+ });
+ form.on('close', function() {
+ assert.ok(endCalled);
+ res.end();
+ });
+ form.parse(req);
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/'
+ var req = superagent.post(url)
+ req.set('Content-Type', 'multipart/form-data; boundary=--WebKitFormBoundaryvfUZhxgsZDO7FXLF')
+ req.set('Content-Length', '186')
+ req.write('----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n');
+ req.write('Content-Disposition: form-data; name="upload"; filename="blah1.txt"\r\n');
+ req.write('Content-Type: plain/text\r\n');
+ req.write('\r\n');
+ req.write('hi1\r\n');
+ req.write('\r\n');
+ req.write('----WebKitFormBoundaryvfUZhxgsZDO7FXLF--\r\n');
+ req.end(function(err, resp) {
+ server.close(cb);
+ });
+ });
+ },
+ },
+ {
+ name: "issue 4",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form({autoFields:true,autoFiles:true});
+
+ form.on('error', function(err) {
+ console.log(err);
+ });
+
+ form.on('close', function() {
+ });
+
+ var fileCount = 0;
+ form.on('file', function(name, file) {
+ fileCount += 1;
+ fs.unlink(file.path, function () {});
+ });
+
+ form.parse(req, function(err, fields, files) {
+ var objFileCount = 0;
+ for (var file in files) {
+ objFileCount += 1;
+ }
+ // multiparty does NOT try to do intelligent things based on
+ // the part name.
+ assert.strictEqual(fileCount, 2);
+ assert.strictEqual(objFileCount, 1);
+ res.end();
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.attach('files[]', fixture('pf1y5.png'), 'SOG2.JPG');
+ req.attach('files[]', fixture('binaryfile.tar.gz'), 'BenF364_LIB353.zip');
+ req.end(function(err, resp) {
+ assert.ifError(err);
+ resp.on('end', function() {
+ server.close(cb);
+ });
+ });
+ });
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "max fields",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form({autoFiles:true,maxFields:2});
+
+ var first = true;
+ form.on('error', function (err) {
+ assert.ok(first);
+ first = false;
+ assert.ok(/maxFields/.test(err.message));
+ assert.equal(err.status, 413);
+ });
+
+ var fieldCount = 0;
+ form.on('field', function() {
+ fieldCount += 1;
+ });
+
+ form.parse(req, function(err, fields, files) {
+ assert.ok(!first);
+ assert.ok(fieldCount <= 2);
+ res.statusCode = 413;
+ res.end('too many fields');
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ var val = new Buffer(10 * 1024);
+ req.field('a', val);
+ req.field('b', val);
+ req.field('c', val);
+ req.on('error', function(err) {
+ assert.ifError(err);
+ });
+ req.end();
+ req.on('response', function(res) {
+ assert.equal(res.statusCode, 413);
+ server.close(cb);
+ });
+ });
+
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "max files size exact",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form({autoFiles:true,maxFilesSize:768323}); // exact size of pf1y5.png
+
+ var fileCount = 0;
+ form.on('file', function(name, file) {
+ fileCount += 1;
+ fs.unlink(file.path, function() {});
+ });
+
+ form.parse(req, function(err, fields, files) {
+ assert.ifError(err);
+ assert.ok(fileCount === 1);
+ res.end('OK');
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
+ req.on('error', function(err) {
+ assert.ifError(err);
+ });
+ req.end();
+ req.on('response', function(res) {
+ assert.equal(res.statusCode, 200);
+ server.close(cb);
+ });
+ });
+
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "max files size",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form({autoFiles:true,maxFilesSize:800*1024});
+
+ var first = true;
+ form.on('error', function (err) {
+ assert.ok(first);
+ first = false;
+ assert.strictEqual(err.code, 'ETOOBIG');
+ assert.strictEqual(err.status, 413);
+ });
+
+ var fileCount = 0;
+ form.on('file', function(name, file) {
+ fileCount += 1;
+ fs.unlinkSync(file.path);
+ });
+
+ form.parse(req, function(err, fields, files) {
+ assert.ok(fileCount <= 1);
+ res.statusCode = 413;
+ res.end('files too large');
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
+ req.attach('file1', fixture('pf1y5.png'), 'SOG2.JPG');
+ req.on('error', function(err) {
+ assert.ifError(err);
+ });
+ req.end();
+ req.on('response', function(res) {
+ assert.equal(res.statusCode, 413);
+ server.close(cb);
+ });
+ });
+
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "missing boundary end",
+ fn: function(cb) {
+ var server = http.createServer(function(req, resp) {
+ var form = new multiparty.Form();
+
+ var errCount = 0;
+ form.on('error', function (err) {
+ assert.ok(err);
+ assert.equal(err.message, 'stream ended unexpectedly');
+ assert.equal(err.status, 400);
+ errCount += 1;
+ resp.end();
+ });
+ form.on('part', function (part) {
+ part.resume();
+ });
+ form.on('close', function () {
+ assert.equal(errCount, 1);
+ })
+
+ form.parse(req);
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/'
+ var req = superagent.post(url)
+ req.set('Content-Type', 'multipart/form-data; boundary=--WebKitFormBoundaryE19zNvXGzXaLvS5C')
+ req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
+ req.write('Content-Disposition: form-data; name="a[b]"\r\n');
+ req.write('\r\n');
+ req.write('3\r\n');
+ req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
+ req.write('Content-Disposition: form-data; name="a[c]"\r\n');
+ req.write('\r\n');
+ req.write('4\r\n');
+ req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
+ req.write('Content-Disposition: form-data; name="file"; filename="test.txt"\r\n');
+ req.write('Content-Type: plain/text\r\n');
+ req.write('\r\n');
+ req.write('and\r\n');
+ req.write('----WebKitFormBoundaryE19zNvXGzXaLvS5C\r\n');
+ req.end(function(err, resp) {
+ server.close(cb);
+ });
+ });
+ },
+ },
+ {
+ name: "missing content-type error",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form();
+
+ form.parse(req, function(err, fields, files) {
+ assert.ok(err);
+ assert.equal(err.message, 'missing content-type header');
+ assert.equal(err.status, 415);
+ res.statusCode = 415;
+ res.end();
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.on('error', function(err) {
+ assert.ifError(err);
+ });
+ req.end();
+ req.on('response', function(res) {
+ assert.equal(res.statusCode, 415);
+ server.close(cb);
+ });
+ });
+
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "unsupported content-type error",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form();
+
+ form.parse(req, function(err, fields, files) {
+ assert.ok(err);
+ assert.equal(err.message, 'unsupported content-type');
+ assert.equal(err.status, 415);
+ res.statusCode = 415;
+ res.end();
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.set('Content-Type', 'application/json');
+ req.write('{}');
+ req.on('error', function(err) {
+ assert.ifError(err);
+ });
+ req.end();
+ req.on('response', function(res) {
+ assert.equal(res.statusCode, 415);
+ server.close(cb);
+ });
+ });
+
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "content-type missing boundary error",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form();
+
+ form.parse(req, function(err, fields, files) {
+ assert.ok(err);
+ assert.equal(err.message, 'content-type missing boundary');
+ assert.equal(err.status, 400);
+ res.statusCode = 400;
+ res.end();
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
+ req.on('error', function(err) {
+ assert.ifError(err);
+ });
+ req.end();
+ req.set('Content-Type', 'multipart/form-data');
+ req.on('response', function(res) {
+ assert.equal(res.statusCode, 400);
+ server.close(cb);
+ });
+ });
+
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "empty header field error",
+ fn: function(cb) {
+ var server = http.createServer(function(req, resp) {
+ var form = new multiparty.Form();
+
+ var partCount = 0;
+ form.on('part', function(part) {
+ part.resume();
+ partCount++;
+ assert.strictEqual(typeof part.byteCount, 'undefined');
+ });
+ form.on('error', function(err) {
+ assert.ok(err);
+ assert.equal(err.message, 'Empty header field');
+ assert.equal(err.statusCode, 400);
+ server.close(cb);
+ });
+ form.on('close', function() {
+ throw new Error('Unexpected "close" event');
+ });
+
+ form.parse(req);
+ });
+ server.listen(function() {
+ var socket = net.connect(server.address().port, 'localhost', function () {
+ socket.write('POST / HTTP/1.1\r\n');
+ socket.write('Host: localhost\r\n');
+ socket.write('Connection: close\r\n');
+ socket.write('Content-Type: multipart/form-data; boundary=foo\r\n');
+ socket.write('Transfer-Encoding: chunked\r\n');
+ socket.write('\r\n');
+ socket.write('7\r\n');
+ socket.write('--foo\r\n\r\n');
+ socket.write('46\r\n');
+ socket.write('Content-Disposition: form-data; name="file"; filename="plain.txt"\r\n:\r\n\r\n');
+ socket.write('12\r\n');
+ socket.write('\r\nsome text here\r\n\r\n');
+ socket.write('9\r\n');
+ socket.write('--foo--\r\n\r\n');
+ socket.write('0\r\n\r\n');
+ socket.end();
+ });
+ });
+ },
+ },
+ {
+ name: "request encoding",
+ fn: function(cb) {
+ var server = http.createServer(function(req, res) {
+ assert.strictEqual(req.url, '/upload');
+ assert.strictEqual(req.method, 'POST');
+
+ var form = new multiparty.Form();
+
+ // this is invalid
+ req.setEncoding('utf8');
+
+ form.parse(req, function(err, fields, files) {
+ assert.ok(err);
+ assert.equal(err.message, 'request encoding must not be set');
+ res.statusCode = 500;
+ res.end();
+ });
+ });
+ server.listen(function() {
+ var url = 'http://localhost:' + server.address().port + '/upload';
+ var req = superagent.post(url);
+ req.attach('file0', fixture('pf1y5.png'), 'SOG1.JPG');
+ req.on('error', function(err) {
+ assert.ifError(err);
+ });
+ req.end();
+ req.on('response', function(res) {
+ assert.equal(res.statusCode, 500);
+ server.close(cb);
+ });
+ });
+
+ function fixture(name) {
+ return path.join(FIXTURE_PATH, 'file', name)
+ }
+ },
+ },
+ {
+ name: "stream error",
+ fn: function(cb) {
+ var server = http.createServer(function (req, res) {
+ var form = new multiparty.Form();
+ var gotPartErr;
+ form.on('part', function(part) {
+ part.on('error', function(err) {
+ gotPartErr = err;
+ });
+ part.resume();
+ });
+ form.on('error', function () {
+ assert.ok(gotPartErr);
+ server.close(cb);
+ });
+ form.on('close', function () {
+ throw new Error('Unexpected "close" event');
+ });
+ form.parse(req);
+ }).listen(0, 'localhost', function () {
+ var client = net.connect(server.address().port);
+ client.write(
+ "POST / HTTP/1.1\r\n" +
+ "Content-Length: 186\r\n" +
+ "Content-Type: multipart/form-data; boundary=--WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "\r\n" +
+ "----WebKitFormBoundaryvfUZhxgsZDO7FXLF\r\n" +
+ "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
+ "Content-Type: plain/text\r\n" +
+ "\r\n" +
+ "hi1\r\n");
+ client.end();
+ });
+ },
+ },
+ {
+ name: "queued part error",
+ fn: function(cb) {
+ var server = http.createServer(function (req, res) {
+ var form = new multiparty.Form();
+ var pend = new Pend();
+
+ pend.go(function(cb){
+ form.on('part', function(part){
+ part.on('error', function(err){
+ assert.ok(err);
+ assert.equal(err.message, 'stream ended unexpectedly');
+ cb();
+ });
+ part.resume();
+ });
+ });
+
+ pend.go(function(cb){
+ form.on('field', function(){
+ cb();
+ });
+ });
+
+ pend.go(function(cb){
+ form.on('error', function(err){
+ assert.ok(err);
+ assert.equal(err.message, 'stream ended unexpectedly');
+ cb();
+ });
+ });
+
+ pend.wait(function(){
+ server.close(cb);
+ });
+
+ form.on('close', function () {
+ throw new Error('Unexpected "close" event');
+ });
+
+ form.parse(req);
+ }).listen(0, 'localhost', function () {
+ var client = net.connect(server.address().port);
+ client.end(
+ "POST / HTTP/1.1\r\n" +
+ "Content-Length: 174\r\n" +
+ "Content-Type: multipart/form-data; boundary=--bounds\r\n" +
+ "\r\n" +
+ "----bounds\r\n" +
+ "Content-Disposition: form-data; name=\"key\"\r\n" +
+ "\r\n" +
+ "hi\r\n" +
+ "----bounds\r\n" +
+ "Content-Disposition: form-data; name=\"upload\"; filename=\"blah1.txt\"\r\n" +
+ "Content-Type: plain/text\r\n" +
+ "\r\n" +
+ "bye");
+ });
+ },
+ },
+];
+
resetTempDir(startFixtureTests);
function startFixtureTests() {
- console.log("Fixture tests:");
+ console.error("Fixture tests:");
var walker = findit(path.join(FIXTURE_PATH, 'js'));
var pend = new Pend();
pend.max = 1;
@@ -44,43 +1273,26 @@ function startFixtureTests() {
}
function startStandaloneTests() {
- console.log("\nStandalone tests:");
- var walker = findit(STANDALONE_PATH);
+ console.error("\nStandalone tests:");
var pend = new Pend();
pend.max = 1;
- walker.on('file', function(jsPath) {
- if (!/\.js$/.test(jsPath)) return;
+ standaloneTests.forEach(function(test) {
pend.go(function(cb) {
- var name = path.basename(jsPath, '.js');
- process.stdout.write(name + "...");
- var child = spawn(process.execPath, [jsPath], { env: { TMPDIR: TMP_PATH }, stdio: 'inherit' });
- child.on('error', function(err) {
- throw err;
- });
- child.on('exit', function(code) {
- if (code) throw new Error("exited with code " + code);
- var tmpWalker = findit(TMP_PATH);
- var fileNames = [];
- tmpWalker.on('file', function(file) {
- fileNames.push(file);
- });
- tmpWalker.on('end', function() {
- if (fileNames.length) {
- cleanFiles(fileNames);
- throw new Error("failed to clean up auto files: " + fileNames.join(', '));
- } else {
- console.log("OK");
- cb();
- }
- });
+ process.stderr.write(test.name + "...");
+ var timeoutRef = setTimeout(timeout, 2000);
+ test.fn(function(err) {
+ clearTimeout(timeoutRef);
+ if (err) throw err;
+ process.stderr.write("OK\n");
+ cb();
});
+ function timeout() {
+ throw new Error("timeout");
+ }
});
});
- walker.on('end', function() {
- pend.wait(function(err) {
- if (err) throw err;
- console.log("\nAll tests passed.");
- });
+ pend.wait(function() {
+ console.error("\nAll tests passed.");
});
}
@@ -107,12 +1319,6 @@ function createFixtureTest(name, fixture) {
};
}
-function cleanFiles(fileNames) {
- fileNames.forEach(function(fileName) {
- fs.unlinkSync(fileName);
- });
-}
-
function resetTempDir(cb) {
rimraf(TMP_PATH, function(err) {
if (err) throw err;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-multiparty.git
More information about the Pkg-javascript-commits
mailing list