vulcan 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/vulcan/cli.rb +3 -0
- data/lib/vulcan/version.rb +1 -1
- data/server/lib/spawner.js +9 -4
- data/server/node_modules/cradle/lib/cradle.js +0 -1
- data/server/node_modules/cradle/package.json +3 -3
- data/server/node_modules/cradle/test/cache-test.js +6 -7
- data/server/node_modules/cradle/test/cradle-test.js +4 -5
- data/server/node_modules/cradle/test/response-test.js +5 -6
- data/server/node_modules/express/History.md +40 -0
- data/server/node_modules/express/Makefile +3 -9
- data/server/node_modules/express/Readme.md +3 -1
- data/server/node_modules/express/bin/express +61 -63
- data/server/node_modules/express/lib/express.js +1 -1
- data/server/node_modules/express/lib/request.js +9 -7
- data/server/node_modules/express/lib/view.js +19 -16
- data/server/node_modules/express/node_modules/connect/lib/connect.js +1 -1
- data/server/node_modules/express/node_modules/connect/lib/http.js +2 -0
- data/server/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js +135 -31
- data/server/node_modules/express/node_modules/connect/lib/middleware/limit.js +5 -1
- data/server/node_modules/express/node_modules/connect/lib/middleware/session.js +2 -2
- data/server/node_modules/express/node_modules/connect/lib/middleware/static.js +26 -21
- data/server/node_modules/express/node_modules/connect/lib/middleware/staticCache.js +91 -38
- data/server/node_modules/express/node_modules/connect/lib/middleware/vhost.js +1 -1
- data/server/node_modules/express/node_modules/connect/lib/utils.js +11 -4
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/Makefile +14 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md +286 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/TODO +3 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js +70 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js +43 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js +48 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/index.js +1 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js +61 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js +377 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js +3 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js +312 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js +25 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js +6 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/package.json +22 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js +19 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt +1 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt +1 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http +13 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md +3 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +26 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http +24 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +23 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +24 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +22 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +22 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +22 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js +3 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js +21 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multi_video.upload +0 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js +72 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js +89 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js +24 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js +80 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js +104 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js +715 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js +50 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js +45 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js +72 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js +2 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js +63 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js +47 -0
- data/server/node_modules/express/node_modules/connect/package.json +7 -6
- data/server/node_modules/express/node_modules/connect/test.js +44 -31
- data/server/node_modules/express/node_modules/qs/History.md +11 -0
- data/server/node_modules/express/node_modules/qs/Makefile +1 -3
- data/server/node_modules/express/node_modules/qs/Readme.md +2 -4
- data/server/node_modules/express/node_modules/qs/lib/querystring.js +100 -74
- data/server/node_modules/express/node_modules/qs/package.json +9 -2
- data/server/node_modules/express/node_modules/qs/test/mocha.opts +2 -0
- data/server/node_modules/express/node_modules/qs/test/{parse.test.js → parse.js} +1 -2
- data/server/node_modules/express/node_modules/qs/test/{stringify.test.js → stringify.js} +0 -0
- data/server/node_modules/express/package.json +7 -7
- data/server/node_modules/express/testing/foo/app.js +35 -0
- data/server/node_modules/express/testing/foo/package.json +9 -0
- data/server/node_modules/express/testing/foo/public/stylesheets/style.css +8 -0
- data/server/node_modules/express/testing/foo/routes/index.js +10 -0
- data/server/node_modules/express/testing/foo/views/index.jade +2 -0
- data/server/node_modules/express/testing/foo/views/layout.jade +6 -0
- data/server/node_modules/express/testing/index.js +31 -5
- data/server/node_modules/express/testing/public/test.txt +2971 -0
- data/server/node_modules/express/testing/views/page.html +1 -0
- data/server/node_modules/express/testing/views/page.jade +3 -0
- data/server/node_modules/express/testing/views/test.md +1 -0
- data/server/node_modules/express/testing/views/user/index.jade +1 -0
- data/server/node_modules/express/testing/views/user/list.jade +1 -0
- data/server/node_modules/node-uuid/README.md +166 -67
- data/server/node_modules/node-uuid/benchmark/README.md +53 -0
- data/server/node_modules/node-uuid/benchmark/bench.gnu +174 -0
- data/server/node_modules/node-uuid/benchmark/bench.sh +34 -0
- data/server/node_modules/node-uuid/{test → benchmark}/benchmark-native.c +0 -0
- data/server/node_modules/node-uuid/benchmark/benchmark.js +84 -0
- data/server/node_modules/node-uuid/package.json +5 -3
- data/server/node_modules/node-uuid/test/benchmark-native +0 -0
- data/server/node_modules/node-uuid/test/compare_v1.js +63 -0
- data/server/node_modules/node-uuid/test/test.html +3 -0
- data/server/node_modules/node-uuid/test/test.js +214 -57
- data/server/node_modules/node-uuid/uuid.js +225 -56
- data/server/node_modules/restler/README.md +20 -7
- data/server/node_modules/restler/bin/restler +1 -1
- data/server/node_modules/restler/lib/multipartform.js +9 -8
- data/server/node_modules/restler/lib/restler.js +64 -22
- data/server/node_modules/restler/package.json +2 -2
- data/server/node_modules/restler/test/restler.js +22 -2
- data/server/node_modules/restler/test/test_helper.js +20 -1
- data/server/package.json +8 -8
- data/server/web.js +22 -6
- metadata +72 -82
- data/server/node_modules/cradle/node_modules/vows/LICENSE +0 -20
- data/server/node_modules/cradle/node_modules/vows/Makefile +0 -7
- data/server/node_modules/cradle/node_modules/vows/README.md +0 -39
- data/server/node_modules/cradle/node_modules/vows/bin/vows +0 -515
- data/server/node_modules/cradle/node_modules/vows/lib/assert/error.js +0 -27
- data/server/node_modules/cradle/node_modules/vows/lib/assert/macros.js +0 -215
- data/server/node_modules/cradle/node_modules/vows/lib/assert/utils.js +0 -77
- data/server/node_modules/cradle/node_modules/vows/lib/vows.js +0 -193
- data/server/node_modules/cradle/node_modules/vows/lib/vows/console.js +0 -131
- data/server/node_modules/cradle/node_modules/vows/lib/vows/context.js +0 -55
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/file.js +0 -29
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-foot.html +0 -2
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-head.html +0 -61
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-html.js +0 -54
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-json.js +0 -54
- data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-plain.js +0 -38
- data/server/node_modules/cradle/node_modules/vows/lib/vows/extras.js +0 -28
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/dot-matrix.js +0 -67
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/json.js +0 -16
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/silent.js +0 -8
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/spec.js +0 -44
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/watch.js +0 -39
- data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/xunit.js +0 -90
- data/server/node_modules/cradle/node_modules/vows/lib/vows/suite.js +0 -319
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/LICENSE +0 -20
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/Makefile +0 -4
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/README.md +0 -72
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/lib/eyes.js +0 -233
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/package.json +0 -14
- data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/test/eyes-test.js +0 -55
- data/server/node_modules/cradle/node_modules/vows/package.json +0 -14
- data/server/node_modules/cradle/node_modules/vows/test/assert-test.js +0 -135
- data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/failing.js +0 -18
- data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/log.js +0 -18
- data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/passing.js +0 -17
- data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/stderr.js +0 -18
- data/server/node_modules/cradle/node_modules/vows/test/isolate-test.js +0 -140
- data/server/node_modules/cradle/node_modules/vows/test/testInherit.js +0 -133
- data/server/node_modules/cradle/node_modules/vows/test/vows-error-test.js +0 -51
- data/server/node_modules/cradle/node_modules/vows/test/vows-test.js +0 -374
- data/server/node_modules/express/node_modules/qs/support/expresso/History.md +0 -128
- data/server/node_modules/express/node_modules/qs/support/expresso/Makefile +0 -53
- data/server/node_modules/express/node_modules/qs/support/expresso/Readme.md +0 -61
- data/server/node_modules/express/node_modules/qs/support/expresso/bin/expresso +0 -856
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/api.html +0 -1080
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.html +0 -377
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.md +0 -290
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/foot.html +0 -3
- data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/head.html +0 -42
- data/server/node_modules/express/node_modules/qs/support/expresso/lib/bar.js +0 -4
- data/server/node_modules/express/node_modules/qs/support/expresso/lib/foo.js +0 -16
- data/server/node_modules/express/node_modules/qs/support/expresso/package.json +0 -12
- data/server/node_modules/express/node_modules/qs/support/expresso/test/assert.test.js +0 -91
- data/server/node_modules/express/node_modules/qs/support/expresso/test/async.test.js +0 -12
- data/server/node_modules/express/node_modules/qs/support/expresso/test/bar.test.js +0 -13
- data/server/node_modules/express/node_modules/qs/support/expresso/test/foo.test.js +0 -14
- data/server/node_modules/express/node_modules/qs/support/expresso/test/http.test.js +0 -146
- data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/async.test.js +0 -39
- data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/http.test.js +0 -48
- data/server/node_modules/express/node_modules/qs/support/should/History.md +0 -22
- data/server/node_modules/express/node_modules/qs/support/should/Makefile +0 -6
- data/server/node_modules/express/node_modules/qs/support/should/Readme.md +0 -248
- data/server/node_modules/express/node_modules/qs/support/should/examples/runner.js +0 -53
- data/server/node_modules/express/node_modules/qs/support/should/index.js +0 -2
- data/server/node_modules/express/node_modules/qs/support/should/lib/eql.js +0 -91
- data/server/node_modules/express/node_modules/qs/support/should/lib/should.js +0 -548
- data/server/node_modules/express/node_modules/qs/support/should/package.json +0 -8
- data/server/node_modules/express/node_modules/qs/support/should/test/should.test.js +0 -358
- data/server/node_modules/express/testing/views/users.jade +0 -1
- data/server/node_modules/node-uuid/test/benchmark.js +0 -27
@@ -10,6 +10,7 @@
|
|
10
10
|
*/
|
11
11
|
|
12
12
|
var http = require('http')
|
13
|
+
, utils = require('../utils')
|
13
14
|
, Cache = require('../cache')
|
14
15
|
, url = require('url')
|
15
16
|
, fs = require('fs');
|
@@ -33,17 +34,15 @@ var http = require('http')
|
|
33
34
|
*
|
34
35
|
* Benchmarks:
|
35
36
|
*
|
36
|
-
*
|
37
|
-
*
|
38
|
-
*
|
37
|
+
* static(): 2700 rps
|
38
|
+
* node-static: 5300 rps
|
39
|
+
* static() + staticCache(): 7500 rps
|
39
40
|
*
|
40
41
|
* Options:
|
41
42
|
*
|
42
43
|
* - `maxObjects` max cache objects [128]
|
43
44
|
* - `maxLength` max cache object length 256kb
|
44
45
|
*
|
45
|
-
* TODO: refactore to accept data stores (redis etc)
|
46
|
-
*
|
47
46
|
* @param {Type} name
|
48
47
|
* @return {Type}
|
49
48
|
* @api public
|
@@ -56,16 +55,82 @@ module.exports = function staticCache(options){
|
|
56
55
|
|
57
56
|
return function staticCache(req, res, next){
|
58
57
|
var path = url.parse(req.url).pathname
|
58
|
+
, ranges = req.headers.range
|
59
59
|
, hit = cache.get(path)
|
60
|
-
,
|
61
|
-
,
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
60
|
+
, hitCC
|
61
|
+
, uaCC
|
62
|
+
, header
|
63
|
+
, age;
|
64
|
+
|
65
|
+
// cache static
|
66
|
+
req.on('static', function(stream){
|
67
|
+
var headers = res._headers
|
68
|
+
, cc = utils.parseCacheControl(headers['cache-control'] || '')
|
69
|
+
, contentLength = headers['content-length']
|
70
|
+
, hit;
|
71
|
+
|
72
|
+
// ignore larger files
|
73
|
+
if (!contentLength || contentLength > maxlen) return;
|
74
|
+
|
75
|
+
// dont cache items we shouldn't be
|
76
|
+
if ( cc['no-cache']
|
77
|
+
|| cc['no-store']
|
78
|
+
|| cc['private']
|
79
|
+
|| cc['must-revalidate']) return;
|
80
|
+
|
81
|
+
// if already in cache then validate
|
82
|
+
if (hit = cache.get(path)){
|
83
|
+
if (headers.etag == hit[0].etag) {
|
84
|
+
hit[0].date = new Date;
|
85
|
+
return;
|
86
|
+
} else {
|
87
|
+
cache.remove(path);
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
// validation notifiactions don't contain a steam
|
92
|
+
if (null == stream) return;
|
93
|
+
|
94
|
+
// add the cache object
|
95
|
+
var arr = cache.add(path);
|
96
|
+
arr.push(headers);
|
97
|
+
|
98
|
+
// store the chunks
|
99
|
+
stream.on('data', function(chunk){
|
100
|
+
arr.push(chunk);
|
101
|
+
});
|
102
|
+
|
103
|
+
// flag it as complete
|
104
|
+
stream.on('end', function(){
|
105
|
+
arr.complete = true;
|
106
|
+
});
|
107
|
+
});
|
108
|
+
|
109
|
+
// cache hit, doesnt support range requests
|
110
|
+
if (hit && hit.complete && !ranges) {
|
111
|
+
header = utils.merge({}, hit[0]);
|
112
|
+
header.Age = age = (new Date - new Date(header.date)) / 1000 | 0;
|
113
|
+
header.date = new Date().toUTCString();
|
114
|
+
|
115
|
+
// parse cache-controls
|
116
|
+
hitCC = utils.parseCacheControl(header['cache-control'] || '');
|
117
|
+
uaCC = utils.parseCacheControl(req.headers['cache-control'] || '');
|
118
|
+
|
119
|
+
// check if we must revalidate(bypass)
|
120
|
+
if (hitCC['no-cache'] || uaCC['no-cache']) return next();
|
121
|
+
|
122
|
+
// check freshness of entity
|
123
|
+
if (isStale(hitCC, age) || isStale(uaCC, age)) return next();
|
124
|
+
|
125
|
+
// conditional GET support
|
126
|
+
if (utils.conditionalGET(req)) {
|
127
|
+
if (!utils.modified(req, res, header)) {
|
128
|
+
header['content-length'] = 0;
|
129
|
+
res.writeHead(304, header);
|
130
|
+
return res.end();
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
69
134
|
// HEAD support
|
70
135
|
if ('HEAD' == req.method) {
|
71
136
|
header['content-length'] = 0;
|
@@ -92,31 +157,19 @@ module.exports = function staticCache(options){
|
|
92
157
|
return write(1);
|
93
158
|
}
|
94
159
|
|
95
|
-
// cache static
|
96
|
-
req.on('static', function(stream){
|
97
|
-
// ignore larger files
|
98
|
-
var contentLength = res._headers['content-length'];
|
99
|
-
if (!contentLength || contentLength > maxlen) return;
|
100
|
-
|
101
|
-
// exists
|
102
|
-
if (cache.get(path)) return;
|
103
|
-
|
104
|
-
// add the cache object
|
105
|
-
var arr = cache.add(path);
|
106
|
-
arr.push(res._headers);
|
107
|
-
|
108
|
-
// store the chunks
|
109
|
-
stream.on('data', function(chunk){
|
110
|
-
arr.push(chunk);
|
111
|
-
});
|
112
|
-
|
113
|
-
// flag it as complete
|
114
|
-
stream.on('end', function(){
|
115
|
-
arr.complete = true;
|
116
|
-
});
|
117
|
-
});
|
118
|
-
|
119
160
|
next();
|
120
161
|
}
|
121
162
|
};
|
122
163
|
|
164
|
+
/**
|
165
|
+
* Check if cache item is stale
|
166
|
+
*
|
167
|
+
* @param {Object} cc
|
168
|
+
* @param {Number} age
|
169
|
+
* @return {Boolean}
|
170
|
+
* @api private
|
171
|
+
*/
|
172
|
+
|
173
|
+
function isStale(cc, age) {
|
174
|
+
return cc['max-age'] && cc['max-age'] <= age;
|
175
|
+
}
|
@@ -36,7 +36,7 @@ module.exports = function vhost(hostname, server){
|
|
36
36
|
var host = req.headers.host.split(':')[0];
|
37
37
|
if (req.subdomains = regexp.exec(host)) {
|
38
38
|
req.subdomains = req.subdomains[0].split('.').slice(0, -1);
|
39
|
-
server.emit("request", req, res
|
39
|
+
server.emit("request", req, res);
|
40
40
|
} else {
|
41
41
|
next();
|
42
42
|
}
|
@@ -403,14 +403,21 @@ exports.parseRange = function(size, str){
|
|
403
403
|
*/
|
404
404
|
|
405
405
|
exports.parseCacheControl = function(str){
|
406
|
-
var
|
407
|
-
, key = parts.shift()
|
408
|
-
, val = parseInt(parts.shift(), 10)
|
406
|
+
var directives = str.split(',')
|
409
407
|
, obj = {};
|
410
|
-
|
408
|
+
|
409
|
+
for(var i = 0, len = directives.length; i < len; i++) {
|
410
|
+
var parts = directives[i].split('=')
|
411
|
+
, key = parts.shift().trim()
|
412
|
+
, val = parseInt(parts.shift(), 10);
|
413
|
+
|
414
|
+
obj[key] = isNaN(val) ? true : val;
|
415
|
+
}
|
416
|
+
|
411
417
|
return obj;
|
412
418
|
};
|
413
419
|
|
420
|
+
|
414
421
|
/**
|
415
422
|
* Convert array-like object to an `Array`.
|
416
423
|
*
|
@@ -0,0 +1,286 @@
|
|
1
|
+
# Formidable
|
2
|
+
|
3
|
+
[![Build Status](https://secure.travis-ci.org/felixge/node-formidable.png)](http://travis-ci.org/felixge/node-formidable)
|
4
|
+
|
5
|
+
## Purpose
|
6
|
+
|
7
|
+
A node.js module for parsing form data, especially file uploads.
|
8
|
+
|
9
|
+
## Current status
|
10
|
+
|
11
|
+
This module was developed for [Transloadit](http://transloadit.com/), a service focused on uploading
|
12
|
+
and encoding images and videos. It has been battle-tested against hundreds of GB of file uploads from
|
13
|
+
a large variety of clients and is considered production-ready.
|
14
|
+
|
15
|
+
## Features
|
16
|
+
|
17
|
+
* Fast (~500mb/sec), non-buffering multipart parser
|
18
|
+
* Automatically writing file uploads to disk
|
19
|
+
* Low memory footprint
|
20
|
+
* Graceful error handling
|
21
|
+
* Very high test coverage
|
22
|
+
|
23
|
+
## Changelog
|
24
|
+
|
25
|
+
### v1.0.6
|
26
|
+
|
27
|
+
* Do not default to the default to the field name for file uploads where
|
28
|
+
filename="".
|
29
|
+
|
30
|
+
### v1.0.5
|
31
|
+
|
32
|
+
* Support filename="" in multipart parts
|
33
|
+
* Explain unexpected end() errors in parser better
|
34
|
+
|
35
|
+
**Note:** Starting with this version, formidable emits 'file' events for empty
|
36
|
+
file input fields. Previously those were incorrectly emitted as regular file
|
37
|
+
input fields with value = "".
|
38
|
+
|
39
|
+
### v1.0.4
|
40
|
+
|
41
|
+
* Detect a good default tmp directory regardless of platform. (#88)
|
42
|
+
|
43
|
+
### v1.0.3
|
44
|
+
|
45
|
+
* Fix problems with utf8 characters (#84) / semicolons in filenames (#58)
|
46
|
+
* Small performance improvements
|
47
|
+
* New test suite and fixture system
|
48
|
+
|
49
|
+
### v1.0.2
|
50
|
+
|
51
|
+
* Exclude node\_modules folder from git
|
52
|
+
* Implement new `'aborted'` event
|
53
|
+
* Fix files in example folder to work with recent node versions
|
54
|
+
* Make gently a devDependency
|
55
|
+
|
56
|
+
[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.1...v1.0.2)
|
57
|
+
|
58
|
+
### v1.0.1
|
59
|
+
|
60
|
+
* Fix package.json to refer to proper main directory. (#68, Dean Landolt)
|
61
|
+
|
62
|
+
[See Commits](https://github.com/felixge/node-formidable/compare/v1.0.0...v1.0.1)
|
63
|
+
|
64
|
+
### v1.0.0
|
65
|
+
|
66
|
+
* Add support for multipart boundaries that are quoted strings. (Jeff Craig)
|
67
|
+
|
68
|
+
This marks the beginning of development on version 2.0 which will include
|
69
|
+
several architectural improvements.
|
70
|
+
|
71
|
+
[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.11...v1.0.0)
|
72
|
+
|
73
|
+
### v0.9.11
|
74
|
+
|
75
|
+
* Emit `'progress'` event when receiving data, regardless of parsing it. (Tim Koschützki)
|
76
|
+
* Use [W3C FileAPI Draft](http://dev.w3.org/2006/webapi/FileAPI/) properties for File class
|
77
|
+
|
78
|
+
**Important:** The old property names of the File class will be removed in a
|
79
|
+
future release.
|
80
|
+
|
81
|
+
[See Commits](https://github.com/felixge/node-formidable/compare/v0.9.10...v0.9.11)
|
82
|
+
|
83
|
+
### Older releases
|
84
|
+
|
85
|
+
These releases were done before starting to maintain the above Changelog:
|
86
|
+
|
87
|
+
* [v0.9.10](https://github.com/felixge/node-formidable/compare/v0.9.9...v0.9.10)
|
88
|
+
* [v0.9.9](https://github.com/felixge/node-formidable/compare/v0.9.8...v0.9.9)
|
89
|
+
* [v0.9.8](https://github.com/felixge/node-formidable/compare/v0.9.7...v0.9.8)
|
90
|
+
* [v0.9.7](https://github.com/felixge/node-formidable/compare/v0.9.6...v0.9.7)
|
91
|
+
* [v0.9.6](https://github.com/felixge/node-formidable/compare/v0.9.5...v0.9.6)
|
92
|
+
* [v0.9.5](https://github.com/felixge/node-formidable/compare/v0.9.4...v0.9.5)
|
93
|
+
* [v0.9.4](https://github.com/felixge/node-formidable/compare/v0.9.3...v0.9.4)
|
94
|
+
* [v0.9.3](https://github.com/felixge/node-formidable/compare/v0.9.2...v0.9.3)
|
95
|
+
* [v0.9.2](https://github.com/felixge/node-formidable/compare/v0.9.1...v0.9.2)
|
96
|
+
* [v0.9.1](https://github.com/felixge/node-formidable/compare/v0.9.0...v0.9.1)
|
97
|
+
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
98
|
+
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
99
|
+
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
100
|
+
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
101
|
+
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
102
|
+
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
103
|
+
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
104
|
+
* [v0.9.0](https://github.com/felixge/node-formidable/compare/v0.8.0...v0.9.0)
|
105
|
+
* [v0.1.0](https://github.com/felixge/node-formidable/commits/v0.1.0)
|
106
|
+
|
107
|
+
## Installation
|
108
|
+
|
109
|
+
Via [npm](http://github.com/isaacs/npm):
|
110
|
+
|
111
|
+
npm install formidable@latest
|
112
|
+
|
113
|
+
Manually:
|
114
|
+
|
115
|
+
git clone git://github.com/felixge/node-formidable.git formidable
|
116
|
+
vim my.js
|
117
|
+
# var formidable = require('./formidable');
|
118
|
+
|
119
|
+
Note: Formidable requires [gently](http://github.com/felixge/node-gently) to run the unit tests, but you won't need it for just using the library.
|
120
|
+
|
121
|
+
## Example
|
122
|
+
|
123
|
+
Parse an incoming file upload.
|
124
|
+
|
125
|
+
var formidable = require('formidable'),
|
126
|
+
http = require('http'),
|
127
|
+
|
128
|
+
sys = require('sys');
|
129
|
+
|
130
|
+
http.createServer(function(req, res) {
|
131
|
+
if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
|
132
|
+
// parse a file upload
|
133
|
+
var form = new formidable.IncomingForm();
|
134
|
+
form.parse(req, function(err, fields, files) {
|
135
|
+
res.writeHead(200, {'content-type': 'text/plain'});
|
136
|
+
res.write('received upload:\n\n');
|
137
|
+
res.end(sys.inspect({fields: fields, files: files}));
|
138
|
+
});
|
139
|
+
return;
|
140
|
+
}
|
141
|
+
|
142
|
+
// show a file upload form
|
143
|
+
res.writeHead(200, {'content-type': 'text/html'});
|
144
|
+
res.end(
|
145
|
+
'<form action="/upload" enctype="multipart/form-data" method="post">'+
|
146
|
+
'<input type="text" name="title"><br>'+
|
147
|
+
'<input type="file" name="upload" multiple="multiple"><br>'+
|
148
|
+
'<input type="submit" value="Upload">'+
|
149
|
+
'</form>'
|
150
|
+
);
|
151
|
+
}).listen(80);
|
152
|
+
|
153
|
+
## API
|
154
|
+
|
155
|
+
### formidable.IncomingForm
|
156
|
+
|
157
|
+
#### new formidable.IncomingForm()
|
158
|
+
|
159
|
+
Creates a new incoming form.
|
160
|
+
|
161
|
+
#### incomingForm.encoding = 'utf-8'
|
162
|
+
|
163
|
+
The encoding to use for incoming form fields.
|
164
|
+
|
165
|
+
#### incomingForm.uploadDir = process.env.TMP || '/tmp' || process.cwd()
|
166
|
+
|
167
|
+
The directory for placing file uploads in. You can move them later on using
|
168
|
+
`fs.rename()`. The default directory is picked at module load time depending on
|
169
|
+
the first existing directory from those listed above.
|
170
|
+
|
171
|
+
#### incomingForm.keepExtensions = false
|
172
|
+
|
173
|
+
If you want the files written to `incomingForm.uploadDir` to include the extensions of the original files, set this property to `true`.
|
174
|
+
|
175
|
+
#### incomingForm.type
|
176
|
+
|
177
|
+
Either 'multipart' or 'urlencoded' depending on the incoming request.
|
178
|
+
|
179
|
+
#### incomingForm.maxFieldsSize = 2 * 1024 * 1024
|
180
|
+
|
181
|
+
Limits the amount of memory a field (not file) can allocate in bytes.
|
182
|
+
If this value is exceeded, an `'error'` event is emitted. The default
|
183
|
+
size is 2MB.
|
184
|
+
|
185
|
+
#### incomingForm.bytesReceived
|
186
|
+
|
187
|
+
The amount of bytes received for this form so far.
|
188
|
+
|
189
|
+
#### incomingForm.bytesExpected
|
190
|
+
|
191
|
+
The expected number of bytes in this form.
|
192
|
+
|
193
|
+
#### incomingForm.parse(request, [cb])
|
194
|
+
|
195
|
+
Parses an incoming node.js `request` containing form data. If `cb` is provided, all fields an files are collected and passed to the callback:
|
196
|
+
|
197
|
+
incomingForm.parse(req, function(err, fields, files) {
|
198
|
+
// ...
|
199
|
+
});
|
200
|
+
|
201
|
+
#### incomingForm.onPart(part)
|
202
|
+
|
203
|
+
You may overwrite this method if you are interested in directly accessing the multipart stream. Doing so will disable any `'field'` / `'file'` events processing which would occur otherwise, making you fully responsible for handling the processing.
|
204
|
+
|
205
|
+
incomingForm.onPart = function(part) {
|
206
|
+
part.addListener('data', function() {
|
207
|
+
// ...
|
208
|
+
});
|
209
|
+
}
|
210
|
+
|
211
|
+
If you want to use formidable to only handle certain parts for you, you can do so:
|
212
|
+
|
213
|
+
incomingForm.onPart = function(part) {
|
214
|
+
if (!part.filename) {
|
215
|
+
// let formidable handle all non-file parts
|
216
|
+
incomingForm.handlePart(part);
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
Check the code in this method for further inspiration.
|
221
|
+
|
222
|
+
#### Event: 'progress' (bytesReceived, bytesExpected)
|
223
|
+
|
224
|
+
Emitted after each incoming chunk of data that has been parsed. Can be used to roll your own progress bar.
|
225
|
+
|
226
|
+
#### Event: 'field' (name, value)
|
227
|
+
|
228
|
+
Emitted whenever a field / value pair has been received.
|
229
|
+
|
230
|
+
#### Event: 'fileBegin' (name, file)
|
231
|
+
|
232
|
+
Emitted whenever a new file is detected in the upload stream. Use this even if
|
233
|
+
you want to stream the file to somewhere else while buffering the upload on
|
234
|
+
the file system.
|
235
|
+
|
236
|
+
#### Event: 'file' (name, file)
|
237
|
+
|
238
|
+
Emitted whenever a field / file pair has been received. `file` is an instance of `File`.
|
239
|
+
|
240
|
+
#### Event: 'error' (err)
|
241
|
+
|
242
|
+
Emitted when there is an error processing the incoming form. A request that experiences an error is automatically paused, you will have to manually call `request.resume()` if you want the request to continue firing `'data'` events.
|
243
|
+
|
244
|
+
#### Event: 'aborted'
|
245
|
+
|
246
|
+
Emitted when the request was aborted by the user. Right now this can be due to a 'timeout' or 'close' event on the socket. In the future there will be a separate 'timeout' event (needs a change in the node core).
|
247
|
+
|
248
|
+
#### Event: 'end' ()
|
249
|
+
|
250
|
+
Emitted when the entire request has been received, and all contained files have finished flushing to disk. This is a great place for you to send your response.
|
251
|
+
|
252
|
+
### formidable.File
|
253
|
+
|
254
|
+
#### file.size = 0
|
255
|
+
|
256
|
+
The size of the uploaded file in bytes. If the file is still being uploaded (see `'fileBegin'` event), this property says how many bytes of the file have been written to disk yet.
|
257
|
+
|
258
|
+
#### file.path = null
|
259
|
+
|
260
|
+
The path this file is being written to. You can modify this in the `'fileBegin'` event in
|
261
|
+
case you are unhappy with the way formidable generates a temporary path for your files.
|
262
|
+
|
263
|
+
#### file.name = null
|
264
|
+
|
265
|
+
The name this file had according to the uploading client.
|
266
|
+
|
267
|
+
#### file.type = null
|
268
|
+
|
269
|
+
The mime type of this file, according to the uploading client.
|
270
|
+
|
271
|
+
#### file.lastModifiedDate = null
|
272
|
+
|
273
|
+
A date object (or `null`) containing the time this file was last written to. Mostly
|
274
|
+
here for compatibility with the [W3C File API Draft](http://dev.w3.org/2006/webapi/FileAPI/).
|
275
|
+
|
276
|
+
## License
|
277
|
+
|
278
|
+
Formidable is licensed under the MIT license.
|
279
|
+
|
280
|
+
## Ports
|
281
|
+
|
282
|
+
* [multipart-parser](http://github.com/FooBarWidget/multipart-parser): a C++ parser based on formidable
|
283
|
+
|
284
|
+
## Credits
|
285
|
+
|
286
|
+
* [Ryan Dahl](http://twitter.com/ryah) for his work on [http-parser](http://github.com/ry/http-parser) which heavily inspired multipart_parser.js
|