vulcan 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. data/lib/vulcan/cli.rb +3 -0
  2. data/lib/vulcan/version.rb +1 -1
  3. data/server/lib/spawner.js +9 -4
  4. data/server/node_modules/cradle/lib/cradle.js +0 -1
  5. data/server/node_modules/cradle/package.json +3 -3
  6. data/server/node_modules/cradle/test/cache-test.js +6 -7
  7. data/server/node_modules/cradle/test/cradle-test.js +4 -5
  8. data/server/node_modules/cradle/test/response-test.js +5 -6
  9. data/server/node_modules/express/History.md +40 -0
  10. data/server/node_modules/express/Makefile +3 -9
  11. data/server/node_modules/express/Readme.md +3 -1
  12. data/server/node_modules/express/bin/express +61 -63
  13. data/server/node_modules/express/lib/express.js +1 -1
  14. data/server/node_modules/express/lib/request.js +9 -7
  15. data/server/node_modules/express/lib/view.js +19 -16
  16. data/server/node_modules/express/node_modules/connect/lib/connect.js +1 -1
  17. data/server/node_modules/express/node_modules/connect/lib/http.js +2 -0
  18. data/server/node_modules/express/node_modules/connect/lib/middleware/bodyParser.js +135 -31
  19. data/server/node_modules/express/node_modules/connect/lib/middleware/limit.js +5 -1
  20. data/server/node_modules/express/node_modules/connect/lib/middleware/session.js +2 -2
  21. data/server/node_modules/express/node_modules/connect/lib/middleware/static.js +26 -21
  22. data/server/node_modules/express/node_modules/connect/lib/middleware/staticCache.js +91 -38
  23. data/server/node_modules/express/node_modules/connect/lib/middleware/vhost.js +1 -1
  24. data/server/node_modules/express/node_modules/connect/lib/utils.js +11 -4
  25. data/server/node_modules/express/node_modules/connect/node_modules/formidable/Makefile +14 -0
  26. data/server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md +286 -0
  27. data/server/node_modules/express/node_modules/connect/node_modules/formidable/TODO +3 -0
  28. data/server/node_modules/express/node_modules/connect/node_modules/formidable/benchmark/bench-multipart-parser.js +70 -0
  29. data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/post.js +43 -0
  30. data/server/node_modules/express/node_modules/connect/node_modules/formidable/example/upload.js +48 -0
  31. data/server/node_modules/express/node_modules/connect/node_modules/formidable/index.js +1 -0
  32. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/file.js +61 -0
  33. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js +377 -0
  34. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/index.js +3 -0
  35. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/multipart_parser.js +312 -0
  36. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/querystring_parser.js +25 -0
  37. data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/util.js +6 -0
  38. data/server/node_modules/express/node_modules/connect/node_modules/formidable/package.json +22 -0
  39. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/common.js +19 -0
  40. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/funkyfilename.txt +1 -0
  41. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/file/plain.txt +1 -0
  42. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http +13 -0
  43. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/info.md +3 -0
  44. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +26 -0
  45. 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
  46. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +23 -0
  47. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +24 -0
  48. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +22 -0
  49. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +22 -0
  50. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +22 -0
  51. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/no-filename.js +3 -0
  52. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/js/special-chars-in-filename.js +21 -0
  53. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multi_video.upload +0 -0
  54. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/multipart.js +72 -0
  55. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/integration/test-fixtures.js +89 -0
  56. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/common.js +24 -0
  57. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/integration/test-multipart-parser.js +80 -0
  58. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-file.js +104 -0
  59. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js +715 -0
  60. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-multipart-parser.js +50 -0
  61. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-querystring-parser.js +45 -0
  62. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/system/test-multi-video-upload.js +72 -0
  63. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/run.js +2 -0
  64. data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/unit/test-incoming-form.js +63 -0
  65. data/server/node_modules/express/node_modules/connect/node_modules/formidable/tool/record.js +47 -0
  66. data/server/node_modules/express/node_modules/connect/package.json +7 -6
  67. data/server/node_modules/express/node_modules/connect/test.js +44 -31
  68. data/server/node_modules/express/node_modules/qs/History.md +11 -0
  69. data/server/node_modules/express/node_modules/qs/Makefile +1 -3
  70. data/server/node_modules/express/node_modules/qs/Readme.md +2 -4
  71. data/server/node_modules/express/node_modules/qs/lib/querystring.js +100 -74
  72. data/server/node_modules/express/node_modules/qs/package.json +9 -2
  73. data/server/node_modules/express/node_modules/qs/test/mocha.opts +2 -0
  74. data/server/node_modules/express/node_modules/qs/test/{parse.test.js → parse.js} +1 -2
  75. data/server/node_modules/express/node_modules/qs/test/{stringify.test.js → stringify.js} +0 -0
  76. data/server/node_modules/express/package.json +7 -7
  77. data/server/node_modules/express/testing/foo/app.js +35 -0
  78. data/server/node_modules/express/testing/foo/package.json +9 -0
  79. data/server/node_modules/express/testing/foo/public/stylesheets/style.css +8 -0
  80. data/server/node_modules/express/testing/foo/routes/index.js +10 -0
  81. data/server/node_modules/express/testing/foo/views/index.jade +2 -0
  82. data/server/node_modules/express/testing/foo/views/layout.jade +6 -0
  83. data/server/node_modules/express/testing/index.js +31 -5
  84. data/server/node_modules/express/testing/public/test.txt +2971 -0
  85. data/server/node_modules/express/testing/views/page.html +1 -0
  86. data/server/node_modules/express/testing/views/page.jade +3 -0
  87. data/server/node_modules/express/testing/views/test.md +1 -0
  88. data/server/node_modules/express/testing/views/user/index.jade +1 -0
  89. data/server/node_modules/express/testing/views/user/list.jade +1 -0
  90. data/server/node_modules/node-uuid/README.md +166 -67
  91. data/server/node_modules/node-uuid/benchmark/README.md +53 -0
  92. data/server/node_modules/node-uuid/benchmark/bench.gnu +174 -0
  93. data/server/node_modules/node-uuid/benchmark/bench.sh +34 -0
  94. data/server/node_modules/node-uuid/{test → benchmark}/benchmark-native.c +0 -0
  95. data/server/node_modules/node-uuid/benchmark/benchmark.js +84 -0
  96. data/server/node_modules/node-uuid/package.json +5 -3
  97. data/server/node_modules/node-uuid/test/benchmark-native +0 -0
  98. data/server/node_modules/node-uuid/test/compare_v1.js +63 -0
  99. data/server/node_modules/node-uuid/test/test.html +3 -0
  100. data/server/node_modules/node-uuid/test/test.js +214 -57
  101. data/server/node_modules/node-uuid/uuid.js +225 -56
  102. data/server/node_modules/restler/README.md +20 -7
  103. data/server/node_modules/restler/bin/restler +1 -1
  104. data/server/node_modules/restler/lib/multipartform.js +9 -8
  105. data/server/node_modules/restler/lib/restler.js +64 -22
  106. data/server/node_modules/restler/package.json +2 -2
  107. data/server/node_modules/restler/test/restler.js +22 -2
  108. data/server/node_modules/restler/test/test_helper.js +20 -1
  109. data/server/package.json +8 -8
  110. data/server/web.js +22 -6
  111. metadata +72 -82
  112. data/server/node_modules/cradle/node_modules/vows/LICENSE +0 -20
  113. data/server/node_modules/cradle/node_modules/vows/Makefile +0 -7
  114. data/server/node_modules/cradle/node_modules/vows/README.md +0 -39
  115. data/server/node_modules/cradle/node_modules/vows/bin/vows +0 -515
  116. data/server/node_modules/cradle/node_modules/vows/lib/assert/error.js +0 -27
  117. data/server/node_modules/cradle/node_modules/vows/lib/assert/macros.js +0 -215
  118. data/server/node_modules/cradle/node_modules/vows/lib/assert/utils.js +0 -77
  119. data/server/node_modules/cradle/node_modules/vows/lib/vows.js +0 -193
  120. data/server/node_modules/cradle/node_modules/vows/lib/vows/console.js +0 -131
  121. data/server/node_modules/cradle/node_modules/vows/lib/vows/context.js +0 -55
  122. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/file.js +0 -29
  123. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-foot.html +0 -2
  124. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/fragments/coverage-head.html +0 -61
  125. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-html.js +0 -54
  126. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-json.js +0 -54
  127. data/server/node_modules/cradle/node_modules/vows/lib/vows/coverage/report-plain.js +0 -38
  128. data/server/node_modules/cradle/node_modules/vows/lib/vows/extras.js +0 -28
  129. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/dot-matrix.js +0 -67
  130. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/json.js +0 -16
  131. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/silent.js +0 -8
  132. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/spec.js +0 -44
  133. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/watch.js +0 -39
  134. data/server/node_modules/cradle/node_modules/vows/lib/vows/reporters/xunit.js +0 -90
  135. data/server/node_modules/cradle/node_modules/vows/lib/vows/suite.js +0 -319
  136. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/LICENSE +0 -20
  137. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/Makefile +0 -4
  138. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/README.md +0 -72
  139. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/lib/eyes.js +0 -233
  140. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/package.json +0 -14
  141. data/server/node_modules/cradle/node_modules/vows/node_modules/eyes/test/eyes-test.js +0 -55
  142. data/server/node_modules/cradle/node_modules/vows/package.json +0 -14
  143. data/server/node_modules/cradle/node_modules/vows/test/assert-test.js +0 -135
  144. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/failing.js +0 -18
  145. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/log.js +0 -18
  146. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/passing.js +0 -17
  147. data/server/node_modules/cradle/node_modules/vows/test/fixtures/isolate/stderr.js +0 -18
  148. data/server/node_modules/cradle/node_modules/vows/test/isolate-test.js +0 -140
  149. data/server/node_modules/cradle/node_modules/vows/test/testInherit.js +0 -133
  150. data/server/node_modules/cradle/node_modules/vows/test/vows-error-test.js +0 -51
  151. data/server/node_modules/cradle/node_modules/vows/test/vows-test.js +0 -374
  152. data/server/node_modules/express/node_modules/qs/support/expresso/History.md +0 -128
  153. data/server/node_modules/express/node_modules/qs/support/expresso/Makefile +0 -53
  154. data/server/node_modules/express/node_modules/qs/support/expresso/Readme.md +0 -61
  155. data/server/node_modules/express/node_modules/qs/support/expresso/bin/expresso +0 -856
  156. data/server/node_modules/express/node_modules/qs/support/expresso/docs/api.html +0 -1080
  157. data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.html +0 -377
  158. data/server/node_modules/express/node_modules/qs/support/expresso/docs/index.md +0 -290
  159. data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/foot.html +0 -3
  160. data/server/node_modules/express/node_modules/qs/support/expresso/docs/layout/head.html +0 -42
  161. data/server/node_modules/express/node_modules/qs/support/expresso/lib/bar.js +0 -4
  162. data/server/node_modules/express/node_modules/qs/support/expresso/lib/foo.js +0 -16
  163. data/server/node_modules/express/node_modules/qs/support/expresso/package.json +0 -12
  164. data/server/node_modules/express/node_modules/qs/support/expresso/test/assert.test.js +0 -91
  165. data/server/node_modules/express/node_modules/qs/support/expresso/test/async.test.js +0 -12
  166. data/server/node_modules/express/node_modules/qs/support/expresso/test/bar.test.js +0 -13
  167. data/server/node_modules/express/node_modules/qs/support/expresso/test/foo.test.js +0 -14
  168. data/server/node_modules/express/node_modules/qs/support/expresso/test/http.test.js +0 -146
  169. data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/async.test.js +0 -39
  170. data/server/node_modules/express/node_modules/qs/support/expresso/test/serial/http.test.js +0 -48
  171. data/server/node_modules/express/node_modules/qs/support/should/History.md +0 -22
  172. data/server/node_modules/express/node_modules/qs/support/should/Makefile +0 -6
  173. data/server/node_modules/express/node_modules/qs/support/should/Readme.md +0 -248
  174. data/server/node_modules/express/node_modules/qs/support/should/examples/runner.js +0 -53
  175. data/server/node_modules/express/node_modules/qs/support/should/index.js +0 -2
  176. data/server/node_modules/express/node_modules/qs/support/should/lib/eql.js +0 -91
  177. data/server/node_modules/express/node_modules/qs/support/should/lib/should.js +0 -548
  178. data/server/node_modules/express/node_modules/qs/support/should/package.json +0 -8
  179. data/server/node_modules/express/node_modules/qs/support/should/test/should.test.js +0 -358
  180. data/server/node_modules/express/testing/views/users.jade +0 -1
  181. data/server/node_modules/node-uuid/test/benchmark.js +0 -27
@@ -28,7 +28,7 @@ var exports = module.exports = connect.middleware;
28
28
  * Framework version.
29
29
  */
30
30
 
31
- exports.version = '2.4.7';
31
+ exports.version = '2.5.6';
32
32
 
33
33
  /**
34
34
  * Shortcut for `new Server(...)`.
@@ -292,16 +292,18 @@ req.flash = function(type, msg){
292
292
  req.is = function(type){
293
293
  var fn = this.app.is(type);
294
294
  if (fn) return fn(this);
295
- var contentType = this.headers['content-type'];
296
- if (!contentType) return;
295
+ var ct = this.headers['content-type'];
296
+ if (!ct) return false;
297
+ ct = ct.split(';')[0];
297
298
  if (!~type.indexOf('/')) type = mime.lookup(type);
298
299
  if (~type.indexOf('*')) {
299
- type = type.split('/')
300
- contentType = contentType.split('/');
301
- if ('*' == type[0] && type[1] == contentType[1]) return true;
302
- if ('*' == type[1] && type[0] == contentType[0]) return true;
300
+ type = type.split('/');
301
+ ct = ct.split('/');
302
+ if ('*' == type[0] && type[1] == ct[1]) return true;
303
+ if ('*' == type[1] && type[0] == ct[0]) return true;
304
+ return false;
303
305
  }
304
- return !! ~contentType.indexOf(type);
306
+ return !! ~ct.indexOf(type);
305
307
  };
306
308
 
307
309
  // Callback for isXMLHttpRequest / xhr
@@ -47,7 +47,10 @@ exports.register = View.register;
47
47
  */
48
48
 
49
49
  exports.compile = function(view, cache, cid, options){
50
- if (cache && cid && cache[cid]) return cache[cid];
50
+ if (cache && cid && cache[cid]){
51
+ options.filename = cache[cid].path;
52
+ return cache[cid];
53
+ }
51
54
 
52
55
  // lookup
53
56
  view = exports.lookup(view, options);
@@ -58,13 +61,13 @@ exports.compile = function(view, cache, cid, options){
58
61
  var err = new Error('failed to locate view "' + view.original.view + '"');
59
62
  err.view = view.original;
60
63
  throw err;
61
- }
64
+ }
62
65
 
63
66
  // compile
64
67
  options.filename = view.path;
65
68
  view.fn = view.templateEngine.compile(view.contents, options);
66
69
  cache[cid] = view;
67
-
70
+
68
71
  return view;
69
72
  };
70
73
 
@@ -81,11 +84,11 @@ exports.compile = function(view, cache, cid, options){
81
84
  *
82
85
  * Lookup:
83
86
  *
84
- * - partial `_<name>`
85
- * - any `<name>/index`
86
- * - non-layout `../<name>/index`
87
- * - any `<root>/<name>`
88
- * - partial `<root>/_<name>`
87
+ * - partial `_<name>`
88
+ * - any `<name>/index`
89
+ * - non-layout `../<name>/index`
90
+ * - any `<root>/<name>`
91
+ * - partial `<root>/_<name>`
89
92
  *
90
93
  * @param {String} view
91
94
  * @param {Object} options
@@ -161,7 +164,7 @@ function renderPartial(res, view, options, parentLocals, parent){
161
164
 
162
165
  // Inherit locals from parent
163
166
  union(options, parentLocals);
164
-
167
+
165
168
  // Merge locals
166
169
  if (locals) merge(options, locals);
167
170
 
@@ -202,7 +205,7 @@ function renderPartial(res, view, options, parentLocals, parent){
202
205
  options.lastInCollection = i == len - 1;
203
206
  object = val;
204
207
  buf += render();
205
- }
208
+ }
206
209
  } else {
207
210
  keys = Object.keys(collection);
208
211
  len = keys.length;
@@ -227,20 +230,20 @@ function renderPartial(res, view, options, parentLocals, parent){
227
230
  };
228
231
 
229
232
  /**
230
- * Render `view` partial with the given `options`. Optionally a
233
+ * Render `view` partial with the given `options`. Optionally a
231
234
  * callback `fn(err, str)` may be passed instead of writing to
232
235
  * the socket.
233
236
  *
234
237
  * Options:
235
238
  *
236
- * - `object` Single object with name derived from the view (unless `as` is present)
239
+ * - `object` Single object with name derived from the view (unless `as` is present)
237
240
  *
238
241
  * - `as` Variable name for each `collection` value, defaults to the view name.
239
242
  * * as: 'something' will add the `something` local variable
240
243
  * * as: this will use the collection value as the template context
241
244
  * * as: global will merge the collection value's properties with `locals`
242
245
  *
243
- * - `collection` Array of objects, the name is derived from the view name itself.
246
+ * - `collection` Array of objects, the name is derived from the view name itself.
244
247
  * For example _video.html_ will have a object _video_ available to it.
245
248
  *
246
249
  * @param {String} view
@@ -294,7 +297,7 @@ res.partial = function(view, options, fn){
294
297
  * automatically, however otherwise a response of _200_ and _text/html_ is given.
295
298
  *
296
299
  * Options:
297
- *
300
+ *
298
301
  * - `scope` Template evaluation context (the value of `this`)
299
302
  * - `debug` Output debugging information
300
303
  * - `status` Response status code
@@ -430,7 +433,7 @@ res._render = function(view, opts, fn, parent, sub){
430
433
  // partial return
431
434
  } else if (partial) {
432
435
  return str;
433
- // render complete, and
436
+ // render complete, and
434
437
  // callback given
435
438
  } else if (fn) {
436
439
  fn(null, str);
@@ -454,4 +457,4 @@ function hintAtViewPaths(view, options) {
454
457
  console.error(' - %s', path);
455
458
  });
456
459
  console.error();
457
- }
460
+ }
@@ -26,7 +26,7 @@ exports = module.exports = createServer;
26
26
  * Framework version.
27
27
  */
28
28
 
29
- exports.version = '1.7.1';
29
+ exports.version = '1.8.5';
30
30
 
31
31
  /**
32
32
  * Initialize a new `connect.HTTPServer` with the middleware
@@ -163,10 +163,12 @@ Server.prototype.handle = function(req, res, out) {
163
163
 
164
164
  res.statusCode = 500;
165
165
  res.setHeader('Content-Type', 'text/plain');
166
+ if ('HEAD' == req.method) return res.end();
166
167
  res.end(msg);
167
168
  } else {
168
169
  res.statusCode = 404;
169
170
  res.setHeader('Content-Type', 'text/plain');
171
+ if ('HEAD' == req.method) return res.end();
170
172
  res.end('Cannot ' + req.method + ' ' + req.url);
171
173
  }
172
174
  return;
@@ -10,7 +10,8 @@
10
10
  * Module dependencies.
11
11
  */
12
12
 
13
- var qs = require('qs');
13
+ var qs = require('qs')
14
+ , formidable = require('formidable');
14
15
 
15
16
  /**
16
17
  * Extract the mime type from the given request's
@@ -29,10 +30,9 @@ function mime(req) {
29
30
  /**
30
31
  * Parse request bodies.
31
32
  *
32
- * By default _application/json_ and _application/x-www-form-urlencoded_
33
- * are supported, however you may map `connect.bodyParser.parse[contentType]`
34
- * to a function of your choice to replace existing parsers, or implement
35
- * one for other content-types.
33
+ * By default _application/json_, _application/x-www-form-urlencoded_,
34
+ * and _multipart/form-data_ are supported, however you may map `connect.bodyParser.parse[contentType]`
35
+ * to a function receiving `(req, options, callback)`.
36
36
  *
37
37
  * Examples:
38
38
  *
@@ -43,36 +43,52 @@ function mime(req) {
43
43
  * }
44
44
  * );
45
45
  *
46
- * Since both _json_ and _x-www-form-urlencoded_ are supported by
47
- * default, either of the following requests would result in the response
48
- * of "viewing user tj".
49
- *
50
46
  * $ curl -d 'user[name]=tj' http://localhost/
51
47
  * $ curl -d '{"user":{"name":"tj"}}' -H "Content-Type: application/json" http://localhost/
52
48
  *
49
+ * Multipart req.files:
50
+ *
51
+ * As a security measure files are stored in a separate object, stored
52
+ * as `req.files`. This prevents attacks that may potentially alter
53
+ * filenames, and depending on the application gain access to restricted files.
54
+ *
55
+ * Multipart configuration:
56
+ *
57
+ * The `options` passed are provided to each parser function.
58
+ * The _multipart/form-data_ parser merges these with formidable's
59
+ * IncomingForm object, allowing you to tweak the upload directory,
60
+ * size limits, etc. For example you may wish to retain the file extension
61
+ * and change the upload directory:
62
+ *
63
+ * server.use(bodyParser({ uploadDir: '/www/mysite.com/uploads' }));
64
+ *
65
+ * View [node-formidable](https://github.com/felixge/node-formidable) for more information.
66
+ *
67
+ * If you wish to use formidable directly within your app, and do not
68
+ * desire this behaviour for multipart requests simply remove the
69
+ * parser:
70
+ *
71
+ * delete connect.bodyParser.parse['multipart/form-data'];
72
+ *
73
+ * Or
74
+ *
75
+ * delete express.bodyParser.parse['multipart/form-data'];
76
+ *
77
+ * @param {Object} options
53
78
  * @return {Function}
54
79
  * @api public
55
80
  */
56
81
 
57
- exports = module.exports = function bodyParser(){
82
+ exports = module.exports = function bodyParser(options){
83
+ options = options || {};
58
84
  return function bodyParser(req, res, next) {
85
+ if (req.body) return next();
86
+ req.body = {};
87
+
59
88
  if ('GET' == req.method || 'HEAD' == req.method) return next();
60
89
  var parser = exports.parse[mime(req)];
61
- if (parser && !req.body) {
62
- var data = '';
63
- req.setEncoding('utf8');
64
- req.on('data', function(chunk) { data += chunk; });
65
- req.on('end', function(){
66
- req.rawBody = data;
67
- try {
68
- req.body = data
69
- ? parser(data)
70
- : {};
71
- } catch (err) {
72
- return next(err);
73
- }
74
- next();
75
- });
90
+ if (parser) {
91
+ parser(req, options, next);
76
92
  } else {
77
93
  next();
78
94
  }
@@ -80,13 +96,101 @@ exports = module.exports = function bodyParser(){
80
96
  };
81
97
 
82
98
  /**
83
- * Supported decoders.
99
+ * Parsers.
100
+ */
101
+
102
+ exports.parse = {};
103
+
104
+ /**
105
+ * Parse application/x-www-form-urlencoded.
106
+ */
107
+
108
+ exports.parse['application/x-www-form-urlencoded'] = function(req, options, fn){
109
+ var buf = '';
110
+ req.setEncoding('utf8');
111
+ req.on('data', function(chunk){ buf += chunk });
112
+ req.on('end', function(){
113
+ try {
114
+ req.body = buf.length
115
+ ? qs.parse(buf)
116
+ : {};
117
+ fn();
118
+ } catch (err){
119
+ fn(err);
120
+ }
121
+ });
122
+ };
123
+
124
+ /**
125
+ * Parse application/json.
126
+ */
127
+
128
+ exports.parse['application/json'] = function(req, options, fn){
129
+ var buf = '';
130
+ req.setEncoding('utf8');
131
+ req.on('data', function(chunk){ buf += chunk });
132
+ req.on('end', function(){
133
+ try {
134
+ req.body = buf.length
135
+ ? JSON.parse(buf)
136
+ : {};
137
+ fn();
138
+ } catch (err){
139
+ fn(err);
140
+ }
141
+ });
142
+ };
143
+
144
+ /**
145
+ * Parse multipart/form-data.
84
146
  *
85
- * - application/x-www-form-urlencoded
86
- * - application/json
147
+ * TODO: make multiple support optional
148
+ * TODO: revisit "error" flag if it's a formidable bug
87
149
  */
88
150
 
89
- exports.parse = {
90
- 'application/x-www-form-urlencoded': qs.parse
91
- , 'application/json': JSON.parse
151
+ exports.parse['multipart/form-data'] = function(req, options, fn){
152
+ var form = new formidable.IncomingForm
153
+ , data = {}
154
+ , files = {}
155
+ , done;
156
+
157
+ Object.keys(options).forEach(function(key){
158
+ form[key] = options[key];
159
+ });
160
+
161
+ function ondata(name, val, data){
162
+ if (Array.isArray(data[name])) {
163
+ data[name].push(val);
164
+ } else if (data[name]) {
165
+ data[name] = [data[name], val];
166
+ } else {
167
+ data[name] = val;
168
+ }
169
+ }
170
+
171
+ form.on('field', function(name, val){
172
+ ondata(name, val, data);
173
+ });
174
+
175
+ form.on('file', function(name, val){
176
+ ondata(name, val, files);
177
+ });
178
+
179
+ form.on('error', function(err){
180
+ fn(err);
181
+ done = true;
182
+ });
183
+
184
+ form.on('end', function(){
185
+ if (done) return;
186
+ try {
187
+ req.body = qs.parse(data);
188
+ req.files = qs.parse(files);
189
+ fn();
190
+ } catch (err) {
191
+ fn(err);
192
+ }
193
+ });
194
+
195
+ form.parse(req);
92
196
  };
@@ -43,7 +43,11 @@ module.exports = function limit(bytes){
43
43
  req._limit = true;
44
44
 
45
45
  // limit by content-length
46
- if (len && len > bytes) deny();
46
+ if (len && len > bytes) {
47
+ res.statusCode = 413;
48
+ res.end('Request Entity Too Large');
49
+ return;
50
+ }
47
51
 
48
52
  // limit
49
53
  req.on('data', function(chunk){
@@ -55,10 +55,10 @@ function defaultFingerprint(req) {
55
55
  };
56
56
 
57
57
  /**
58
- * Paths to ignore, defaulting to `/favicon.ico`.
58
+ * Paths to ignore.
59
59
  */
60
60
 
61
- exports.ignore = ['/favicon.ico'];
61
+ exports.ignore = [];
62
62
 
63
63
  /**
64
64
  * Setup session store with the given `options`.
@@ -39,6 +39,7 @@ var fs = require('fs')
39
39
  *
40
40
  * - `maxAge` Browser cache maxAge in milliseconds. defaults to 0
41
41
  * - `hidden` Allow transfer of hidden files. defaults to false
42
+ * - `redirect` Redirect to trailing "/" when the pathname is a dir
42
43
  *
43
44
  * @param {String} root
44
45
  * @param {Object} options
@@ -101,6 +102,7 @@ var send = exports.send = function(req, res, next, options){
101
102
  , head = 'HEAD' == req.method
102
103
  , get = 'GET' == req.method
103
104
  , root = options.root ? normalize(options.root) : null
105
+ , redirect = false === options.redirect ? false : true
104
106
  , getOnly = options.getOnly
105
107
  , fn = options.callback
106
108
  , hidden = options.hidden
@@ -132,7 +134,7 @@ var send = exports.send = function(req, res, next, options){
132
134
  : utils.forbidden(res);
133
135
 
134
136
  // index.html support
135
- if ('/' == path[path.length - 1]) path += 'index.html';
137
+ if (normalize('/') == path[path.length - 1]) path += 'index.html';
136
138
 
137
139
  // "hidden" file
138
140
  if (!hidden && '.' == basename(path)[0]) return next();
@@ -149,13 +151,34 @@ var send = exports.send = function(req, res, next, options){
149
151
  : next(err);
150
152
  // redirect directory in case index.html is present
151
153
  } else if (stat.isDirectory()) {
154
+ if (!redirect) return next();
152
155
  res.statusCode = 301;
153
156
  res.setHeader('Location', url.pathname + '/');
154
157
  res.end('Redirecting to ' + url.pathname + '/');
155
158
  return;
156
159
  }
157
160
 
161
+ // header fields
162
+ if (!res.getHeader('Date')) res.setHeader('Date', new Date().toUTCString());
163
+ if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
164
+ if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
165
+ if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
166
+ if (!res.getHeader('content-type')) {
167
+ var charset = mime.charsets.lookup(type);
168
+ res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
169
+ }
170
+ res.setHeader('Accept-Ranges', 'bytes');
171
+
172
+ // conditional GET support
173
+ if (utils.conditionalGET(req)) {
174
+ if (!utils.modified(req, res)) {
175
+ req.emit('static');
176
+ return utils.notModified(res);
177
+ }
178
+ }
179
+
158
180
  var opts = {};
181
+ var chunkSize = stat.size;
159
182
 
160
183
  // we have a Range request
161
184
  if (ranges) {
@@ -166,6 +189,7 @@ var send = exports.send = function(req, res, next, options){
166
189
  // TODO: multiple support
167
190
  opts.start = ranges[0].start;
168
191
  opts.end = ranges[0].end;
192
+ chunkSize = opts.end - opts.start + 1;
169
193
  res.statusCode = 206;
170
194
  res.setHeader('Content-Range', 'bytes '
171
195
  + opts.start
@@ -179,27 +203,9 @@ var send = exports.send = function(req, res, next, options){
179
203
  ? fn(new Error('Requested Range Not Satisfiable'))
180
204
  : invalidRange(res);
181
205
  }
182
- // stream the entire file
183
- } else {
184
- res.setHeader('Content-Length', stat.size);
185
- if (!res.getHeader('Cache-Control')) res.setHeader('Cache-Control', 'public, max-age=' + (maxAge / 1000));
186
- if (!res.getHeader('Last-Modified')) res.setHeader('Last-Modified', stat.mtime.toUTCString());
187
- if (!res.getHeader('ETag')) res.setHeader('ETag', utils.etag(stat));
188
-
189
- // conditional GET support
190
- if (utils.conditionalGET(req)) {
191
- if (!utils.modified(req, res)) {
192
- return utils.notModified(res);
193
- }
194
- }
195
206
  }
196
207
 
197
- // header fields
198
- if (!res.getHeader('content-type')) {
199
- var charset = mime.charsets.lookup(type);
200
- res.setHeader('Content-Type', type + (charset ? '; charset=' + charset : ''));
201
- }
202
- res.setHeader('Accept-Ranges', 'bytes');
208
+ res.setHeader('Content-Length', chunkSize);
203
209
 
204
210
  // transfer
205
211
  if (head) return res.end();
@@ -213,7 +219,6 @@ var send = exports.send = function(req, res, next, options){
213
219
  if (fn) {
214
220
  function callback(err) { done || fn(err); done = true }
215
221
  req.on('close', callback);
216
- req.socket.on('error', callback);
217
222
  stream.on('end', callback);
218
223
  }
219
224
  });