vulcan 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/vulcan/cli.rb +20 -10
- data/lib/vulcan/version.rb +1 -1
- data/server/Procfile +1 -1
- data/server/bin/web +10 -0
- data/server/lib/cloudant.coffee +20 -0
- data/server/lib/logger.coffee +17 -0
- data/server/lib/on.coffee +10 -0
- data/server/lib/spawner.coffee +65 -0
- data/server/node_modules/coffee-script/CNAME +1 -0
- data/server/node_modules/coffee-script/LICENSE +22 -0
- data/server/node_modules/coffee-script/README +51 -0
- data/server/node_modules/coffee-script/Rakefile +78 -0
- data/server/node_modules/coffee-script/bin/cake +7 -0
- data/server/node_modules/coffee-script/bin/coffee +7 -0
- data/server/node_modules/coffee-script/extras/jsl.conf +44 -0
- data/server/node_modules/coffee-script/lib/coffee-script/browser.js +92 -0
- data/server/node_modules/coffee-script/lib/coffee-script/cake.js +111 -0
- data/server/node_modules/coffee-script/lib/coffee-script/coffee-script.js +167 -0
- data/server/node_modules/coffee-script/lib/coffee-script/command.js +500 -0
- data/server/node_modules/coffee-script/lib/coffee-script/grammar.js +606 -0
- data/server/node_modules/coffee-script/lib/coffee-script/helpers.js +77 -0
- data/server/node_modules/coffee-script/lib/coffee-script/index.js +11 -0
- data/server/node_modules/coffee-script/lib/coffee-script/lexer.js +788 -0
- data/server/node_modules/coffee-script/lib/coffee-script/nodes.js +2986 -0
- data/server/node_modules/coffee-script/lib/coffee-script/optparse.js +138 -0
- data/server/node_modules/coffee-script/lib/coffee-script/parser.js +683 -0
- data/server/node_modules/coffee-script/lib/coffee-script/repl.js +261 -0
- data/server/node_modules/coffee-script/lib/coffee-script/rewriter.js +349 -0
- data/server/node_modules/coffee-script/lib/coffee-script/scope.js +146 -0
- data/server/node_modules/coffee-script/package.json +55 -0
- data/server/node_modules/connect-form/History.md +0 -6
- data/server/node_modules/connect-form/lib/connect-form.js +2 -4
- data/server/node_modules/connect-form/node_modules/formidable/Readme.md +64 -36
- data/server/node_modules/connect-form/node_modules/formidable/lib/incoming_form.js +5 -1
- data/server/node_modules/connect-form/node_modules/formidable/package.json +20 -6
- data/server/node_modules/connect-form/node_modules/formidable/test/common.js +5 -6
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/file/funkyfilename.txt +1 -0
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/js/special-chars-in-filename.js +1 -1
- data/server/node_modules/connect-form/node_modules/formidable/test/{slow → integration}/test-fixtures.js +38 -33
- data/server/node_modules/connect-form/node_modules/formidable/test/legacy/simple/test-incoming-form.js +11 -0
- data/server/node_modules/connect-form/node_modules/formidable/test/run.js +1 -6
- data/server/node_modules/connect-form/node_modules/formidable/test/unit/test-incoming-form.js +63 -0
- data/server/node_modules/connect-form/package.json +27 -5
- data/server/node_modules/cradle/README.md +10 -10
- data/server/node_modules/cradle/lib/cradle.js +117 -523
- data/server/node_modules/cradle/lib/cradle/database/attachments.js +120 -0
- data/server/node_modules/cradle/lib/cradle/database/changes.js +56 -0
- data/server/node_modules/cradle/lib/cradle/database/documents.js +215 -0
- data/server/node_modules/cradle/lib/cradle/database/index.js +65 -0
- data/server/node_modules/cradle/lib/cradle/database/views.js +125 -0
- data/server/node_modules/cradle/node_modules/follow/LICENSE +202 -0
- data/server/node_modules/cradle/node_modules/follow/README.md +164 -0
- data/server/node_modules/cradle/node_modules/follow/Rakefile +54 -0
- data/server/node_modules/cradle/node_modules/follow/api.js +35 -0
- data/server/node_modules/cradle/node_modules/follow/browser/eventemitter2.js +453 -0
- data/server/node_modules/cradle/node_modules/follow/browser/export.js +78 -0
- data/server/node_modules/cradle/node_modules/follow/browser/index.html +14 -0
- data/server/node_modules/cradle/node_modules/follow/browser/jquery-1.6.1.min.js +18 -0
- data/server/node_modules/cradle/node_modules/follow/browser/log4js.js +46 -0
- data/server/node_modules/cradle/node_modules/follow/browser/main.js +92 -0
- data/server/node_modules/cradle/node_modules/follow/browser/querystring.js +28 -0
- data/server/node_modules/cradle/node_modules/follow/browser/request.jquery.js +237 -0
- data/server/node_modules/cradle/node_modules/follow/browser/require.js +33 -0
- data/server/node_modules/cradle/node_modules/follow/browser/util.js +28 -0
- data/server/node_modules/cradle/node_modules/follow/cli.js +101 -0
- data/server/node_modules/cradle/node_modules/follow/lib/feed.js +556 -0
- data/server/node_modules/cradle/node_modules/follow/lib/index.js +66 -0
- data/server/node_modules/cradle/node_modules/follow/lib/stream.js +305 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/LICENSE +55 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/README.md +285 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/main.js +618 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/mimetypes.js +146 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/oauth.js +34 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/package.json +42 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/googledoodle.png +0 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/run.sh +6 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/server.js +57 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-body.js +90 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-cookie.js +29 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-cookiejar.js +90 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-errors.js +30 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-oauth.js +109 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-pipes.js +167 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-proxy.js +39 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/tests/test-timeout.js +87 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/uuid.js +19 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/vendor/cookie/index.js +55 -0
- data/server/node_modules/cradle/node_modules/follow/node_modules/request/vendor/cookie/jar.js +72 -0
- data/server/node_modules/cradle/node_modules/follow/package.json +45 -0
- data/server/node_modules/cradle/node_modules/follow/test/couch.js +153 -0
- data/server/node_modules/cradle/node_modules/follow/test/follow.js +136 -0
- data/server/node_modules/cradle/node_modules/follow/test/issues.js +178 -0
- data/server/node_modules/cradle/node_modules/follow/test/issues/10.js +24 -0
- data/server/node_modules/cradle/node_modules/follow/test/stream.js +493 -0
- data/server/node_modules/cradle/node_modules/request/LICENSE +55 -0
- data/server/node_modules/cradle/node_modules/request/README.md +287 -0
- data/server/node_modules/cradle/node_modules/request/forever.js +103 -0
- data/server/node_modules/cradle/node_modules/request/main.js +913 -0
- data/server/node_modules/cradle/node_modules/request/mimetypes.js +152 -0
- data/server/node_modules/cradle/node_modules/request/oauth.js +34 -0
- data/server/node_modules/cradle/node_modules/request/package.json +42 -0
- data/server/node_modules/cradle/node_modules/request/tests/googledoodle.png +0 -0
- data/server/node_modules/cradle/node_modules/request/tests/run.js +38 -0
- data/server/node_modules/cradle/node_modules/request/tests/server.js +82 -0
- data/server/node_modules/cradle/node_modules/request/tests/squid.conf +77 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.cnf +20 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.crl +0 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.crt +17 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.csr +13 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.key +18 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/ca.srl +1 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.cnf +19 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.crt +16 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.csr +11 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.js +28 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/ca/server.key +9 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/npm-ca.crt +16 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/test.crt +15 -0
- data/server/node_modules/cradle/node_modules/request/tests/ssl/test.key +15 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-body.js +95 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-cookie.js +29 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-cookiejar.js +90 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-defaults.js +68 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-errors.js +37 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-headers.js +52 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-httpModule.js +94 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-https-strict.js +97 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-https.js +86 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-oauth.js +117 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-params.js +92 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-pipes.js +202 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-proxy.js +39 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-qs.js +28 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-redirect.js +154 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-timeout.js +87 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-toJSON.js +14 -0
- data/server/node_modules/cradle/node_modules/request/tests/test-tunnel.js +61 -0
- data/server/node_modules/cradle/node_modules/request/tunnel.js +229 -0
- data/server/node_modules/cradle/node_modules/request/uuid.js +19 -0
- data/server/node_modules/cradle/node_modules/request/vendor/cookie/index.js +65 -0
- data/server/node_modules/cradle/node_modules/request/vendor/cookie/jar.js +72 -0
- data/server/node_modules/cradle/node_modules/vargs/package.json +33 -10
- data/server/node_modules/cradle/package.json +50 -12
- data/server/node_modules/cradle/test/cache-test.js +1 -4
- data/server/node_modules/cradle/test/connection-test.js +179 -0
- data/server/node_modules/cradle/test/database-attachment-test.js +344 -0
- data/server/node_modules/cradle/test/database-cache-test.js +132 -0
- data/server/node_modules/cradle/test/database-test.js +219 -0
- data/server/node_modules/cradle/test/database-view-test.js +141 -0
- data/server/node_modules/cradle/test/fixtures/databases.json +28 -1
- data/server/node_modules/cradle/test/helpers/seed.js +14 -5
- data/server/node_modules/cradle/test/response-test.js +1 -1
- data/server/node_modules/express/History.md +16 -0
- data/server/node_modules/express/bin/express +7 -6
- data/server/node_modules/express/lib-cov/application.js +510 -0
- data/server/node_modules/express/lib-cov/express.js +65 -0
- data/server/node_modules/express/lib-cov/middleware.js +54 -0
- data/server/node_modules/express/lib-cov/request.js +225 -0
- data/server/node_modules/express/lib-cov/response.js +611 -0
- data/server/node_modules/express/lib-cov/router/collection.js +40 -0
- data/server/node_modules/express/lib-cov/router/index.js +515 -0
- data/server/node_modules/express/lib-cov/router/methods.js +9 -0
- data/server/node_modules/express/lib-cov/router/route.js +68 -0
- data/server/node_modules/express/lib-cov/utils.js +151 -0
- data/server/node_modules/express/lib-cov/view.js +81 -0
- data/server/node_modules/express/lib/express.js +1 -1
- data/server/node_modules/express/lib/http.js +1 -2
- data/server/node_modules/express/lib/request.js +2 -2
- data/server/node_modules/express/lib/router/methods.js +10 -1
- data/server/node_modules/express/node_modules/connect/lib/connect.js +1 -1
- data/server/node_modules/express/node_modules/connect/lib/http.js +3 -2
- data/server/node_modules/express/node_modules/connect/lib/middleware/limit.js +0 -2
- data/server/node_modules/express/node_modules/connect/lib/middleware/session.js +1 -2
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/Readme.md +42 -25
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/lib/incoming_form.js +1 -0
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/package.json +14 -3
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/legacy/simple/test-incoming-form.js +11 -0
- data/server/node_modules/express/node_modules/connect/package.json +35 -7
- data/server/node_modules/express/node_modules/mime/package.json +30 -8
- data/server/node_modules/express/node_modules/mkdirp/README.markdown +35 -2
- data/server/node_modules/express/node_modules/mkdirp/examples/pow.js +1 -1
- data/server/node_modules/express/node_modules/mkdirp/index.js +72 -13
- data/server/node_modules/express/node_modules/mkdirp/package.json +39 -21
- data/server/node_modules/express/node_modules/mkdirp/test/chmod.js +38 -0
- data/server/node_modules/express/node_modules/mkdirp/test/clobber.js +37 -0
- data/server/node_modules/express/node_modules/mkdirp/test/perm.js +32 -0
- data/server/node_modules/express/node_modules/mkdirp/test/perm_sync.js +39 -0
- data/server/node_modules/express/node_modules/mkdirp/test/sync.js +27 -0
- data/server/node_modules/express/node_modules/mkdirp/test/umask.js +28 -0
- data/server/node_modules/express/node_modules/mkdirp/test/umask_sync.js +27 -0
- data/server/node_modules/express/node_modules/qs/History.md +10 -0
- data/server/node_modules/express/node_modules/qs/Readme.md +9 -2
- data/server/node_modules/express/node_modules/qs/examples.js +3 -0
- data/server/node_modules/express/node_modules/qs/lib/querystring.js +8 -6
- data/server/node_modules/express/node_modules/qs/package.json +26 -8
- data/server/node_modules/express/node_modules/qs/test/parse.js +13 -1
- data/server/node_modules/express/node_modules/qs/test/stringify.js +45 -37
- data/server/node_modules/express/package.json +55 -16
- data/server/node_modules/express/test.js +41 -0
- data/server/node_modules/knox/package.json +26 -4
- data/server/node_modules/node-uuid/package.json +40 -11
- data/server/node_modules/node-uuid/test/test.js +1 -1
- data/server/node_modules/nodemon/README.md +120 -0
- data/server/node_modules/nodemon/nodemon.js +518 -0
- data/server/node_modules/nodemon/nodemonignore.example +11 -0
- data/server/node_modules/nodemon/package.json +49 -0
- data/server/node_modules/restler/README.md +144 -94
- data/server/node_modules/restler/lib/multipartform.js +2 -0
- data/server/node_modules/restler/lib/restler.js +218 -61
- data/server/node_modules/restler/package.json +35 -8
- data/server/node_modules/restler/test/all.js +6 -1
- data/server/node_modules/restler/test/restler.js +624 -118
- data/server/package.json +14 -10
- data/server/web.coffee +64 -0
- data/server/web.js +15 -3
- metadata +170 -57
- data/server/index.js +0 -14
- data/server/node_modules/connect-form/LICENSE +0 -22
- data/server/node_modules/connect-form/index.js +0 -100
- data/server/node_modules/connect-form/node_modules/formidable/test/fast/test-incoming-form.js +0 -45
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/no-filename/generic.http +0 -13
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +0 -26
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http +0 -24
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +0 -23
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +0 -24
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +0 -22
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +0 -22
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +0 -22
- data/server/node_modules/connect-form/node_modules/formidable/test/fixture/multi_video.upload +0 -0
- data/server/node_modules/cradle/Makefile +0 -10
- data/server/node_modules/cradle/test/cradle-test.js +0 -650
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/no-filename/generic.http +0 -13
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-chrome-13.http +0 -26
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-firefox-3.6.http +0 -24
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/osx-safari-5.http +0 -23
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-chrome-12.http +0 -24
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-7.http +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-ie-8.http +0 -22
- data/server/node_modules/express/node_modules/connect/node_modules/formidable/test/fixture/http/special-chars-in-filename/xp-safari-5.http +0 -22
- 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/test.js +0 -52
- data/server/node_modules/express/testing/foo/app.js +0 -35
- data/server/node_modules/express/testing/foo/package.json +0 -9
- data/server/node_modules/express/testing/foo/public/stylesheets/style.css +0 -8
- data/server/node_modules/express/testing/foo/routes/index.js +0 -10
- data/server/node_modules/express/testing/foo/views/index.jade +0 -2
- data/server/node_modules/express/testing/foo/views/layout.jade +0 -6
- data/server/node_modules/express/testing/index.js +0 -43
- data/server/node_modules/express/testing/public/test.txt +0 -2971
- data/server/node_modules/express/testing/views/page.html +0 -1
- data/server/node_modules/express/testing/views/page.jade +0 -3
- data/server/node_modules/express/testing/views/test.md +0 -1
- data/server/node_modules/express/testing/views/user/index.jade +0 -1
- data/server/node_modules/express/testing/views/user/list.jade +0 -1
- data/server/node_modules/knox/lib/knox/mime/index.js +0 -308
- data/server/node_modules/knox/lib/knox/mime/test.js +0 -59
- data/server/node_modules/node-uuid/test/benchmark-native +0 -0
- data/server/node_modules/on/index.js +0 -13
- data/server/node_modules/restler/test/test_helper.js +0 -163
- data/server/node_modules/spawner/index.js +0 -106
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nodemon",
|
|
3
|
+
"homepage": "http://github.com/remy/nodemon",
|
|
4
|
+
"author": {
|
|
5
|
+
"name": "Remy Sharp",
|
|
6
|
+
"url": "http://github.com/remy"
|
|
7
|
+
},
|
|
8
|
+
"bin": {
|
|
9
|
+
"nodemon": "./nodemon.js"
|
|
10
|
+
},
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "git://github.com/remy/nodemon.git"
|
|
14
|
+
},
|
|
15
|
+
"description": "Simple monitor script for use during development of a node.js app.",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"monitor",
|
|
18
|
+
"development",
|
|
19
|
+
"restart",
|
|
20
|
+
"autoload",
|
|
21
|
+
"reload",
|
|
22
|
+
"terminal"
|
|
23
|
+
],
|
|
24
|
+
"version": "0.6.18",
|
|
25
|
+
"preferGlobal": "true",
|
|
26
|
+
"licenses": [
|
|
27
|
+
{
|
|
28
|
+
"type": "MIT",
|
|
29
|
+
"url": "http://rem.mit-license.org"
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"main": "./nodemon",
|
|
33
|
+
"_npmUser": {
|
|
34
|
+
"name": "ddollar",
|
|
35
|
+
"email": "ddollar@gmail.com"
|
|
36
|
+
},
|
|
37
|
+
"_id": "nodemon@0.6.18",
|
|
38
|
+
"dependencies": {},
|
|
39
|
+
"devDependencies": {},
|
|
40
|
+
"optionalDependencies": {},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": "*"
|
|
43
|
+
},
|
|
44
|
+
"_engineSupported": true,
|
|
45
|
+
"_npmVersion": "1.1.21",
|
|
46
|
+
"_nodeVersion": "v0.6.17",
|
|
47
|
+
"_defaultsLoaded": true,
|
|
48
|
+
"_from": "nodemon@0.6.x"
|
|
49
|
+
}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
Restler
|
|
2
|
-
|
|
1
|
+
Restler
|
|
2
|
+
=======
|
|
3
3
|
|
|
4
4
|
(C) Dan Webb (dan@danwebb.net/@danwrong) 2011, Licensed under the MIT-LICENSE
|
|
5
5
|
|
|
6
|
-
An HTTP client library for node.js (0.
|
|
6
|
+
An HTTP client library for node.js (0.6.x and up). Hides most of the complexity of creating and using http.Client.
|
|
7
|
+
|
|
8
|
+
**Release 2.x.x** is dedicated to modifying how errors are handled and emitted. Currently errors are being fired as an on 'error' event but as [@ctavan](https://github.com/ctavan) pointed out on [issue #36](https://github.com/danwrong/restler/pull/36) a better approach (and more commonly in vogue now) would be to pass the error obj to the callback.
|
|
9
|
+
|
|
10
|
+
Ths change will inevitably affect those using older < 0.2.x versions of restler. Those not ready to upgrade yet are encouraged to stay on the 0.2.x version.
|
|
7
11
|
|
|
8
12
|
See [Version History](https://github.com/danwrong/restler/wiki/Version-History) for changes
|
|
9
13
|
|
|
@@ -21,7 +25,8 @@ Features
|
|
|
21
25
|
* Transparently handle SSL (just specify https in the URL)
|
|
22
26
|
* Deals with basic auth for you, just provide username and password options
|
|
23
27
|
* Simple service wrapper that allows you to easily put together REST API libraries
|
|
24
|
-
* Transparently handle content-encoded responses (gzip, deflate)
|
|
28
|
+
* Transparently handle content-encoded responses (gzip, deflate) (requires node 0.6+)
|
|
29
|
+
* Transparently handle different content charsets via [iconv](https://github.com/bnoordhuis/node-iconv) (if available)
|
|
25
30
|
|
|
26
31
|
|
|
27
32
|
API
|
|
@@ -29,18 +34,28 @@ API
|
|
|
29
34
|
|
|
30
35
|
### request(url, options)
|
|
31
36
|
|
|
32
|
-
Basic method to make a request of any type.
|
|
33
|
-
|
|
37
|
+
Basic method to make a request of any type. The function returns a RestRequest object that emits events:
|
|
38
|
+
|
|
39
|
+
#### events
|
|
40
|
+
|
|
41
|
+
* `complete: function(result, response)` - emitted when the request has finished whether it was successful or not. Gets passed the response result and the response object as arguments. If some error has occurred, `result` is always instance of `Error`, otherwise it contains response data.
|
|
42
|
+
* `success: function(data, response)` - emitted when the request was successful. Gets passed the response data and the response object as arguments.
|
|
43
|
+
* `fail: function(data, response)` - emitted when the request was successful, but 4xx status code returned. Gets passed the response data and the response object as arguments.
|
|
44
|
+
* `error: function(err, response)` - emitted when some errors have occurred (eg. connection aborted, parse, encoding, decoding failed or some other unhandled errors). Gets passed the `Error` object and the response object (when available) as arguments.
|
|
45
|
+
* `abort: function()` - emitted when `request.abort()` is called.
|
|
46
|
+
* `2XX`, `3XX`, `4XX`, `5XX: function(data, response)` - emitted for all requests with response codes in the range (eg. `2XX` emitted for 200, 201, 203).
|
|
47
|
+
* <code><i>actual response code</i>: function(data, response)</code> - emitted for every single response code (eg. 404, 201, etc).
|
|
48
|
+
|
|
49
|
+
#### members
|
|
50
|
+
|
|
51
|
+
* `abort([error])` Cancels request. `abort` event is emitted. `request.aborted` is set to `true`. If non-falsy `error` is passed, then `error` will be additionaly emitted (with `error` passed as a param and `error.type` is set to `"abort"`). Otherwise only `complete` event will raise.
|
|
52
|
+
* `retry([timeout])` Re-sends request after `timeout` ms. Pending request is aborted.
|
|
53
|
+
* `aborted` Determines if request was aborted.
|
|
34
54
|
|
|
35
|
-
* _complete_ emitted when the request has finished whether it was successful or not. Gets passed the response data and the response as arguments.
|
|
36
|
-
* _success_ emitted when the request was successful. Gets passed the response data and the response as arguments.
|
|
37
|
-
* _error_ emitted when the request was unsuccessful. Gets passed the response data and the response as arguments.
|
|
38
|
-
* _2XX, 3XX, 4XX, 5XX etc_ emitted for all requests with response codes in the range. Eg. 2XX emitted for 200, 201, 203
|
|
39
|
-
* _actual response code_ there is an event emitted for every single response code. eg. 404, 201, etc.
|
|
40
55
|
|
|
41
56
|
### get(url, options)
|
|
42
57
|
|
|
43
|
-
Create a GET request.
|
|
58
|
+
Create a GET request.
|
|
44
59
|
|
|
45
60
|
### post(url, options)
|
|
46
61
|
|
|
@@ -54,107 +69,142 @@ Create a PUT request.
|
|
|
54
69
|
|
|
55
70
|
Create a DELETE request.
|
|
56
71
|
|
|
57
|
-
###
|
|
72
|
+
### head(url, options)
|
|
73
|
+
|
|
74
|
+
Create a HEAD request.
|
|
75
|
+
|
|
76
|
+
### json(url, data, options)
|
|
77
|
+
|
|
78
|
+
Send json `data` via GET method.
|
|
79
|
+
|
|
80
|
+
### postJson(url, data, options)
|
|
81
|
+
|
|
82
|
+
Send json `data` via POST method.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
### Parsers
|
|
58
86
|
|
|
59
87
|
You can give any of these to the parsers option to specify how the response data is deserialized.
|
|
88
|
+
In case of malformed content, parsers emit `error` event. Original data returned by server is stored in `response.raw`.
|
|
60
89
|
|
|
61
90
|
#### parsers.auto
|
|
62
91
|
|
|
63
|
-
Checks the content-type and then uses parsers.xml, parsers.json or parsers.yaml.
|
|
92
|
+
Checks the content-type and then uses parsers.xml, parsers.json or parsers.yaml.
|
|
64
93
|
If the content type isn't recognised it just returns the data untouched.
|
|
65
94
|
|
|
66
95
|
#### parsers.json, parsers.xml, parsers.yaml
|
|
67
96
|
|
|
68
97
|
All of these attempt to turn the response into a JavaScript object. In order to use the YAML and XML parsers you must have yaml and/or xml2js installed.
|
|
69
98
|
|
|
70
|
-
###
|
|
71
|
-
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
Note that if you want your request body to be JSON with the Content-Type
|
|
76
|
-
JSON.stringify your object first. Otherwise, it will be sent as `application/x-www-form-urlencoded` and encoded accordingly.
|
|
77
|
-
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
99
|
+
### Options
|
|
100
|
+
|
|
101
|
+
* `method` Request method, can be get, post, put, del. Defaults to `"get"`.
|
|
102
|
+
* `query` Query string variables as a javascript object, will override the querystring in the URL. Defaults to empty.
|
|
103
|
+
* `data` The data to be added to the body of the request. Can be a string or any object.
|
|
104
|
+
Note that if you want your request body to be JSON with the `Content-Type: application/json`, you need to
|
|
105
|
+
`JSON.stringify` your object first. Otherwise, it will be sent as `application/x-www-form-urlencoded` and encoded accordingly.
|
|
106
|
+
Also you can use `json()` and `postJson()` methods.
|
|
107
|
+
* `parser` A function that will be called on the returned data. Use any of predefined `restler.parsers`. See parsers section below. Defaults to `restler.parsers.auto`.
|
|
108
|
+
* `encoding` The encoding of the request body. Defaults to `"utf8"`.
|
|
109
|
+
* `decoding` The encoding of the response body. For a list of supported values see [Buffers](http://nodejs.org/docs/latest/api/buffers.html#buffers). Additionally accepts `"buffer"` - returns response as `Buffer`. Defaults to `"utf8"`.
|
|
110
|
+
* `headers` A hash of HTTP headers to be sent. Defaults to `{ 'Accept': '*/*', 'User-Agent': 'Restler for node.js' }`.
|
|
111
|
+
* `username` Basic auth username. Defaults to empty.
|
|
112
|
+
* `password` Basic auth password. Defaults to empty.
|
|
113
|
+
* `multipart` If set the data passed will be formated as `multipart/form-encoded`. See multipart example below. Defaults to `false`.
|
|
114
|
+
* `client` A http.Client instance if you want to reuse or implement some kind of connection pooling. Defaults to empty.
|
|
115
|
+
* `followRedirects` If set will recursively follow redirects. Defaults to `true`.
|
|
86
116
|
|
|
87
117
|
|
|
88
118
|
Example usage
|
|
89
119
|
-------------
|
|
90
120
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
121
|
+
```javascript
|
|
122
|
+
var sys = require('util'),
|
|
123
|
+
rest = require('./restler');
|
|
124
|
+
|
|
125
|
+
rest.get('http://google.com').on('complete', function(result) {
|
|
126
|
+
if (result instanceof Error) {
|
|
127
|
+
sys.puts('Error: ' + result.message);
|
|
128
|
+
this.retry(5000); // try again after 5 sec
|
|
129
|
+
} else {
|
|
130
|
+
sys.puts(result);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
rest.get('http://twaud.io/api/v1/users/danwrong.json').on('complete', function(data) {
|
|
135
|
+
sys.puts(data[0].message); // auto convert to object
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
rest.get('http://twaud.io/api/v1/users/danwrong.xml').on('complete', function(data) {
|
|
139
|
+
sys.puts(data[0].sounds[0].sound[0].message); // auto convert to object
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
rest.post('http://user:pass@service.com/action', {
|
|
143
|
+
data: { id: 334 },
|
|
144
|
+
}).on('complete', function(data, response) {
|
|
145
|
+
if (response.statusCode == 201) {
|
|
146
|
+
// you can get at the raw response like this...
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// multipart request sending a 321567 byte long file using https
|
|
151
|
+
rest.post('https://twaud.io/api/v1/upload.json', {
|
|
152
|
+
multipart: true,
|
|
153
|
+
username: 'danwrong',
|
|
154
|
+
password: 'wouldntyouliketoknow',
|
|
155
|
+
data: {
|
|
156
|
+
'sound[message]': 'hello from restler!',
|
|
157
|
+
'sound[file]': rest.file('doug-e-fresh_the-show.mp3', null, 321567, null, 'audio/mpeg')
|
|
158
|
+
}
|
|
159
|
+
}).on('complete', function(data) {
|
|
160
|
+
sys.puts(data.audio_url);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// create a service constructor for very easy API wrappers a la HTTParty...
|
|
164
|
+
Twitter = rest.service(function(u, p) {
|
|
165
|
+
this.defaults.username = u;
|
|
166
|
+
this.defaults.password = p;
|
|
167
|
+
}, {
|
|
168
|
+
baseURL: 'http://twitter.com'
|
|
169
|
+
}, {
|
|
170
|
+
update: function(message) {
|
|
171
|
+
return this.post('/statuses/update.json', { data: { status: message } });
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
var client = new Twitter('danwrong', 'password');
|
|
176
|
+
client.update('Tweeting using a Restler service thingy').on('complete', function(data) {
|
|
177
|
+
sys.p(data);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// post JSON
|
|
181
|
+
var jsonData = { id: 334 };
|
|
182
|
+
rest.postJson('http://example.com/action', jsonData).on('complete', function(data, response) {
|
|
183
|
+
// handle response
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
|
|
152
188
|
Running the tests
|
|
153
189
|
-----------------
|
|
190
|
+
install **[nodeunit](https://github.com/caolan/nodeunit)**
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npm install nodeunit
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
then
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
node test/all.js
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
or
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
nodeunit test/restler.js
|
|
206
|
+
```
|
|
154
207
|
|
|
155
|
-
node test/restler.js
|
|
156
|
-
|
|
157
208
|
TODO
|
|
158
209
|
----
|
|
159
|
-
* Deal with no utf-8 response bodies
|
|
160
210
|
* What do you need? Let me know or fork.
|
|
@@ -87,6 +87,8 @@ Part.prototype = {
|
|
|
87
87
|
valueSize = this.value.fileSize;
|
|
88
88
|
} else if (this.value.data) {
|
|
89
89
|
valueSize = this.value.data.length;
|
|
90
|
+
} else if (typeof this.value === 'number') {
|
|
91
|
+
valueSize = this.value.toString().length;
|
|
90
92
|
} else {
|
|
91
93
|
valueSize = this.value.length;
|
|
92
94
|
}
|
|
@@ -1,19 +1,29 @@
|
|
|
1
|
-
var sys = require('util')
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
var sys = require('util');
|
|
2
|
+
var http = require('http');
|
|
3
|
+
var https = require('https');
|
|
4
|
+
var url = require('url');
|
|
5
|
+
var qs = require('querystring');
|
|
6
|
+
var multipart = require('./multipartform');
|
|
7
|
+
var zlib = null;
|
|
8
|
+
var Iconv = null;
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
zlib = require('zlib');
|
|
12
|
+
} catch (err) {}
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
Iconv = require('iconv').Iconv;
|
|
16
|
+
} catch (err) {}
|
|
17
|
+
|
|
9
18
|
function mixin(target, source) {
|
|
19
|
+
source = source || {};
|
|
10
20
|
Object.keys(source).forEach(function(key) {
|
|
11
21
|
target[key] = source[key];
|
|
12
22
|
});
|
|
13
23
|
|
|
14
24
|
return target;
|
|
15
25
|
}
|
|
16
|
-
|
|
26
|
+
|
|
17
27
|
function Request(uri, options) {
|
|
18
28
|
this.url = url.parse(uri);
|
|
19
29
|
this.options = options;
|
|
@@ -22,6 +32,10 @@ function Request(uri, options) {
|
|
|
22
32
|
'User-Agent': 'Restler for node.js',
|
|
23
33
|
'Host': this.url.host
|
|
24
34
|
};
|
|
35
|
+
|
|
36
|
+
if (zlib) {
|
|
37
|
+
this.headers['Accept-Encoding'] = 'gzip, deflate';
|
|
38
|
+
}
|
|
25
39
|
|
|
26
40
|
mixin(this.headers, options.headers || {});
|
|
27
41
|
|
|
@@ -41,6 +55,13 @@ function Request(uri, options) {
|
|
|
41
55
|
|
|
42
56
|
if (this.options.multipart) {
|
|
43
57
|
this.headers['Content-Type'] = 'multipart/form-data; boundary=' + multipart.defaultBoundary;
|
|
58
|
+
var multipart_size = multipart.sizeOf(this.options.data, multipart.defaultBoundary);
|
|
59
|
+
if (typeof multipart_size === 'number' && multipart_size === multipart_size) {
|
|
60
|
+
this.headers['Content-Length'] = multipart_size;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
console.log("Building multipart request without Content-Length header, please specify all file sizes");
|
|
64
|
+
}
|
|
44
65
|
} else {
|
|
45
66
|
if (typeof this.options.data == 'object') {
|
|
46
67
|
this.options.data = qs.stringify(this.options.data);
|
|
@@ -96,14 +117,14 @@ mixin(Request.prototype, {
|
|
|
96
117
|
_responseHandler: function(response) {
|
|
97
118
|
var self = this;
|
|
98
119
|
|
|
99
|
-
if (
|
|
120
|
+
if (self._isRedirect(response) && self.options.followRedirects) {
|
|
100
121
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
self.
|
|
122
|
+
self.url = url.parse(url.resolve(self.url.href, response.headers['location']));
|
|
123
|
+
self._retry();
|
|
124
|
+
// todo handle somehow infinite redirects
|
|
125
|
+
} catch(err) {
|
|
126
|
+
err.message = 'Failed to follow redirect: ' + err.message;
|
|
127
|
+
self._fireError(err, response);
|
|
107
128
|
}
|
|
108
129
|
} else {
|
|
109
130
|
var body = '';
|
|
@@ -115,62 +136,96 @@ mixin(Request.prototype, {
|
|
|
115
136
|
});
|
|
116
137
|
|
|
117
138
|
response.on('end', function() {
|
|
139
|
+
response.rawEncoded = body;
|
|
118
140
|
self._decode(new Buffer(body, 'binary'), response, function(err, body) {
|
|
119
141
|
if (err) {
|
|
120
|
-
self.
|
|
142
|
+
self._fireError(err, response);
|
|
121
143
|
return;
|
|
122
144
|
}
|
|
123
|
-
|
|
124
|
-
|
|
145
|
+
response.raw = body;
|
|
146
|
+
body = self._iconv(body, response);
|
|
147
|
+
self._encode(body, response, function(err, body) {
|
|
148
|
+
if (err) {
|
|
149
|
+
self._fireError(err, response);
|
|
150
|
+
} else {
|
|
151
|
+
self._fireSuccess(body, response);
|
|
152
|
+
}
|
|
125
153
|
});
|
|
126
154
|
});
|
|
127
155
|
});
|
|
128
156
|
}
|
|
129
157
|
},
|
|
130
158
|
_decode: function(body, response, callback) {
|
|
131
|
-
var
|
|
132
|
-
if (
|
|
133
|
-
decoders[
|
|
159
|
+
var decoder = response.headers['content-encoding'];
|
|
160
|
+
if (decoder in decoders) {
|
|
161
|
+
decoders[decoder].call(response, body, callback);
|
|
134
162
|
} else {
|
|
135
163
|
callback(null, body);
|
|
136
164
|
}
|
|
137
165
|
},
|
|
166
|
+
_iconv: function(body, response) {
|
|
167
|
+
if (Iconv) {
|
|
168
|
+
var charset = response.headers['content-type'];
|
|
169
|
+
if (charset) {
|
|
170
|
+
charset = /\bcharset=(.+)(?:;|$)/i.exec(charset);
|
|
171
|
+
if (charset) {
|
|
172
|
+
charset = charset[1].trim().toUpperCase();
|
|
173
|
+
if (charset != 'UTF-8') {
|
|
174
|
+
try {
|
|
175
|
+
var iconv = new Iconv(charset, 'UTF-8//TRANSLIT//IGNORE');
|
|
176
|
+
return iconv.convert(body);
|
|
177
|
+
} catch (err) {}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return body;
|
|
183
|
+
},
|
|
138
184
|
_encode: function(body, response, callback) {
|
|
139
185
|
var self = this;
|
|
140
186
|
if (self.options.decoding == 'buffer') {
|
|
141
|
-
callback(body);
|
|
187
|
+
callback(null, body);
|
|
142
188
|
} else {
|
|
143
189
|
body = body.toString(self.options.decoding);
|
|
144
190
|
if (self.options.parser) {
|
|
145
191
|
self.options.parser.call(response, body, callback);
|
|
146
192
|
} else {
|
|
147
|
-
callback(body);
|
|
193
|
+
callback(null, body);
|
|
148
194
|
}
|
|
149
195
|
}
|
|
150
196
|
},
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
197
|
+
_fireError: function(err, response) {
|
|
198
|
+
this.emit('error', err, response);
|
|
199
|
+
this.emit('complete', err, response);
|
|
200
|
+
},
|
|
201
|
+
_fireSuccess: function(body, response) {
|
|
202
|
+
if (parseInt(response.statusCode) >= 400) {
|
|
203
|
+
this.emit('fail', body, response);
|
|
154
204
|
} else {
|
|
155
|
-
this.emit(
|
|
205
|
+
this.emit('success', body, response);
|
|
156
206
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
else this._respond('success', body, response);
|
|
161
|
-
|
|
162
|
-
this._respond(response.statusCode.toString().replace(/\d{2}$/, 'XX'), body, response);
|
|
163
|
-
this._respond(response.statusCode.toString(), body, response);
|
|
164
|
-
this._respond('complete', body, response);
|
|
207
|
+
this.emit(response.statusCode.toString().replace(/\d{2}$/, 'XX'), body, response);
|
|
208
|
+
this.emit(response.statusCode.toString(), body, response);
|
|
209
|
+
this.emit('complete', body, response);
|
|
165
210
|
},
|
|
166
211
|
_makeRequest: function() {
|
|
167
212
|
var self = this;
|
|
168
|
-
|
|
169
213
|
this.request.on('response', function(response) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
214
|
+
self.emit('response', response);
|
|
215
|
+
self._responseHandler(response);
|
|
216
|
+
}).on('error', function(err) {
|
|
217
|
+
if (!self.aborted) {
|
|
218
|
+
self._fireError(err, null);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
},
|
|
222
|
+
_retry: function() {
|
|
223
|
+
this.request.removeAllListeners().on('error', function() {});
|
|
224
|
+
if (this.request.finished) {
|
|
225
|
+
this.request.abort();
|
|
226
|
+
}
|
|
227
|
+
Request.call(this, this.url.href, this.options); // reusing request object to handle recursive calls and remember listeners
|
|
228
|
+
this.run();
|
|
174
229
|
},
|
|
175
230
|
run: function() {
|
|
176
231
|
var self = this;
|
|
@@ -186,6 +241,44 @@ mixin(Request.prototype, {
|
|
|
186
241
|
this.request.end();
|
|
187
242
|
}
|
|
188
243
|
|
|
244
|
+
return this;
|
|
245
|
+
},
|
|
246
|
+
abort: function(err) {
|
|
247
|
+
var self = this;
|
|
248
|
+
|
|
249
|
+
if (err) {
|
|
250
|
+
if (typeof err == 'string') {
|
|
251
|
+
err = new Error(err);
|
|
252
|
+
} else if (!(err instanceof Error)) {
|
|
253
|
+
err = new Error('AbortError');
|
|
254
|
+
}
|
|
255
|
+
err.type = 'abort';
|
|
256
|
+
} else {
|
|
257
|
+
err = null;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
self.request.on('close', function() {
|
|
261
|
+
if (err) {
|
|
262
|
+
self._fireError(err, null);
|
|
263
|
+
} else {
|
|
264
|
+
self.emit('complete', null, null);
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
self.aborted = true;
|
|
269
|
+
self.request.abort();
|
|
270
|
+
self.emit('abort', err);
|
|
271
|
+
return this;
|
|
272
|
+
},
|
|
273
|
+
retry: function(timeout) {
|
|
274
|
+
var self = this;
|
|
275
|
+
timeout = parseInt(timeout);
|
|
276
|
+
var fn = self._retry.bind(self);
|
|
277
|
+
if (!isFinite(timeout) || timeout <= 0) {
|
|
278
|
+
process.nextTick(fn, timeout);
|
|
279
|
+
} else {
|
|
280
|
+
setTimeout(fn, timeout);
|
|
281
|
+
}
|
|
189
282
|
return this;
|
|
190
283
|
}
|
|
191
284
|
});
|
|
@@ -199,14 +292,19 @@ function shortcutOptions(options, method) {
|
|
|
199
292
|
|
|
200
293
|
function request(url, options) {
|
|
201
294
|
var request = new Request(url, options);
|
|
202
|
-
request.on('error', function() {});
|
|
203
|
-
|
|
295
|
+
request.on('error', function() {});
|
|
296
|
+
process.nextTick(request.run.bind(request));
|
|
297
|
+
return request;
|
|
204
298
|
}
|
|
205
299
|
|
|
206
300
|
function get(url, options) {
|
|
207
301
|
return request(url, shortcutOptions(options, 'GET'));
|
|
208
302
|
}
|
|
209
303
|
|
|
304
|
+
function patch(url, options) {
|
|
305
|
+
return request(url, shortcutOptions(options, 'PATCH'));
|
|
306
|
+
}
|
|
307
|
+
|
|
210
308
|
function post(url, options) {
|
|
211
309
|
return request(url, shortcutOptions(options, 'POST'));
|
|
212
310
|
}
|
|
@@ -219,23 +317,66 @@ function del(url, options) {
|
|
|
219
317
|
return request(url, shortcutOptions(options, 'DELETE'));
|
|
220
318
|
}
|
|
221
319
|
|
|
320
|
+
function head(url, options) {
|
|
321
|
+
return request(url, shortcutOptions(options, 'HEAD'));
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function json(url, data, options, method) {
|
|
325
|
+
options = options || {};
|
|
326
|
+
options.parser = (typeof options.parser !== "undefined") ? options.parser : parsers.auto;
|
|
327
|
+
options.headers = options.headers || {};
|
|
328
|
+
options.headers['content-type'] = 'application/json';
|
|
329
|
+
options.data = JSON.stringify(data);
|
|
330
|
+
options.method = method || 'GET';
|
|
331
|
+
return request(url, options);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function postJson(url, data, options) {
|
|
335
|
+
return json(url, data, options, 'POST');
|
|
336
|
+
}
|
|
337
|
+
|
|
222
338
|
var parsers = {
|
|
223
339
|
auto: function(data, callback) {
|
|
224
340
|
var contentType = this.headers['content-type'];
|
|
225
|
-
|
|
341
|
+
var contentParser;
|
|
226
342
|
if (contentType) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
343
|
+
contentType = contentType.replace(/;.+/, ''); // remove all except mime type (eg. text/html; charset=UTF-8)
|
|
344
|
+
if (contentType in parsers.auto.matchers) {
|
|
345
|
+
contentParser = parsers.auto.matchers[contentType];
|
|
346
|
+
} else {
|
|
347
|
+
// custom (vendor) mime types
|
|
348
|
+
var parts = contentType.match(/^([\w-]+)\/vnd((?:\.(?:[\w-]+))+)\+([\w-]+)$/i);
|
|
349
|
+
if (parts) {
|
|
350
|
+
var type = parts[1];
|
|
351
|
+
var vendors = parts[2].substr(1).split('.');
|
|
352
|
+
var subtype = parts[3];
|
|
353
|
+
var vendorType;
|
|
354
|
+
while (vendors.pop() && !(vendorType in parsers.auto.matchers)) {
|
|
355
|
+
vendorType = vendors.length
|
|
356
|
+
? type + '/vnd.' + vendors.join('.') + '+' + subtype
|
|
357
|
+
: vendorType = type + '/' + subtype;
|
|
358
|
+
}
|
|
359
|
+
contentParser = parsers.auto.matchers[vendorType];
|
|
231
360
|
}
|
|
232
361
|
}
|
|
233
362
|
}
|
|
234
|
-
|
|
235
|
-
|
|
363
|
+
if (typeof contentParser == 'function') {
|
|
364
|
+
contentParser.call(this, data, callback);
|
|
365
|
+
} else {
|
|
366
|
+
callback(null, data);
|
|
367
|
+
}
|
|
236
368
|
},
|
|
237
369
|
json: function(data, callback) {
|
|
238
|
-
|
|
370
|
+
if (data && data.length) {
|
|
371
|
+
try {
|
|
372
|
+
callback(null, JSON.parse(data));
|
|
373
|
+
} catch (err) {
|
|
374
|
+
err.message = 'Failed to parse JSON body: ' + err.message;
|
|
375
|
+
callback(err, null);
|
|
376
|
+
}
|
|
377
|
+
} else {
|
|
378
|
+
callback(null, null);
|
|
379
|
+
}
|
|
239
380
|
}
|
|
240
381
|
};
|
|
241
382
|
|
|
@@ -247,7 +388,16 @@ try {
|
|
|
247
388
|
var yaml = require('yaml');
|
|
248
389
|
|
|
249
390
|
parsers.yaml = function(data, callback) {
|
|
250
|
-
|
|
391
|
+
if (data) {
|
|
392
|
+
try {
|
|
393
|
+
callback(null, yaml.eval(data));
|
|
394
|
+
} catch (err) {
|
|
395
|
+
err.message = 'Failed to parse YAML body: ' + err.message;
|
|
396
|
+
callback(err, null);
|
|
397
|
+
}
|
|
398
|
+
} else {
|
|
399
|
+
callback(null, null);
|
|
400
|
+
}
|
|
251
401
|
};
|
|
252
402
|
|
|
253
403
|
parsers.auto.matchers['application/yaml'] = parsers.yaml;
|
|
@@ -259,17 +409,14 @@ try {
|
|
|
259
409
|
parsers.xml = function(data, callback) {
|
|
260
410
|
if (data) {
|
|
261
411
|
var parser = new xml2js.Parser();
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
412
|
+
parser.parseString(data, function(err, data) {
|
|
413
|
+
if (err) {
|
|
414
|
+
err.message = 'Failed to parse XML body: ' + err.message;
|
|
415
|
+
}
|
|
416
|
+
callback(err, data);
|
|
265
417
|
});
|
|
266
|
-
try {
|
|
267
|
-
parser.parseString(data);
|
|
268
|
-
} catch (e) {
|
|
269
|
-
callback({error:'Oops, something went wrong.'});
|
|
270
|
-
}
|
|
271
418
|
} else {
|
|
272
|
-
callback();
|
|
419
|
+
callback(null, null);
|
|
273
420
|
}
|
|
274
421
|
};
|
|
275
422
|
|
|
@@ -302,12 +449,18 @@ mixin(Service.prototype, {
|
|
|
302
449
|
get: function(path, options) {
|
|
303
450
|
return get(this._url(path), this._withDefaults(options));
|
|
304
451
|
},
|
|
452
|
+
patch: function(path, options) {
|
|
453
|
+
return patch(this._url(path), this._withDefaults(options));
|
|
454
|
+
},
|
|
305
455
|
put: function(path, options) {
|
|
306
456
|
return put(this._url(path), this._withDefaults(options));
|
|
307
457
|
},
|
|
308
458
|
post: function(path, options) {
|
|
309
459
|
return post(this._url(path), this._withDefaults(options));
|
|
310
460
|
},
|
|
461
|
+
json: function(method, path, data, options) {
|
|
462
|
+
return json(this._url(path), data, this._withDefaults(options), method);
|
|
463
|
+
},
|
|
311
464
|
del: function(path, options) {
|
|
312
465
|
return del(this._url(path), this._withDefaults(options));
|
|
313
466
|
},
|
|
@@ -333,9 +486,13 @@ mixin(exports, {
|
|
|
333
486
|
request: request,
|
|
334
487
|
service: service,
|
|
335
488
|
get: get,
|
|
489
|
+
patch: patch,
|
|
336
490
|
post: post,
|
|
337
491
|
put: put,
|
|
338
492
|
del: del,
|
|
493
|
+
head: head,
|
|
494
|
+
json: json,
|
|
495
|
+
postJson: postJson,
|
|
339
496
|
parsers: parsers,
|
|
340
497
|
file: multipart.file,
|
|
341
498
|
data: multipart.data
|