node-pre-gyp
Advanced tools
Comparing version 0.5.29 to 0.5.30
# node-pre-gyp changelog | ||
## 0.5.30 | ||
- Repackaged with latest bundled deps | ||
## 0.5.29 | ||
@@ -4,0 +8,0 @@ |
@@ -65,4 +65,3 @@ { | ||
"_shasum": "857fcabfc3397d2625b8228262e86aa7a011b05d", | ||
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz" | ||
} |
@@ -56,4 +56,3 @@ { | ||
"_shasum": "1d73076a6df986cd9344e15e71fcc05a4c9abf12", | ||
"_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz" | ||
} |
@@ -44,4 +44,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.5.tgz" | ||
} |
@@ -55,4 +55,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.1.tgz" | ||
} |
@@ -52,4 +52,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.0.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/ansi/-/ansi-0.3.0.tgz" | ||
} |
@@ -49,4 +49,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/npmlog/-/npmlog-0.1.1.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/npmlog/-/npmlog-0.1.1.tgz" | ||
} |
@@ -12,4 +12,4 @@ #! /usr/bin/env node | ||
module.exports = function (name, defaults, argv) { | ||
if(!name) | ||
throw new Error('nameless configuration fail') | ||
if('string' !== typeof name) | ||
throw new Error('rc(name): name *must* be string') | ||
if(!argv) | ||
@@ -16,0 +16,0 @@ argv = require('minimist')(process.argv.slice(2)) |
@@ -57,4 +57,3 @@ { | ||
"_shasum": "7a16ba69729132340506170494bc83f7076fe08f", | ||
"_resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.2.11.tgz" | ||
} |
@@ -44,8 +44,3 @@ { | ||
"_shasum": "4e808c2ce144c6c1788918e034d6797bc6cf6281", | ||
"_resolved": "https://registry.npmjs.org/ini/-/ini-1.1.0.tgz", | ||
"bugs": { | ||
"url": "https://github.com/isaacs/ini/issues" | ||
}, | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/isaacs/ini" | ||
"_resolved": "https://registry.npmjs.org/ini/-/ini-1.1.0.tgz" | ||
} |
@@ -65,4 +65,3 @@ { | ||
"_shasum": "de3f98543dbf96082be48ad1a0c7cda836301dcf", | ||
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz" | ||
} |
@@ -75,4 +75,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz" | ||
} |
{ | ||
"name": "rc", | ||
"version": "0.5.1", | ||
"version": "0.5.2", | ||
"description": "hardwired configuration loader", | ||
@@ -39,3 +39,3 @@ "main": "index.js", | ||
}, | ||
"gitHead": "24cc92c2f9c6d7193c283bc6be7164d6fa4fcf23", | ||
"gitHead": "7b07492852a07de465547bb1a3bad0fec75fb4b1", | ||
"bugs": { | ||
@@ -45,4 +45,4 @@ "url": "https://github.com/dominictarr/rc/issues" | ||
"homepage": "https://github.com/dominictarr/rc", | ||
"_id": "rc@0.5.1", | ||
"_shasum": "b88ef9421a08151352a659e0c3a58c4b82eb7576", | ||
"_id": "rc@0.5.2", | ||
"_shasum": "6b8e05894a158e3d4a15e7daddb970f4d15a024f", | ||
"_from": "rc@~0.5.1", | ||
@@ -61,8 +61,7 @@ "_npmVersion": "1.4.26", | ||
"dist": { | ||
"shasum": "b88ef9421a08151352a659e0c3a58c4b82eb7576", | ||
"tarball": "http://registry.npmjs.org/rc/-/rc-0.5.1.tgz" | ||
"shasum": "6b8e05894a158e3d4a15e7daddb970f4d15a024f", | ||
"tarball": "http://registry.npmjs.org/rc/-/rc-0.5.2.tgz" | ||
}, | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/rc/-/rc-0.5.1.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/rc/-/rc-0.5.2.tgz" | ||
} |
@@ -7,3 +7,5 @@ # This is an OPEN Open Source Project | ||
Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project. | ||
Individuals making significant and valuable contributions are given | ||
commit-access to the project to contribute as they see fit. This project is | ||
more like an open wiki than a standard guarded open source project. | ||
@@ -16,6 +18,17 @@ ## Rules | ||
1. **Non-master branches** ought to be used for ongoing work. | ||
1. **External API changes and significant modifications** ought to be subject to an **internal pull-request** to solicit feedback from other contributors. | ||
1. Internal pull-requests to solicit feedback are *encouraged* for any other non-trivial contribution but left to the discretion of the contributor. | ||
1. For significant changes wait a full 24 hours before merging so that active contributors who are distributed throughout the world have a chance to weigh in. | ||
1. **External API changes and significant modifications** ought to be subject | ||
to an **internal pull-request** to solicit feedback from other contributors. | ||
1. Internal pull-requests to solicit feedback are *encouraged* for any other | ||
non-trivial contribution but left to the discretion of the contributor. | ||
1. For significant changes wait a full 24 hours before merging so that active | ||
contributors who are distributed throughout the world have a chance to weigh | ||
in. | ||
1. Contributors should attempt to adhere to the prevailing code-style. | ||
1. Run `npm test` locally before submitting your PR, to catch any easy to miss | ||
style & testing issues. To diagnose test failures, there are two ways to | ||
run a single test file: | ||
- `node_modules/.bin/taper tests/test-file.js` - run using the default | ||
[`taper`](/nylen/taper) test reporter. | ||
- `node tests/test-file.js` - view the raw | ||
[tap](https://testanything.org/) output. | ||
@@ -29,4 +42,6 @@ | ||
This is an experiment and feedback is welcome! This document may also be subject to pull-requests or changes by contributors where you believe you have something valuable to add or change. | ||
This is an experiment and feedback is welcome! This document may also be | ||
subject to pull-requests or changes by contributors where you believe you have | ||
something valuable to add or change. | ||
----------------------------------------- |
@@ -15,3 +15,3 @@ // Copyright 2010-2012 Mikeal Rogers | ||
'use strict'; | ||
'use strict' | ||
@@ -21,3 +21,4 @@ var extend = require('util')._extend | ||
, helpers = require('./lib/helpers') | ||
, isFunction = helpers.isFunction | ||
var isFunction = helpers.isFunction | ||
, constructObject = helpers.constructObject | ||
@@ -27,4 +28,4 @@ , filterForCallback = helpers.filterForCallback | ||
, paramsHaveRequestBody = helpers.paramsHaveRequestBody | ||
; | ||
// organize params for patch, post, put, head, del | ||
@@ -43,4 +44,5 @@ function initParams(uri, options, callback) { | ||
function request (uri, options, callback) { | ||
if (typeof uri === 'undefined') | ||
if (typeof uri === 'undefined') { | ||
throw new Error('undefined is not a valid uri or options object.') | ||
} | ||
@@ -56,4 +58,5 @@ var params = initParams(uri, options, callback) | ||
function requester(params) { | ||
if(typeof params.options._requester === 'function') | ||
if(typeof params.options._requester === 'function') { | ||
return params.options._requester | ||
} | ||
return request | ||
@@ -72,4 +75,5 @@ } | ||
if (paramsHaveRequestBody(params)) | ||
throw new Error("HTTP HEAD requests MUST NOT include a request body.") | ||
if (paramsHaveRequestBody(params)) { | ||
throw new Error('HTTP HEAD requests MUST NOT include a request body.') | ||
} | ||
@@ -103,4 +107,4 @@ return requester(params)(params.uri || null, params.options, params.callback) | ||
request.jar = function () { | ||
return cookies.jar() | ||
request.jar = function (store) { | ||
return cookies.jar(store) | ||
} | ||
@@ -132,4 +136,5 @@ | ||
if (options.headers) | ||
if (options.headers) { | ||
params.options.headers = getHeaders(params, options) | ||
} | ||
@@ -163,4 +168,8 @@ if (isFunction(requester)) { | ||
var options = constructObject() | ||
if (optionsArg) options.extend(optionsArg) | ||
if (agentOptions) options.agentOptions = agentOptions | ||
if (optionsArg) { | ||
options.extend(optionsArg) | ||
} | ||
if (agentOptions) { | ||
options.agentOptions = agentOptions | ||
} | ||
@@ -167,0 +176,0 @@ options.extend({forever: true}) |
@@ -1,42 +0,39 @@ | ||
'use strict'; | ||
'use strict' | ||
var optional = require('./optional') | ||
, tough = optional('tough-cookie') | ||
, Cookie = tough && tough.Cookie | ||
, CookieJar = tough && tough.CookieJar | ||
; | ||
var tough = require('tough-cookie') | ||
var Cookie = tough.Cookie | ||
, CookieJar = tough.CookieJar | ||
exports.parse = function(str) { | ||
if (str && str.uri) str = str.uri | ||
if (typeof str !== 'string') throw new Error("The cookie function only accepts STRING as param") | ||
if (!Cookie) { | ||
return null; | ||
if (str && str.uri) { | ||
str = str.uri | ||
} | ||
if (typeof str !== 'string') { | ||
throw new Error('The cookie function only accepts STRING as param') | ||
} | ||
return Cookie.parse(str) | ||
}; | ||
} | ||
// Adapt the sometimes-Async api of tough.CookieJar to our requirements | ||
function RequestJar() { | ||
this._jar = new CookieJar(); | ||
function RequestJar(store) { | ||
var self = this | ||
self._jar = new CookieJar(store) | ||
} | ||
RequestJar.prototype.setCookie = function(cookieOrStr, uri, options) { | ||
return this._jar.setCookieSync(cookieOrStr, uri, options || {}); | ||
}; | ||
var self = this | ||
return self._jar.setCookieSync(cookieOrStr, uri, options || {}) | ||
} | ||
RequestJar.prototype.getCookieString = function(uri) { | ||
return this._jar.getCookieStringSync(uri); | ||
}; | ||
var self = this | ||
return self._jar.getCookieStringSync(uri) | ||
} | ||
RequestJar.prototype.getCookies = function(uri) { | ||
return this._jar.getCookiesSync(uri); | ||
}; | ||
var self = this | ||
return self._jar.getCookiesSync(uri) | ||
} | ||
exports.jar = function() { | ||
if (!CookieJar) { | ||
// tough-cookie not loaded, return a stub object: | ||
return { | ||
setCookie: function(){}, | ||
getCookieString: function(){}, | ||
getCookies: function(){} | ||
}; | ||
} | ||
return new RequestJar(); | ||
}; | ||
exports.jar = function(store) { | ||
return new RequestJar(store) | ||
} |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
'use strict' | ||
@@ -3,0 +3,0 @@ module.exports = |
@@ -1,7 +0,7 @@ | ||
'use strict'; | ||
'use strict' | ||
var util = require('util') | ||
, request = require('../index') | ||
; | ||
module.exports = function debug() { | ||
@@ -8,0 +8,0 @@ if (request.debug) { |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
'use strict' | ||
@@ -6,4 +6,11 @@ var extend = require('util')._extend | ||
, crypto = require('crypto') | ||
; | ||
function deferMethod() { | ||
if(typeof setImmediate === 'undefined') { | ||
return process.nextTick | ||
} | ||
return setImmediate | ||
} | ||
function constructObject(initialObject) { | ||
@@ -34,2 +41,6 @@ initialObject = initialObject || {} | ||
function isFunction(value) { | ||
return typeof value === 'function' | ||
} | ||
function filterForCallback(values) { | ||
@@ -40,6 +51,2 @@ var callbacks = values.filter(isFunction) | ||
function isFunction(value) { | ||
return typeof value === 'function' | ||
} | ||
function paramsHaveRequestBody(params) { | ||
@@ -69,7 +76,7 @@ return ( | ||
function isReadStream (rs) { | ||
return rs.readable && rs.path && rs.mode; | ||
return rs.readable && rs.path && rs.mode | ||
} | ||
function toBase64 (str) { | ||
return (new Buffer(str || "", "ascii")).toString("base64") | ||
return (new Buffer(str || '', 'ascii')).toString('base64') | ||
} | ||
@@ -86,1 +93,2 @@ | ||
exports.toBase64 = toBase64 | ||
exports.defer = deferMethod() |
@@ -44,5 +44,3 @@ { | ||
"_shasum": "c57103f7a17fc037f02d7c2e64b602ea223f7d63", | ||
"_resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", | ||
"homepage": "https://github.com/mikeal/aws-sign", | ||
"scripts": {} | ||
"_resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz" | ||
} |
@@ -52,4 +52,3 @@ { | ||
"_shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538", | ||
"_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", | ||
"scripts": {} | ||
"_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" | ||
} |
@@ -50,6 +50,3 @@ { | ||
"_shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", | ||
"_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", | ||
"bugs": { | ||
"url": "https://github.com/juliangruber/isarray/issues" | ||
} | ||
"_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" | ||
} |
@@ -52,4 +52,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" | ||
} |
{ | ||
"name": "readable-stream", | ||
"version": "1.0.33-1", | ||
"version": "1.0.33", | ||
"description": "Streams2, a user-land copy of the stream library from Node.js v0.10.x", | ||
@@ -36,3 +36,3 @@ "main": "readable.js", | ||
"license": "MIT", | ||
"gitHead": "cd9bc3fbcdc82211c5649b5170706b10c65c8479", | ||
"gitHead": "0bf97a117c5646556548966409ebc57a6dda2638", | ||
"bugs": { | ||
@@ -42,6 +42,6 @@ "url": "https://github.com/isaacs/readable-stream/issues" | ||
"homepage": "https://github.com/isaacs/readable-stream", | ||
"_id": "readable-stream@1.0.33-1", | ||
"_shasum": "40d0d91338691291a9117c05d78adb5497c37810", | ||
"_id": "readable-stream@1.0.33", | ||
"_shasum": "3a360dd66c1b1d7fd4705389860eda1d0f61126c", | ||
"_from": "readable-stream@~1.0.26", | ||
"_npmVersion": "1.4.23", | ||
"_npmVersion": "1.4.28", | ||
"_npmUser": { | ||
@@ -66,8 +66,8 @@ "name": "rvagg", | ||
"dist": { | ||
"shasum": "40d0d91338691291a9117c05d78adb5497c37810", | ||
"tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz" | ||
"shasum": "3a360dd66c1b1d7fd4705389860eda1d0f61126c", | ||
"tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz" | ||
}, | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", | ||
"_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz", | ||
"readme": "ERROR: No README data found!" | ||
} |
@@ -1,3 +0,4 @@ | ||
require('stream'); // hack to fix a circular dependency issue when used with browserify | ||
var Stream = require('stream'); // hack to fix a circular dependency issue when used with browserify | ||
exports = module.exports = require('./lib/_stream_readable.js'); | ||
exports.Stream = Stream; | ||
exports.Readable = exports; | ||
@@ -4,0 +5,0 @@ exports.Writable = require('./lib/_stream_writable.js'); |
@@ -5,4 +5,4 @@ # readable-stream | ||
[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true)](https://nodei.co/npm/readable-stream/) | ||
[![NPM](https://nodei.co/npm-dl/readable-stream.png)](https://nodei.co/npm/readable-stream/) | ||
[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) | ||
[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/) | ||
@@ -9,0 +9,0 @@ This package is a mirror of the Streams2 and Streams3 implementations in Node-core. |
@@ -59,4 +59,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/bl/-/bl-0.9.3.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/bl/-/bl-0.9.3.tgz" | ||
} |
@@ -50,4 +50,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/caseless/-/caseless-0.6.0.tgz" | ||
} |
@@ -43,5 +43,3 @@ { | ||
"_shasum": "6d0e09c4921f94a27f63d3b49c5feff1ea4c5130", | ||
"_resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", | ||
"readme": "ERROR: No README data found!", | ||
"scripts": {} | ||
"_resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz" | ||
} |
@@ -58,4 +58,3 @@ { | ||
"_shasum": "ac3613b1da9bed1b47510bb4651b8931e47146c7", | ||
"_resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/async/-/async-0.9.0.tgz" | ||
} |
@@ -56,5 +56,3 @@ { | ||
"_shasum": "58203eed86e3a5ef17aed2b7d9ebd47f0a60dd10", | ||
"_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", | ||
"homepage": "https://github.com/broofa/node-mime", | ||
"scripts": {} | ||
"_resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz" | ||
} |
@@ -78,4 +78,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz" | ||
} |
@@ -58,8 +58,3 @@ { | ||
"_shasum": "7a636e9ded4efcefb19cef4947a3c67dfaee911b", | ||
"_resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", | ||
"bugs": { | ||
"url": "https://github.com/spumko/boom/issues" | ||
}, | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/spumko/boom" | ||
"_resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz" | ||
} |
@@ -62,5 +62,3 @@ { | ||
"_shasum": "ed91ff1f17ad13d3748288594f8a48a0d26f325c", | ||
"_resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/hueniverse/cryptiles" | ||
"_resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz" | ||
} |
@@ -64,8 +64,3 @@ { | ||
"_shasum": "3d322462badf07716ea7eb85baf88079cddce505", | ||
"_resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", | ||
"bugs": { | ||
"url": "https://github.com/spumko/hoek/issues" | ||
}, | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/spumko/hoek" | ||
"_resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz" | ||
} |
@@ -59,8 +59,3 @@ { | ||
"_shasum": "fb885f18b0f3aad189f824862536bceeec750900", | ||
"_resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", | ||
"bugs": { | ||
"url": "https://github.com/hueniverse/sntp/issues" | ||
}, | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/hueniverse/sntp" | ||
"_resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz" | ||
} |
@@ -67,5 +67,3 @@ { | ||
"_shasum": "87cd491f9b46e4e2aeaca335416766885d2d1ed9", | ||
"_resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/hueniverse/hawk" | ||
"_resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz" | ||
} |
@@ -33,3 +33,3 @@ { | ||
"pretest": "which gjslint; if [[ \"$?\" = 0 ]] ; then gjslint --nojsdoc -r lib -r tst; else echo \"Missing gjslint. Skipping lint\"; fi", | ||
"test": "tap ./tst" | ||
"test": "./node_modules/.bin/tap ./tst" | ||
}, | ||
@@ -58,8 +58,3 @@ "_npmUser": { | ||
"_from": "asn1@0.1.11", | ||
"_resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", | ||
"bugs": { | ||
"url": "https://github.com/mcavage/node-asn1/issues" | ||
}, | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/mcavage/node-asn1" | ||
"_resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz" | ||
} |
@@ -35,4 +35,3 @@ { | ||
"_from": "assert-plus@0.1.2", | ||
"_resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.2.tgz" | ||
} |
@@ -33,4 +33,3 @@ { | ||
"_from": "ctype@0.5.2", | ||
"_resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.2.tgz" | ||
} |
@@ -17,3 +17,3 @@ { | ||
"scripts": { | ||
"test": "tap tst/*.js" | ||
"test": "./node_modules/.bin/tap tst/*.js" | ||
}, | ||
@@ -50,7 +50,3 @@ "dependencies": { | ||
"_shasum": "1494e4f5000a83c0f11bcc12d6007c530cb99582", | ||
"_resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz", | ||
"bugs": { | ||
"url": "https://github.com/joyent/node-http-signature/issues" | ||
}, | ||
"homepage": "https://github.com/joyent/node-http-signature" | ||
"_resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.0.tgz" | ||
} |
@@ -47,5 +47,3 @@ { | ||
"_shasum": "4c1f228b5050837eba9d21f50c2e6e320624566e", | ||
"_resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz", | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/isaacs/json-stringify-safe" | ||
"_resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.0.tgz" | ||
} |
@@ -67,4 +67,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz" | ||
} |
@@ -51,5 +51,3 @@ { | ||
"_shasum": "39aef510e5889a3dca9c895b506c73aae1bac048", | ||
"_resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz", | ||
"homepage": "https://github.com/broofa/node-uuid", | ||
"scripts": {} | ||
"_resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.1.tgz" | ||
} |
@@ -23,4 +23,2 @@ { | ||
}, | ||
"readme": "oauth-sign\n==========\n\nOAuth 1 signing. Formerly a vendor lib in mikeal/request, now a standalone module. \n", | ||
"readmeFilename": "README.md", | ||
"bugs": { | ||
@@ -48,4 +46,3 @@ "url": "https://github.com/mikeal/oauth-sign/issues" | ||
"_shasum": "f22956f31ea7151a821e5f2fb32c113cad8b9f69", | ||
"_resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz", | ||
"homepage": "https://github.com/mikeal/oauth-sign" | ||
"_resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.4.0.tgz" | ||
} |
@@ -12,12 +12,10 @@ // Load modules | ||
arrayLimit: 20, | ||
parametersLimit: 1000 | ||
parameterLimit: 1000 | ||
}; | ||
internals.parseValues = function (str, delimiter) { | ||
internals.parseValues = function (str, options) { | ||
delimiter = typeof delimiter === 'string' ? delimiter : internals.delimiter; | ||
var obj = {}; | ||
var parts = str.split(delimiter, internals.parametersLimit); | ||
var parts = str.split(options.delimiter, options.parameterLimit === Infinity ? undefined : options.parameterLimit); | ||
@@ -35,3 +33,3 @@ for (var i = 0, il = parts.length; i < il; ++i) { | ||
if (!obj[key]) { | ||
if (!obj.hasOwnProperty(key)) { | ||
obj[key] = val; | ||
@@ -49,3 +47,3 @@ } | ||
internals.parseObject = function (chain, val) { | ||
internals.parseObject = function (chain, val, options) { | ||
@@ -61,3 +59,3 @@ if (!chain.length) { | ||
obj = []; | ||
obj = obj.concat(internals.parseObject(chain, val)); | ||
obj = obj.concat(internals.parseObject(chain, val, options)); | ||
} | ||
@@ -67,11 +65,13 @@ else { | ||
var index = parseInt(cleanRoot, 10); | ||
var indexString = '' + index; | ||
if (!isNaN(index) && | ||
root !== cleanRoot && | ||
index <= internals.arrayLimit) { | ||
indexString === cleanRoot && | ||
index <= options.arrayLimit) { | ||
obj = []; | ||
obj[index] = internals.parseObject(chain, val); | ||
obj[index] = internals.parseObject(chain, val, options); | ||
} | ||
else { | ||
obj[cleanRoot] = internals.parseObject(chain, val); | ||
obj[cleanRoot] = internals.parseObject(chain, val, options); | ||
} | ||
@@ -84,3 +84,3 @@ } | ||
internals.parseKeys = function (key, val, depth) { | ||
internals.parseKeys = function (key, val, options) { | ||
@@ -116,3 +116,3 @@ if (!key) { | ||
var i = 0; | ||
while ((segment = child.exec(key)) !== null && i < depth) { | ||
while ((segment = child.exec(key)) !== null && i < options.depth) { | ||
@@ -131,7 +131,7 @@ ++i; | ||
return internals.parseObject(keys, val); | ||
return internals.parseObject(keys, val, options); | ||
}; | ||
module.exports = function (str, depth, delimiter) { | ||
module.exports = function (str, options) { | ||
@@ -145,17 +145,18 @@ if (str === '' || | ||
if (typeof depth !== 'number') { | ||
delimiter = depth; | ||
depth = internals.depth; | ||
} | ||
options = options || {}; | ||
options.delimiter = typeof options.delimiter === 'string' || Utils.isRegExp(options.delimiter) ? options.delimiter : internals.delimiter; | ||
options.depth = typeof options.depth === 'number' ? options.depth : internals.depth; | ||
options.arrayLimit = typeof options.arrayLimit === 'number' ? options.arrayLimit : internals.arrayLimit; | ||
options.parameterLimit = typeof options.parameterLimit === 'number' ? options.parameterLimit : internals.parameterLimit; | ||
var tempObj = typeof str === 'string' ? internals.parseValues(str, delimiter) : Utils.clone(str); | ||
var tempObj = typeof str === 'string' ? internals.parseValues(str, options) : str; | ||
var obj = {}; | ||
// Iterate over the keys and setup the new object | ||
// | ||
for (var key in tempObj) { | ||
if (tempObj.hasOwnProperty(key)) { | ||
var newObj = internals.parseKeys(key, tempObj[key], depth); | ||
obj = Utils.merge(obj, newObj); | ||
} | ||
var keys = Object.keys(tempObj); | ||
for (var i = 0, il = keys.length; i < il; ++i) { | ||
var key = keys[i]; | ||
var newObj = internals.parseKeys(key, tempObj[key], options); | ||
obj = Utils.merge(obj, newObj); | ||
} | ||
@@ -162,0 +163,0 @@ |
// Load modules | ||
var Utils = require('./utils'); | ||
// Declare internals | ||
var internals = { | ||
delimiter: '&' | ||
delimiter: '&', | ||
indices: true | ||
}; | ||
internals.stringify = function (obj, prefix) { | ||
internals.stringify = function (obj, prefix, options) { | ||
if (Buffer.isBuffer(obj)) { | ||
if (Utils.isBuffer(obj)) { | ||
obj = obj.toString(); | ||
@@ -32,6 +35,17 @@ } | ||
for (var key in obj) { | ||
if (obj.hasOwnProperty(key)) { | ||
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']')); | ||
if (typeof obj === 'undefined') { | ||
return values; | ||
} | ||
var objKeys = Object.keys(obj); | ||
for (var i = 0, il = objKeys.length; i < il; ++i) { | ||
var key = objKeys[i]; | ||
if (!options.indices && | ||
Array.isArray(obj)) { | ||
values = values.concat(internals.stringify(obj[key], prefix, options)); | ||
} | ||
else { | ||
values = values.concat(internals.stringify(obj[key], prefix + '[' + key + ']', options)); | ||
} | ||
} | ||
@@ -43,15 +57,23 @@ | ||
module.exports = function (obj, delimiter) { | ||
module.exports = function (obj, options) { | ||
delimiter = typeof delimiter === 'undefined' ? internals.delimiter : delimiter; | ||
options = options || {}; | ||
var delimiter = typeof options.delimiter === 'undefined' ? internals.delimiter : options.delimiter; | ||
options.indices = typeof options.indices === 'boolean' ? options.indices : internals.indices; | ||
var keys = []; | ||
for (var key in obj) { | ||
if (obj.hasOwnProperty(key)) { | ||
keys = keys.concat(internals.stringify(obj[key], key)); | ||
} | ||
if (typeof obj !== 'object' || | ||
obj === null) { | ||
return ''; | ||
} | ||
var objKeys = Object.keys(obj); | ||
for (var i = 0, il = objKeys.length; i < il; ++i) { | ||
var key = objKeys[i]; | ||
keys = keys.concat(internals.stringify(obj[key], key, options)); | ||
} | ||
return keys.join(delimiter); | ||
}; |
@@ -23,52 +23,24 @@ // Load modules | ||
exports.clone = function (source) { | ||
exports.merge = function (target, source) { | ||
if (typeof source !== 'object' || | ||
source === null) { | ||
return source; | ||
if (!source) { | ||
return target; | ||
} | ||
if (Buffer.isBuffer(source)) { | ||
return source.toString(); | ||
if (typeof source !== 'object') { | ||
target.push(source); | ||
return target; | ||
} | ||
var obj = Array.isArray(source) ? [] : {}; | ||
for (var i in source) { | ||
if (source.hasOwnProperty(i)) { | ||
obj[i] = exports.clone(source[i]); | ||
} | ||
} | ||
return obj; | ||
}; | ||
exports.merge = function (target, source) { | ||
if (!source) { | ||
if (typeof target !== 'object') { | ||
target = [target].concat(source); | ||
return target; | ||
} | ||
var obj = exports.clone(target); | ||
if (Array.isArray(target) && | ||
!Array.isArray(source)) { | ||
if (Array.isArray(source)) { | ||
for (var i = 0, il = source.length; i < il; ++i) { | ||
if (typeof source[i] !== 'undefined') { | ||
if (typeof obj[i] === 'object') { | ||
obj[i] = exports.merge(obj[i], source[i]); | ||
} | ||
else { | ||
obj[i] = source[i]; | ||
} | ||
} | ||
} | ||
return obj; | ||
target = exports.arrayToObject(target); | ||
} | ||
if (Array.isArray(obj)) { | ||
obj = exports.arrayToObject(obj); | ||
} | ||
var keys = Object.keys(source); | ||
@@ -79,18 +51,11 @@ for (var k = 0, kl = keys.length; k < kl; ++k) { | ||
if (value && | ||
typeof value === 'object') { | ||
if (!obj[key]) { | ||
obj[key] = exports.clone(value); | ||
} | ||
else { | ||
obj[key] = exports.merge(obj[key], value); | ||
} | ||
if (!target[key]) { | ||
target[key] = value; | ||
} | ||
else { | ||
obj[key] = value; | ||
target[key] = exports.merge(target[key], value); | ||
} | ||
} | ||
return obj; | ||
return target; | ||
}; | ||
@@ -109,28 +74,56 @@ | ||
exports.compact = function (obj) { | ||
exports.compact = function (obj, refs) { | ||
if (typeof obj !== 'object' || obj === null) { | ||
if (typeof obj !== 'object' || | ||
obj === null) { | ||
return obj; | ||
} | ||
var compacted = {}; | ||
refs = refs || []; | ||
var lookup = refs.indexOf(obj); | ||
if (lookup !== -1) { | ||
return refs[lookup]; | ||
} | ||
for (var key in obj) { | ||
if (obj.hasOwnProperty(key)) { | ||
if (Array.isArray(obj[key])) { | ||
compacted[key] = []; | ||
refs.push(obj); | ||
for (var i = 0, l = obj[key].length; i < l; i++) { | ||
if (typeof obj[key][i] !== 'undefined') { | ||
compacted[key].push(obj[key][i]); | ||
} | ||
} | ||
if (Array.isArray(obj)) { | ||
var compacted = []; | ||
for (var i = 0, l = obj.length; i < l; ++i) { | ||
if (typeof obj[i] !== 'undefined') { | ||
compacted.push(obj[i]); | ||
} | ||
else { | ||
compacted[key] = exports.compact(obj[key]); | ||
} | ||
} | ||
return compacted; | ||
} | ||
return compacted; | ||
var keys = Object.keys(obj); | ||
for (var i = 0, il = keys.length; i < il; ++i) { | ||
var key = keys[i]; | ||
obj[key] = exports.compact(obj[key], refs); | ||
} | ||
return obj; | ||
}; | ||
exports.isRegExp = function (obj) { | ||
return Object.prototype.toString.call(obj) === '[object RegExp]'; | ||
}; | ||
exports.isBuffer = function (obj) { | ||
if (obj === null || | ||
typeof obj === 'undefined') { | ||
return false; | ||
} | ||
return !!(obj.constructor && | ||
obj.constructor.isBuffer && | ||
obj.constructor.isBuffer(obj)); | ||
}; |
{ | ||
"name": "qs", | ||
"version": "1.2.2", | ||
"version": "2.3.1", | ||
"description": "A querystring parser that supports nesting and arrays, with a depth limit", | ||
@@ -9,3 +9,3 @@ "homepage": "https://github.com/hapijs/qs", | ||
"devDependencies": { | ||
"lab": "3.x.x" | ||
"lab": "4.x.x" | ||
}, | ||
@@ -23,6 +23,2 @@ "scripts": { | ||
], | ||
"author": { | ||
"name": "Nathan LaFreniere", | ||
"email": "quitlahok@gmail.com" | ||
}, | ||
"licenses": [ | ||
@@ -34,13 +30,13 @@ { | ||
], | ||
"gitHead": "bd9455fea88d1c51a80dbf57ef0f99b4e553177d", | ||
"gitHead": "a601ae18bc419399db7debc2765c96c84e83c237", | ||
"bugs": { | ||
"url": "https://github.com/hapijs/qs/issues" | ||
}, | ||
"_id": "qs@1.2.2", | ||
"_shasum": "19b57ff24dc2a99ce1f8bdf6afcda59f8ef61f88", | ||
"_from": "qs@~1.2.0", | ||
"_npmVersion": "1.4.21", | ||
"_id": "qs@2.3.1", | ||
"_shasum": "24e448bc4ee726201995a3c0c768c3bf19494c1c", | ||
"_from": "qs@~2.3.1", | ||
"_npmVersion": "1.4.28", | ||
"_npmUser": { | ||
"name": "hueniverse", | ||
"email": "eran@hueniverse.com" | ||
"name": "nlf", | ||
"email": "quitlahok@gmail.com" | ||
}, | ||
@@ -58,8 +54,7 @@ "maintainers": [ | ||
"dist": { | ||
"shasum": "19b57ff24dc2a99ce1f8bdf6afcda59f8ef61f88", | ||
"tarball": "http://registry.npmjs.org/qs/-/qs-1.2.2.tgz" | ||
"shasum": "24e448bc4ee726201995a3c0c768c3bf19494c1c", | ||
"tarball": "http://registry.npmjs.org/qs/-/qs-2.3.1.tgz" | ||
}, | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/qs/-/qs-2.3.1.tgz" | ||
} |
@@ -23,3 +23,3 @@ # qs | ||
```javascript | ||
Qs.parse(string, [depth], [delimiter]); | ||
Qs.parse(string, [options]); | ||
``` | ||
@@ -78,18 +78,32 @@ | ||
This depth can be overridden by passing a `depth` option to `Qs.parse(string, depth)`: | ||
This depth can be overridden by passing a `depth` option to `Qs.parse(string, [options])`: | ||
```javascript | ||
Qs.parse('a[b][c][d][e][f][g][h][i]=j', 1); | ||
Qs.parse('a[b][c][d][e][f][g][h][i]=j', { depth: 1 }); | ||
// { a: { b: { '[c][d][e][f][g][h][i]': 'j' } } } | ||
``` | ||
The depth limit mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. | ||
The depth limit helps mitigate abuse when **qs** is used to parse user input, and it is recommended to keep it a reasonably small number. | ||
For similar reasons, by default **qs** will only parse up to 1000 parameters. This can be overridden by passing a `parameterLimit` option: | ||
```javascript | ||
Qs.parse('a=b&c=d', { parameterLimit: 1 }); | ||
// { a: 'b' } | ||
``` | ||
An optional delimiter can also be passed: | ||
```javascript | ||
Qs.parse('a=b;c=d', ';'); | ||
Qs.parse('a=b;c=d', { delimiter: ';' }); | ||
// { a: 'b', c: 'd' } | ||
``` | ||
Delimiters can be a regular expression too: | ||
```javascript | ||
Qs.parse('a=b;c=d,e=f', { delimiter: /[;,]/ }); | ||
// { a: 'b', c: 'd', e: 'f' } | ||
``` | ||
### Parsing Arrays | ||
@@ -137,2 +151,9 @@ | ||
This limit can be overridden by passing an `arrayLimit` option: | ||
```javascript | ||
Qs.parse('a[1]=b', { arrayLimit: 0 }); | ||
// { a: { '1': 'b' } } | ||
``` | ||
If you mix notations, **qs** will merge the two items into an object: | ||
@@ -155,3 +176,3 @@ | ||
```javascript | ||
Qs.stringify(object, [delimiter]); | ||
Qs.stringify(object, [options]); | ||
``` | ||
@@ -170,3 +191,3 @@ | ||
When arrays are stringified, they are always given explicit indices: | ||
When arrays are stringified, by default they are given explicit indices: | ||
@@ -178,2 +199,9 @@ ```javascript | ||
You may override this by setting the `indices` option to `false`: | ||
```javascript | ||
Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false }); | ||
// 'a=b&a=c&a=d' | ||
``` | ||
Empty strings and null values will omit the value, but the equals sign (=) remains in place: | ||
@@ -196,4 +224,4 @@ | ||
```javascript | ||
Qs.stringify({ a: 'b', c: 'd' }, ';'); | ||
Qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' }); | ||
// 'a=b;c=d' | ||
``` |
@@ -14,10 +14,9 @@ // Load modules | ||
var lab = exports.lab = Lab.script(); | ||
var expect = Lab.expect; | ||
var before = Lab.before; | ||
var after = Lab.after; | ||
var describe = Lab.experiment; | ||
var it = Lab.test; | ||
var describe = lab.experiment; | ||
var it = lab.test; | ||
describe('#parse', function () { | ||
describe('parse()', function () { | ||
@@ -66,4 +65,4 @@ it('parses a simple string', function (done) { | ||
expect(Qs.parse('a[b][c]=d', 1)).to.deep.equal({ a: { b: { '[c]': 'd' } } }); | ||
expect(Qs.parse('a[b][c][d]=e', 1)).to.deep.equal({ a: { b: { '[c][d]': 'e' } } }); | ||
expect(Qs.parse('a[b][c]=d', { depth: 1 })).to.deep.equal({ a: { b: { '[c]': 'd' } } }); | ||
expect(Qs.parse('a[b][c][d]=e', { depth: 1 })).to.deep.equal({ a: { b: { '[c][d]': 'e' } } }); | ||
done(); | ||
@@ -86,2 +85,13 @@ }); | ||
it('parses a mix of simple and explicit arrays', function (done) { | ||
expect(Qs.parse('a=b&a[]=c')).to.deep.equal({ a: ['b', 'c'] }); | ||
expect(Qs.parse('a[]=b&a=c')).to.deep.equal({ a: ['b', 'c'] }); | ||
expect(Qs.parse('a[0]=b&a=c')).to.deep.equal({ a: ['b', 'c'] }); | ||
expect(Qs.parse('a=b&a[0]=c')).to.deep.equal({ a: ['b', 'c'] }); | ||
expect(Qs.parse('a[1]=b&a=c')).to.deep.equal({ a: ['b', 'c'] }); | ||
expect(Qs.parse('a=b&a[1]=c')).to.deep.equal({ a: ['b', 'c'] }); | ||
done(); | ||
}); | ||
it('parses a nested array', function (done) { | ||
@@ -109,2 +119,8 @@ | ||
it('supports keys that begin with a number', function (done) { | ||
expect(Qs.parse('a[12b]=c')).to.deep.equal({ a: { '12b': 'c' } }); | ||
done(); | ||
}); | ||
it('supports encoded = signs', function (done) { | ||
@@ -196,2 +212,3 @@ | ||
expect(Qs.parse('a[0]=b&a[1]=&a[2]=c&a[19]=')).to.deep.equal({ a: ['b', '', 'c', ''] }); | ||
expect(Qs.parse('a[]=&a[]=b&a[]=c')).to.deep.equal({ a: ['', 'b', 'c'] }); | ||
done(); | ||
@@ -213,6 +230,6 @@ }); | ||
it('parses buffers to strings', function (done) { | ||
it('parses buffers correctly', function (done) { | ||
var b = new Buffer('test'); | ||
expect(Qs.parse({ a: b })).to.deep.equal({ a: b.toString() }); | ||
expect(Qs.parse({ a: b })).to.deep.equal({ a: b }); | ||
done(); | ||
@@ -256,14 +273,38 @@ }); | ||
it('parses a string with an alternative delimiter', function (done) { | ||
it('parses a string with an alternative string delimiter', function (done) { | ||
expect(Qs.parse('a=b;c=d', ';')).to.deep.equal({ a: 'b', c: 'd' }); | ||
expect(Qs.parse('a=b;c=d', { delimiter: ';' })).to.deep.equal({ a: 'b', c: 'd' }); | ||
done(); | ||
}); | ||
it('does not use non-string objects as delimiters', function (done) { | ||
it('parses a string with an alternative RegExp delimiter', function (done) { | ||
expect(Qs.parse('a=b&c=d', {})).to.deep.equal({ a: 'b', c: 'd' }); | ||
expect(Qs.parse('a=b; c=d', { delimiter: /[;,] */ })).to.deep.equal({ a: 'b', c: 'd' }); | ||
done(); | ||
}); | ||
it('does not use non-splittable objects as delimiters', function (done) { | ||
expect(Qs.parse('a=b&c=d', { delimiter: true })).to.deep.equal({ a: 'b', c: 'd' }); | ||
done(); | ||
}); | ||
it('allows overriding parameter limit', function (done) { | ||
expect(Qs.parse('a=b&c=d', { parameterLimit: 1 })).to.deep.equal({ a: 'b' }); | ||
done(); | ||
}); | ||
it('allows setting the parameter limit to Infinity', function (done) { | ||
expect(Qs.parse('a=b&c=d', { parameterLimit: Infinity })).to.deep.equal({ a: 'b', c: 'd' }); | ||
done(); | ||
}); | ||
it('allows overriding array limit', function (done) { | ||
expect(Qs.parse('a[0]=b&a[1]=c', { arrayLimit: 0 })).to.deep.equal({ a: { '0': 'b', '1': 'c' } }); | ||
done(); | ||
}); | ||
it('parses an object', function (done) { | ||
@@ -308,2 +349,60 @@ | ||
}); | ||
it('does not blow up when Buffer global is missing', function (done) { | ||
var tempBuffer = global.Buffer; | ||
delete global.Buffer; | ||
expect(Qs.parse('a=b&c=d')).to.deep.equal({ a: 'b', c: 'd' }); | ||
global.Buffer = tempBuffer; | ||
done(); | ||
}); | ||
it('does not crash when using invalid dot notation', function (done) { | ||
expect(Qs.parse('roomInfoList[0].childrenAges[0]=15&roomInfoList[0].numberOfAdults=2')).to.deep.equal({ roomInfoList: [['15', '2']] }); | ||
done(); | ||
}); | ||
it('does not crash when parsing circular references', function (done) { | ||
var a = {}; | ||
a.b = a; | ||
var parsed; | ||
expect(function () { | ||
parsed = Qs.parse({ 'foo[bar]': 'baz', 'foo[baz]': a }); | ||
}).to.not.throw(Error); | ||
expect(parsed).to.have.key('foo'); | ||
expect(parsed.foo).to.have.keys('bar', 'baz'); | ||
expect(parsed.foo.bar).to.equal('baz'); | ||
expect(parsed.foo.baz).to.deep.equal(a); | ||
done(); | ||
}); | ||
it('parses plain objects correctly', function (done) { | ||
var a = Object.create(null); | ||
a.b = 'c'; | ||
expect(Qs.parse(a)).to.deep.equal({ b: 'c' }); | ||
expect(Qs.parse({ a: a })).to.deep.equal({ a: { b: 'c' } }); | ||
done(); | ||
}); | ||
it('parses dates correctly', function (done) { | ||
var now = new Date(); | ||
expect(Qs.parse({ a: now })).to.deep.equal({ a: now }); | ||
done(); | ||
}); | ||
it('parses regular expressions correctly', function (done) { | ||
var re = /^test$/; | ||
expect(Qs.parse({ a: re })).to.deep.equal({ a: re }); | ||
done(); | ||
}); | ||
}); |
@@ -14,10 +14,9 @@ // Load modules | ||
var lab = exports.lab = Lab.script(); | ||
var expect = Lab.expect; | ||
var before = Lab.before; | ||
var after = Lab.after; | ||
var describe = Lab.experiment; | ||
var it = Lab.test; | ||
var describe = lab.experiment; | ||
var it = lab.test; | ||
describe('#stringify', function () { | ||
describe('stringify()', function () { | ||
@@ -45,2 +44,8 @@ it('stringifies a querystring object', function (done) { | ||
it('omits array indices when asked', function (done) { | ||
expect(Qs.stringify({ a: ['b', 'c', 'd'] }, { indices: false })).to.equal('a=b&a=c&a=d'); | ||
done(); | ||
}); | ||
it('stringifies a nested array value', function (done) { | ||
@@ -59,2 +64,8 @@ | ||
it('does not omit object keys when indices = false', function (done) { | ||
expect(Qs.stringify({ a: [{ b: 'c' }] }, { indices: false })).to.equal('a%5Bb%5D=c'); | ||
done(); | ||
}); | ||
it('stringifies a complicated object', function (done) { | ||
@@ -75,2 +86,30 @@ | ||
it('stringifies an empty object', function (done) { | ||
var obj = Object.create(null); | ||
obj.a = 'b'; | ||
expect(Qs.stringify(obj)).to.equal('a=b'); | ||
done(); | ||
}); | ||
it('returns an empty string for invalid input', function (done) { | ||
expect(Qs.stringify(undefined)).to.equal(''); | ||
expect(Qs.stringify(false)).to.equal(''); | ||
expect(Qs.stringify(null)).to.equal(''); | ||
expect(Qs.stringify('')).to.equal(''); | ||
done(); | ||
}); | ||
it('stringifies an object with an empty object as a child', function (done) { | ||
var obj = { | ||
a: Object.create(null) | ||
}; | ||
obj.a.b = 'c'; | ||
expect(Qs.stringify(obj)).to.equal('a%5Bb%5D=c'); | ||
done(); | ||
}); | ||
it('drops keys with a value of undefined', function (done) { | ||
@@ -130,5 +169,14 @@ | ||
expect(Qs.stringify({ a: 'b', c: 'd' }, ';')).to.equal('a=b;c=d'); | ||
expect(Qs.stringify({ a: 'b', c: 'd' }, { delimiter: ';' })).to.equal('a=b;c=d'); | ||
done(); | ||
}); | ||
it('doesn\'t blow up when Buffer global is missing', function (done) { | ||
var tempBuffer = global.Buffer; | ||
delete global.Buffer; | ||
expect(Qs.stringify({ a: 'b', c: 'd' })).to.equal('a=b&c=d'); | ||
global.Buffer = tempBuffer; | ||
done(); | ||
}); | ||
}); |
@@ -43,7 +43,3 @@ { | ||
"_from": "stringstream@~0.0.4", | ||
"_resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz", | ||
"bugs": { | ||
"url": "https://github.com/mhart/StringStream/issues" | ||
}, | ||
"homepage": "https://github.com/mhart/StringStream" | ||
"_resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.4.tgz" | ||
} |
@@ -1,2 +0,2 @@ | ||
Copyright Mathias Bynens <http://mathiasbynens.be/> | ||
Copyright Mathias Bynens <https://mathiasbynens.be/> | ||
@@ -3,0 +3,0 @@ Permission is hereby granted, free of charge, to any person obtaining |
{ | ||
"name": "punycode", | ||
"version": "1.3.1", | ||
"version": "1.3.2", | ||
"description": "A robust Punycode converter that fully complies to RFC 3492 and RFC 5891, and works on nearly all JavaScript platforms.", | ||
"homepage": "http://mths.be/punycode", | ||
"homepage": "https://mths.be/punycode", | ||
"main": "punycode.js", | ||
@@ -16,11 +16,6 @@ "keywords": [ | ||
], | ||
"licenses": [ | ||
{ | ||
"type": "MIT", | ||
"url": "http://mths.be/mit" | ||
} | ||
], | ||
"license": "MIT", | ||
"author": { | ||
"name": "Mathias Bynens", | ||
"url": "http://mathiasbynens.be/" | ||
"url": "https://mathiasbynens.be/" | ||
}, | ||
@@ -30,3 +25,3 @@ "contributors": [ | ||
"name": "Mathias Bynens", | ||
"url": "http://mathiasbynens.be/" | ||
"url": "https://mathiasbynens.be/" | ||
}, | ||
@@ -49,5 +44,2 @@ { | ||
], | ||
"directories": { | ||
"test": "tests" | ||
}, | ||
"scripts": { | ||
@@ -66,6 +58,7 @@ "test": "node tests/tests.js" | ||
}, | ||
"_id": "punycode@1.3.1", | ||
"_shasum": "710afe5123c20a1530b712e3e682b9118fe8058e", | ||
"gitHead": "38c8d3131a82567bfef18da09f7f4db68c84f8a3", | ||
"_id": "punycode@1.3.2", | ||
"_shasum": "9653a036fb7c1ee42342f2325cceefea3926c48d", | ||
"_from": "punycode@>=0.2.0", | ||
"_npmVersion": "1.4.9", | ||
"_npmVersion": "1.4.28", | ||
"_npmUser": { | ||
@@ -86,7 +79,7 @@ "name": "mathias", | ||
"dist": { | ||
"shasum": "710afe5123c20a1530b712e3e682b9118fe8058e", | ||
"tarball": "http://registry.npmjs.org/punycode/-/punycode-1.3.1.tgz" | ||
"shasum": "9653a036fb7c1ee42342f2325cceefea3926c48d", | ||
"tarball": "http://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" | ||
}, | ||
"_resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.1.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" | ||
} |
@@ -1,2 +0,2 @@ | ||
/*! http://mths.be/punycode v1.3.1 by @mathias */ | ||
/*! https://mths.be/punycode v1.3.2 by @mathias */ | ||
;(function(root) { | ||
@@ -106,3 +106,5 @@ | ||
} | ||
var labels = string.split(regexSeparators); | ||
// Avoid `split(regex)` for IE8 compatibility. See #17. | ||
string = string.replace(regexSeparators, '\x2E'); | ||
var labels = string.split('.'); | ||
var encoded = map(labels, fn).join('.'); | ||
@@ -119,3 +121,3 @@ return result + encoded; | ||
* @see `punycode.ucs2.encode` | ||
* @see <http://mathiasbynens.be/notes/javascript-encoding> | ||
* @see <https://mathiasbynens.be/notes/javascript-encoding> | ||
* @memberOf punycode.ucs2 | ||
@@ -489,7 +491,7 @@ * @name decode | ||
*/ | ||
'version': '1.3.1', | ||
'version': '1.3.2', | ||
/** | ||
* An object of methods to convert from JavaScript's internal character | ||
* representation (UCS-2) to Unicode code points, and back. | ||
* @see <http://mathiasbynens.be/notes/javascript-encoding> | ||
* @see <https://mathiasbynens.be/notes/javascript-encoding> | ||
* @memberOf punycode | ||
@@ -496,0 +498,0 @@ * @type Object |
@@ -127,3 +127,3 @@ # Punycode.js [![Build status](https://travis-ci.org/bestiejs/punycode.js.svg?branch=master)](https://travis-ci.org/bestiejs/punycode.js) [![Code coverage status](http://img.shields.io/coveralls/bestiejs/punycode.js/master.svg)](https://coveralls.io/r/bestiejs/punycode.js) [![Dependency status](https://gemnasium.com/bestiejs/punycode.js.svg)](https://gemnasium.com/bestiejs/punycode.js) | ||
Creates an array containing the numeric code point values of each Unicode symbol in the string. While [JavaScript uses UCS-2 internally](http://mathiasbynens.be/notes/javascript-encoding), this function will convert a pair of surrogate halves (each of which UCS-2 exposes as separate characters) into a single code point, matching UTF-16. | ||
Creates an array containing the numeric code point values of each Unicode symbol in the string. While [JavaScript uses UCS-2 internally](https://mathiasbynens.be/notes/javascript-encoding), this function will convert a pair of surrogate halves (each of which UCS-2 exposes as separate characters) into a single code point, matching UTF-16. | ||
@@ -167,3 +167,3 @@ ```js | ||
|---| | ||
| [Mathias Bynens](http://mathiasbynens.be/) | | ||
| [Mathias Bynens](https://mathiasbynens.be/) | | ||
@@ -178,2 +178,2 @@ ## Contributors | ||
Punycode.js is available under the [MIT](http://mths.be/mit) license. | ||
Punycode.js is available under the [MIT](https://mths.be/mit) license. |
@@ -43,4 +43,3 @@ { | ||
"_shasum": "b1184e312ffbcf70b3b4c78e8c219de7ebb1c550", | ||
"_resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.0.tgz" | ||
} |
@@ -10,3 +10,3 @@ { | ||
], | ||
"version": "2.45.0", | ||
"version": "2.47.0", | ||
"author": { | ||
@@ -18,6 +18,6 @@ "name": "Mikeal Rogers", | ||
"type": "git", | ||
"url": "https://github.com/mikeal/request.git" | ||
"url": "https://github.com/request/request.git" | ||
}, | ||
"bugs": { | ||
"url": "http://github.com/mikeal/request/issues" | ||
"url": "http://github.com/request/request/issues" | ||
}, | ||
@@ -33,8 +33,8 @@ "license": "Apache-2.0", | ||
"forever-agent": "~0.5.0", | ||
"qs": "~1.2.0", | ||
"form-data": "~0.1.0", | ||
"json-stringify-safe": "~5.0.0", | ||
"mime-types": "~1.0.1", | ||
"node-uuid": "~1.4.0", | ||
"qs": "~2.3.1", | ||
"tunnel-agent": "~0.4.0", | ||
"form-data": "~0.1.0", | ||
"tough-cookie": ">=0.12.0", | ||
@@ -45,24 +45,19 @@ "http-signature": "~0.10.0", | ||
"aws-sign2": "~0.5.0", | ||
"stringstream": "~0.0.4" | ||
"stringstream": "~0.0.4", | ||
"combined-stream": "~0.0.5" | ||
}, | ||
"optionalDependencies": { | ||
"tough-cookie": ">=0.12.0", | ||
"http-signature": "~0.10.0", | ||
"oauth-sign": "~0.4.0", | ||
"hawk": "1.1.1", | ||
"aws-sign2": "~0.5.0", | ||
"stringstream": "~0.0.4" | ||
}, | ||
"scripts": { | ||
"test": "npm run lint && node tests/run.js", | ||
"lint": "./node_modules/eslint/bin/eslint.js lib/ *.js" | ||
"test": "npm run lint && node node_modules/.bin/taper tests/test-*.js", | ||
"lint": "node node_modules/.bin/eslint lib/ *.js tests/ && echo Lint passed." | ||
}, | ||
"devDependencies": { | ||
"eslint": "0.5.1", | ||
"rimraf": "~2.2.8", | ||
"eslint": "0.5.1" | ||
"tape": "~3.0.0", | ||
"taper": "~0.3.0" | ||
}, | ||
"gitHead": "fff5c951778859dc1f3d17f38f7d4426cbb75918", | ||
"homepage": "https://github.com/mikeal/request", | ||
"_id": "request@2.45.0", | ||
"_shasum": "29d713a0a07f17fb2e7b61815d2010681718e93c", | ||
"gitHead": "0ad38bf9a51b34cb4bde1e65807dbee7e83bca82", | ||
"homepage": "https://github.com/request/request", | ||
"_id": "request@2.47.0", | ||
"_shasum": "09e9fd1a4fed6593a805ef8202b20f0c5ecb485f", | ||
"_from": "request@2.x", | ||
@@ -85,8 +80,7 @@ "_npmVersion": "1.4.14", | ||
"dist": { | ||
"shasum": "29d713a0a07f17fb2e7b61815d2010681718e93c", | ||
"tarball": "http://registry.npmjs.org/request/-/request-2.45.0.tgz" | ||
"shasum": "09e9fd1a4fed6593a805ef8202b20f0c5ecb485f", | ||
"tarball": "http://registry.npmjs.org/request/-/request-2.47.0.tgz" | ||
}, | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/request/-/request-2.45.0.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/request/-/request-2.47.0.tgz" | ||
} |
# Request — Simplified HTTP client | ||
[![NPM](https://nodei.co/npm/request.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/request/) | ||
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/request/request?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) | ||
## Super simple to use | ||
@@ -38,2 +39,14 @@ | ||
Request emits a "response" event when a response is received. The `response` argument will be an instance of [http.IncomingMessage](http://nodejs.org/api/http.html#http_http_incomingmessage). | ||
```javascript | ||
request | ||
.get('http://google.com/img.png') | ||
.on('response', function(response) { | ||
console.log(response.statusCode) // 200 | ||
console.log(response.headers['content-type']) // 'image/png' | ||
}) | ||
.pipe(request.put('http://mysite.com/img.png')) | ||
``` | ||
Now let’s get fancy. | ||
@@ -138,2 +151,5 @@ | ||
You can also set the `proxyHeaderExclusiveList` to share certain | ||
headers only with the proxy and not with destination host. | ||
By default, this set is: | ||
@@ -169,5 +185,4 @@ | ||
Note that, when using a tunneling proxy, the `proxy-authorization` | ||
header is *never* sent to the endpoint server, but only to the proxy | ||
server. All other headers are sent as-is over the established | ||
connection. | ||
header and any headers from custom `proxyHeaderExclusiveList` are | ||
*never* sent to the endpoint server, but only to the proxy server. | ||
@@ -193,14 +208,14 @@ ### Controlling proxy behaviour using environment variables | ||
## UNIX Socket | ||
## UNIX Socket | ||
`request` supports the `unix://` protocol for all requests. The path is assumed to be absolute to the root of the host file system. | ||
`request` supports making requests to [UNIX Domain Sockets](http://en.wikipedia.org/wiki/Unix_domain_socket). To make one, use the following URL scheme: | ||
HTTP paths are extracted from the supplied URL by testing each level of the full URL against net.connect for a socket response. | ||
Thus the following request will GET `/httppath` from the HTTP server listening on `/tmp/unix.socket` | ||
```javascript | ||
request.get('unix://tmp/unix.socket/httppath') | ||
/* Pattern */ 'http://unix:SOCKET:PATH' | ||
/* Example */ request.get('http://unix:/absolute/path/to/unix.socket:/request/path') | ||
``` | ||
Note: The `SOCKET` path is assumed to be absolute to the root of the host file system. | ||
## Forms | ||
@@ -210,2 +225,4 @@ | ||
#### application/x-www-form-urlencoded (URL-Encoded Forms) | ||
URL-encoded forms are simple. | ||
@@ -217,13 +234,33 @@ | ||
request.post('http://service.com/upload').form({key:'value'}) | ||
// or | ||
request.post({url:'http://service.com/upload', form: {key:'value'}}, function(err,httpResponse,body){ /* ... */ }) | ||
``` | ||
For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). For the most basic case, you can pass your upload form data via the `formData` option. | ||
#### multipart/form-data (Multipart Form Uploads) | ||
For `multipart/form-data` we use the [form-data](https://github.com/felixge/node-form-data) library by [@felixge](https://github.com/felixge). For the most cases, you can pass your upload form data via the `formData` option. | ||
```javascript | ||
var formData = { | ||
// Pass a simple key-value pair | ||
my_field: 'my_value', | ||
// Pass data via Buffers | ||
my_buffer: new Buffer([1, 2, 3]), | ||
// Pass data via Streams | ||
my_file: fs.createReadStream(__dirname + '/unicycle.jpg'), | ||
remote_file: request(remoteFile) | ||
// Pass multiple values /w an Array | ||
attachments: [ | ||
fs.createReadStream(__dirname + '/attacment1.jpg') | ||
fs.createReadStream(__dirname + '/attachment2.jpg') | ||
], | ||
// Pass optional meta-data with an 'options' object with style: {value: DATA, options: OPTIONS} | ||
// See the `form-data` README for more information about options: https://github.com/felixge/node-form-data | ||
custom_file: { | ||
value: fs.createReadStream('/dev/urandom'), | ||
options: { | ||
filename: 'topsecret.jpg', | ||
contentType: 'image/jpg' | ||
} | ||
} | ||
}; | ||
@@ -238,23 +275,19 @@ request.post({url:'http://service.com/upload', formData: formData}, function optionalCallback(err, httpResponse, body) { | ||
For more advanced cases (like appending form data options) you'll need access to the form itself. | ||
For advanced cases, you can the form-data object itself via `r.form()`. This can be modified until the request is fired on the next cycle of the event-loop. (Note that this calling `form()` will clear the currently set form data for that request.) | ||
```javascript | ||
var r = request.post('http://service.com/upload', function optionalCallback(err, httpResponse, body) { | ||
if (err) { | ||
return console.error('upload failed:', err); | ||
} | ||
console.log('Upload successful! Server responded with:', body); | ||
}) | ||
// NOTE: Advanced use-case, for normal use see 'formData' usage above | ||
var r = request.post('http://service.com/upload', function optionalCallback(err, httpResponse, body) { // ... | ||
// Just like always, `r` is a writable stream, and can be used as such (you have until nextTick to pipe it, etc.) | ||
// Alternatively, you can provide a callback (that's what this example does — see `optionalCallback` above). | ||
var form = r.form(); | ||
form.append('my_field', 'my_value'); | ||
form.append('my_buffer', new Buffer([1, 2, 3])); | ||
form.append('my_buffer', fs.createReadStream(__dirname + '/unicycle.jpg'), {filename: 'unicycle.jpg'}); | ||
form.append('custom_file', fs.createReadStream(__dirname + '/unicycle.jpg'), {filename: 'unicycle.jpg'}); | ||
``` | ||
See the [form-data](https://github.com/felixge/node-form-data) README for more information & examples. | ||
See the [form-data README](https://github.com/felixge/node-form-data) for more information & examples. | ||
Some variations in different HTTP implementations require a newline/CRLF before, after, or both before and after the boundary of a `multipart/form-data` request. This has been observed in the .NET WebAPI version 4.0. You can turn on a boundary preambleCRLF or postamble by passing them as `true` to your request options. | ||
#### multipart/related | ||
Some variations in different HTTP implementations require a newline/CRLF before, after, or both before and after the boundary of a `multipart/related` request (using the multipart option). This has been observed in the .NET WebAPI version 4.0. You can turn on a boundary preambleCRLF or postamble by passing them as `true` to your request options. | ||
```javascript | ||
@@ -309,3 +342,3 @@ request( | ||
Note that you can also use for basic authentication a trick using the URL itself, as specified in [RFC 1738](http://www.ietf.org/rfc/rfc1738.txt). | ||
Note that you can also use for basic authentication a trick using the URL itself, as specified in [RFC 1738](http://www.ietf.org/rfc/rfc1738.txt). | ||
Simply pass the `user:password` before the host with an `@` sign. | ||
@@ -386,3 +419,3 @@ | ||
var options = { | ||
url: 'https://api.github.com/repos/mikeal/request', | ||
url: 'https://api.github.com/repos/request/request', | ||
headers: { | ||
@@ -404,2 +437,43 @@ 'User-Agent': 'request' | ||
## TLS/SSL Protocol | ||
TLS/SSL Protocol options, such as `cert`, `key` and `passphrase`, can be | ||
set in the `agentOptions` property of the `options` object. | ||
In the example below, we call an API requires client side SSL certificate | ||
(in PEM format) with passphrase protected private key (in PEM format) and disable the SSLv3 protocol: | ||
```javascript | ||
var fs = require('fs') | ||
, path = require('path') | ||
, certFile = path.resolve(__dirname, 'ssl/client.crt') | ||
, keyFile = path.resolve(__dirname, 'ssl/client.key') | ||
, request = require('request'); | ||
var options = { | ||
url: 'https://api.some-server.com/', | ||
agentOptions: { | ||
'cert': fs.readFileSync(certFile), | ||
'key': fs.readFileSync(keyFile), | ||
// Or use `pfx` property replacing `cert` and `key` when using private key, certificate and CA certs in PFX or PKCS12 format: | ||
// 'pfx': fs.readFileSync(pfxFilePath), | ||
'passphrase': 'password', | ||
'securityOptions': 'SSL_OP_NO_SSLv3' | ||
} | ||
}; | ||
request.get(options); | ||
``` | ||
It is able to force using SSLv3 only by specifying `secureProtocol`: | ||
```javascript | ||
request.get({ | ||
url: 'https://api.some-server.com/', | ||
agentOptions: { | ||
'secureProtocol': 'SSLv3_method' | ||
} | ||
}); | ||
``` | ||
## request(options, callback) | ||
@@ -411,6 +485,12 @@ | ||
* `qs` - object containing querystring values to be appended to the `uri` | ||
* `useQuerystring` - If true, use `querystring` to stringify and parse | ||
querystrings, otherwise use `qs` (default: `false`). Set this option to | ||
`true` if you need arrays to be serialized as `foo=bar&foo=baz` instead of the | ||
default `foo[0]=bar&foo[1]=baz`. | ||
* `method` - http method (default: `"GET"`) | ||
* `headers` - http headers (default: `{}`) | ||
* `body` - entity body for PATCH, POST and PUT requests. Must be a `Buffer` or `String`. | ||
* `form` - when passed an object or a querystring, this sets `body` to a querystring representation of value, and adds `Content-type: application/x-www-form-urlencoded; charset=utf-8` header. When passed no options, a `FormData` instance is returned (and is piped to request). | ||
* `body` - entity body for PATCH, POST and PUT requests. Must be a `Buffer` or `String`, unless `json` is `true`. If `json` is `true`, then `body` must be a JSON-serializable object. | ||
* `form` - when passed an object or a querystring, this sets `body` to a querystring representation of value, and adds `Content-type: application/x-www-form-urlencoded` header. When passed no options, a `FormData` instance is returned (and is piped to request). See "Forms" section above. | ||
* `formData` - Data to pass for a `multipart/form-data` request. See "Forms" section above. | ||
* `multipart` - (experimental) Data to pass for a `multipart/related` request. See "Forms" section above | ||
* `auth` - A hash containing values `user` || `username`, `pass` || `password`, and `sendImmediately` (optional). See documentation above. | ||
@@ -425,4 +505,4 @@ * `json` - sets `body` but to JSON representation of value and adds `Content-type: application/json` header. Additionally, parses the response body as JSON. | ||
* `encoding` - Encoding to be used on `setEncoding` of response data. If `null`, the `body` is returned as a `Buffer`. Anything else **(including the default value of `undefined`)** will be passed as the [encoding](http://nodejs.org/api/buffer.html#buffer_buffer) parameter to `toString()` (meaning this is effectively `utf8` by default). | ||
* `pool` - A hash object containing the agents for these requests. If omitted, the request will use the global pool (which is set to node's default `maxSockets`) | ||
* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool. | ||
* `pool` - An object describing which agents to use for the request. If this option is omitted the request will use the global agent (as long as [your options allow for it](request.js#L747)). Otherwise, request will search the pool for your custom agent. If no custom agent is found, a new agent will be created and added to the pool. | ||
* A `maxSockets` property can also be provided on the `pool` object to set the max number of sockets for all agents created (ex: `pool: {maxSockets: Infinity}`). | ||
* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request | ||
@@ -433,2 +513,4 @@ * `proxy` - An HTTP proxy to be used. Supports proxy Auth with Basic Auth, identical to support for the `url` parameter (by embedding the auth info in the `uri`) | ||
* `strictSSL` - If `true`, requires SSL certificates be valid. **Note:** to use your own certificate authority, you need to specify an agent that was created with that CA as an option. | ||
* `agentOptions` - Object containing user agent options. See documentation above. **Note:** [see tls API doc for TLS/SSL options](http://nodejs.org/api/tls.html#tls_tls_connect_options_callback). | ||
* `jar` - If `true` and `tough-cookie` is installed, remember cookies for future use (or define your custom cookie jar; see examples section) | ||
@@ -445,5 +527,7 @@ * `aws` - `object` containing AWS signing information. Should have the properties `key`, `secret`. Also requires the property `bucket`, unless you’re specifying your `bucket` as part of the path, or the request doesn’t use a bucket (i.e. GET Services) | ||
tunneling proxy. | ||
* `proxyHeaderExclusiveList` - A whitelist of headers to send | ||
exclusively to a tunneling proxy and not to destination. | ||
The callback argument gets 3 arguments: | ||
The callback argument gets 3 arguments: | ||
@@ -462,3 +546,3 @@ 1. An `error` when applicable (usually from [`http.ClientRequest`](http://nodejs.org/api/http.html#http_class_http_clientrequest) object) | ||
**Note:** You can call `.defaults()` on the wrapper that is returned from `request.defaults` to add/override defaults that were previously defaulted. | ||
**Note:** You can call `.defaults()` on the wrapper that is returned from `request.defaults` to add/override defaults that were previously defaulted. | ||
@@ -531,5 +615,5 @@ For example: | ||
```javascript | ||
request.cookie('cookie_string_here') | ||
request.cookie('key1=value1') | ||
``` | ||
### request.jar | ||
### request.jar() | ||
@@ -623,7 +707,6 @@ Function that creates a new cookie jar. | ||
```javascript | ||
// `npm install --save tough-cookie` before this works | ||
var j = request.jar(); | ||
var cookie = request.cookie('key1=value1'); | ||
var url = 'http://www.google.com'; | ||
j.setCookieSync(cookie, url); | ||
j.setCookie(cookie, url); | ||
request({url: url, jar: j}, function () { | ||
@@ -634,9 +717,30 @@ request('http://images.google.com') | ||
To inspect your cookie jar after a request | ||
To use a custom cookie store (such as a | ||
[`FileCookieStore`](https://github.com/mitsuru/tough-cookie-filestore) | ||
which supports saving to and restoring from JSON files), pass it as a parameter | ||
to `request.jar()`: | ||
```javascript | ||
var j = request.jar() | ||
var FileCookieStore = require('tough-cookie-filestore'); | ||
// NOTE - currently the 'cookies.json' file must already exist! | ||
var j = request.jar(new FileCookieStore('cookies.json')); | ||
request = request.defaults({ jar : j }) | ||
request('http://www.google.com', function() { | ||
request('http://images.google.com') | ||
}) | ||
``` | ||
The cookie store must be a | ||
[`tough-cookie`](https://github.com/goinstant/tough-cookie) | ||
store and it must support synchronous operations; see the | ||
[`CookieStore` API docs](https://github.com/goinstant/tough-cookie/#cookiestore-api) | ||
for details. | ||
To inspect your cookie jar after a request: | ||
```javascript | ||
var j = request.jar() | ||
request({url: 'http://www.google.com', jar: j}, function () { | ||
var cookie_string = j.getCookieString(uri); // "key1=value1; key2=value2; ..." | ||
var cookies = j.getCookies(uri); | ||
var cookies = j.getCookies(uri); | ||
// [{key: 'key1', value: 'value1', domain: "www.google.com", ...}, ...] | ||
@@ -643,0 +747,0 @@ }) |
@@ -1,6 +0,5 @@ | ||
'use strict'; | ||
'use strict' | ||
var optional = require('./lib/optional') | ||
, http = require('http') | ||
, https = optional('https') | ||
var http = require('http') | ||
, https = require('https') | ||
, url = require('url') | ||
@@ -13,30 +12,30 @@ , util = require('util') | ||
, helpers = require('./lib/helpers') | ||
, safeStringify = helpers.safeStringify | ||
, md5 = helpers.md5 | ||
, isReadStream = helpers.isReadStream | ||
, toBase64 = helpers.toBase64 | ||
, bl = require('bl') | ||
, oauth = optional('oauth-sign') | ||
, hawk = optional('hawk') | ||
, aws = optional('aws-sign2') | ||
, httpSignature = optional('http-signature') | ||
, oauth = require('oauth-sign') | ||
, hawk = require('hawk') | ||
, aws = require('aws-sign2') | ||
, httpSignature = require('http-signature') | ||
, uuid = require('node-uuid') | ||
, mime = require('mime-types') | ||
, tunnel = require('tunnel-agent') | ||
, stringstream = optional('stringstream') | ||
, stringstream = require('stringstream') | ||
, caseless = require('caseless') | ||
, ForeverAgent = require('forever-agent') | ||
, FormData = optional('form-data') | ||
, FormData = require('form-data') | ||
, cookies = require('./lib/cookies') | ||
, globalCookieJar = cookies.jar() | ||
, copy = require('./lib/copy') | ||
, debug = require('./lib/debug') | ||
, net = require('net') | ||
; | ||
, CombinedStream = require('combined-stream') | ||
var safeStringify = helpers.safeStringify | ||
, md5 = helpers.md5 | ||
, isReadStream = helpers.isReadStream | ||
, toBase64 = helpers.toBase64 | ||
, defer = helpers.defer | ||
, globalCookieJar = cookies.jar() | ||
var globalPool = {} | ||
var isUrl = /^https?:|^unix:/ | ||
, isUrl = /^https?:/ | ||
@@ -62,3 +61,2 @@ var defaultProxyHeaderWhiteList = [ | ||
'pragma', | ||
'proxy-authorization', | ||
'referer', | ||
@@ -71,2 +69,190 @@ 'te', | ||
var defaultProxyHeaderExclusiveList = [ | ||
'proxy-authorization' | ||
] | ||
function filterForNonReserved(reserved, options) { | ||
// Filter out properties that are not reserved. | ||
// Reserved values are passed in at call site. | ||
var object = {} | ||
for (var i in options) { | ||
var notReserved = (reserved.indexOf(i) === -1) | ||
if (notReserved) { | ||
object[i] = options[i] | ||
} | ||
} | ||
return object | ||
} | ||
function filterOutReservedFunctions(reserved, options) { | ||
// Filter out properties that are functions and are reserved. | ||
// Reserved values are passed in at call site. | ||
var object = {} | ||
for (var i in options) { | ||
var isReserved = !(reserved.indexOf(i) === -1) | ||
var isFunction = (typeof options[i] === 'function') | ||
if (!(isReserved && isFunction)) { | ||
object[i] = options[i] | ||
} | ||
} | ||
return object | ||
} | ||
function constructProxyHost(uriObject) { | ||
var port = uriObject.portA | ||
, protocol = uriObject.protocol | ||
, proxyHost = uriObject.hostname + ':' | ||
if (port) { | ||
proxyHost += port | ||
} else if (protocol === 'https:') { | ||
proxyHost += '443' | ||
} else { | ||
proxyHost += '80' | ||
} | ||
return proxyHost | ||
} | ||
function constructProxyHeaderWhiteList(headers, proxyHeaderWhiteList) { | ||
var whiteList = proxyHeaderWhiteList | ||
.reduce(function (set, header) { | ||
set[header] = true | ||
return set | ||
}, {}) | ||
return Object.keys(headers) | ||
.filter(function (header) { | ||
return whiteList[header.toLowerCase()] | ||
}) | ||
.reduce(function (set, header) { | ||
set[header] = headers[header] | ||
return set | ||
}, {}) | ||
} | ||
function construcTunnelOptions(request) { | ||
var proxy = request.proxy | ||
var tunnelOptions = { | ||
proxy: { | ||
host: proxy.hostname, | ||
port: +proxy.port, | ||
proxyAuth: proxy.auth, | ||
headers: request.proxyHeaders | ||
}, | ||
rejectUnauthorized: request.rejectUnauthorized, | ||
headers: request.headers, | ||
ca: request.ca, | ||
cert: request.cert, | ||
key: request.key | ||
} | ||
return tunnelOptions | ||
} | ||
function constructTunnelFnName(uri, proxy) { | ||
var uriProtocol = (uri.protocol === 'https:' ? 'https' : 'http') | ||
var proxyProtocol = (proxy.protocol === 'https:' ? 'Https' : 'Http') | ||
return [uriProtocol, proxyProtocol].join('Over') | ||
} | ||
function getTunnelFn(request) { | ||
var uri = request.uri | ||
var proxy = request.proxy | ||
var tunnelFnName = constructTunnelFnName(uri, proxy) | ||
return tunnel[tunnelFnName] | ||
} | ||
// Decide the proper request proxy to use based on the request URI object and the | ||
// environmental variables (NO_PROXY, HTTP_PROXY, etc.) | ||
function getProxyFromURI(uri) { | ||
// respect NO_PROXY environment variables (see: http://lynx.isc.org/current/breakout/lynx_help/keystrokes/environments.html) | ||
var noProxy = process.env.NO_PROXY || process.env.no_proxy || null | ||
// easy case first - if NO_PROXY is '*' | ||
if (noProxy === '*') { | ||
return null | ||
} | ||
// otherwise, parse the noProxy value to see if it applies to the URL | ||
if (noProxy !== null) { | ||
var noProxyItem, hostname, port, noProxyItemParts, noProxyHost, noProxyPort, noProxyList | ||
// canonicalize the hostname, so that 'oogle.com' won't match 'google.com' | ||
hostname = uri.hostname.replace(/^\.*/, '.').toLowerCase() | ||
noProxyList = noProxy.split(',') | ||
for (var i = 0, len = noProxyList.length; i < len; i++) { | ||
noProxyItem = noProxyList[i].trim().toLowerCase() | ||
// no_proxy can be granular at the port level, which complicates things a bit. | ||
if (noProxyItem.indexOf(':') > -1) { | ||
noProxyItemParts = noProxyItem.split(':', 2) | ||
noProxyHost = noProxyItemParts[0].replace(/^\.*/, '.') | ||
noProxyPort = noProxyItemParts[1] | ||
port = uri.port || (uri.protocol === 'https:' ? '443' : '80') | ||
// we've found a match - ports are same and host ends with no_proxy entry. | ||
if (port === noProxyPort && hostname.indexOf(noProxyHost) === hostname.length - noProxyHost.length) { | ||
return null | ||
} | ||
} else { | ||
noProxyItem = noProxyItem.replace(/^\.*/, '.') | ||
if (hostname.indexOf(noProxyItem) === hostname.length - noProxyItem.length) { | ||
return null | ||
} | ||
} | ||
} | ||
} | ||
// check for HTTP(S)_PROXY environment variables | ||
if (uri.protocol === 'http:') { | ||
return process.env.HTTP_PROXY || process.env.http_proxy || null | ||
} else if (uri.protocol === 'https:') { | ||
return process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || null | ||
} | ||
// return null if all else fails (What uri protocol are you using then?) | ||
return null | ||
} | ||
// Function for properly handling a connection error | ||
function connectionErrorHandler(error) { | ||
var socket = this | ||
if (socket.res) { | ||
if (socket.res.request) { | ||
socket.res.request.emit('error', error) | ||
} else { | ||
socket.res.emit('error', error) | ||
} | ||
} else { | ||
socket._httpMessage.emit('error', error) | ||
} | ||
} | ||
// Return a simpler request object to allow serialization | ||
function requestToJSON() { | ||
var self = this | ||
return { | ||
uri: self.uri, | ||
method: self.method, | ||
headers: self.headers | ||
} | ||
} | ||
// Return a simpler response object to allow serialization | ||
function responseToJSON() { | ||
var self = this | ||
return { | ||
statusCode: self.statusCode, | ||
body: self.body, | ||
headers: self.headers, | ||
request: requestToJSON.call(self.request) | ||
} | ||
} | ||
function Request (options) { | ||
@@ -85,3 +271,5 @@ // if tunnel property of options was not given default to false | ||
var nonReserved = filterForNonReserved(reserved, options) | ||
util._extend(this, nonReserved) | ||
stream.Stream.call(self) | ||
util._extend(self, nonReserved) | ||
options = filterOutReservedFunctions(reserved, options) | ||
@@ -103,72 +291,51 @@ | ||
// Set up the tunneling agent if necessary | ||
Request.prototype.setupTunnel = function () { | ||
// Set up the tunneling agent if necessary | ||
// Only send the proxy whitelisted header names. | ||
// Turn on tunneling for the rest of request. | ||
var self = this | ||
if (typeof self.proxy === 'string') self.proxy = url.parse(self.proxy) | ||
if (!self.proxy) return false | ||
if (typeof self.proxy === 'string') { | ||
self.proxy = url.parse(self.proxy) | ||
} | ||
// Don't need to use a tunneling proxy | ||
if (!self.tunnel && self.uri.protocol !== 'https:') return false | ||
if (!self.proxy) { | ||
return false | ||
} | ||
// do the HTTP CONNECT dance using koichik/node-tunnel | ||
if (!self.tunnel && self.uri.protocol !== 'https:') { | ||
return false | ||
} | ||
// The host to tell the proxy to CONNECT to | ||
var proxyHost = self.uri.hostname + ':' | ||
if (self.uri.port) | ||
proxyHost += self.uri.port | ||
else if (self.uri.protocol === 'https:') | ||
proxyHost += '443' | ||
else | ||
proxyHost += '80' | ||
// Always include `defaultProxyHeaderExclusiveList` | ||
if (!self.proxyHeaderWhiteList) | ||
self.proxyHeaderWhiteList = defaultProxyHeaderWhiteList | ||
if (!self.proxyHeaderExclusiveList) { | ||
self.proxyHeaderExclusiveList = [] | ||
} | ||
// Only send the proxy the whitelisted header names. | ||
var proxyHeaders = Object.keys(self.headers).filter(function (h) { | ||
return self.proxyHeaderWhiteList.indexOf(h.toLowerCase()) !== -1 | ||
}).reduce(function (set, h) { | ||
set[h] = self.headers[h] | ||
return set | ||
}, {}) | ||
var proxyHeaderExclusiveList = self.proxyHeaderExclusiveList.concat(defaultProxyHeaderExclusiveList) | ||
proxyHeaders.host = proxyHost | ||
// Treat `proxyHeaderExclusiveList` as part of `proxyHeaderWhiteList` | ||
var tunnelFnName = | ||
(self.uri.protocol === 'https:' ? 'https' : 'http') + | ||
'Over' + | ||
(self.proxy.protocol === 'https:' ? 'Https' : 'Http') | ||
if (!self.proxyHeaderWhiteList) { | ||
self.proxyHeaderWhiteList = defaultProxyHeaderWhiteList | ||
} | ||
var tunnelFn = tunnel[tunnelFnName] | ||
var proxyHeaderWhiteList = self.proxyHeaderWhiteList.concat(proxyHeaderExclusiveList) | ||
var proxyAuth | ||
if (self.proxy.auth) | ||
proxyAuth = self.proxy.auth | ||
else if (self.proxyAuthorization) | ||
proxyHeaders['Proxy-Authorization'] = self.proxyAuthorization | ||
var proxyHost = constructProxyHost(self.uri) | ||
self.proxyHeaders = constructProxyHeaderWhiteList(self.headers, proxyHeaderWhiteList) | ||
self.proxyHeaders.host = proxyHost | ||
var tunnelOptions = { proxy: { host: self.proxy.hostname | ||
, port: +self.proxy.port | ||
, proxyAuth: proxyAuth | ||
, headers: proxyHeaders } | ||
, rejectUnauthorized: self.rejectUnauthorized | ||
, headers: self.headers | ||
, ca: self.ca | ||
, cert: self.cert | ||
, key: self.key} | ||
proxyHeaderExclusiveList.forEach(self.removeHeader, self) | ||
var tunnelFn = getTunnelFn(self) | ||
var tunnelOptions = construcTunnelOptions(self) | ||
self.agent = tunnelFn(tunnelOptions) | ||
// At this point, we know that the proxy will support tunneling | ||
// (or fail miserably), so we're going to tunnel all proxied requests | ||
// from here on out. | ||
self.tunnel = true | ||
return true | ||
} | ||
Request.prototype.init = function (options) { | ||
@@ -179,3 +346,5 @@ // init() contains all the code to setup the request object. | ||
var self = this | ||
if (!options) options = {} | ||
if (!options) { | ||
options = {} | ||
} | ||
self.headers = self.headers ? copy(self.headers) : {} | ||
@@ -185,13 +354,15 @@ | ||
// Never send proxy-auth to the endpoint! | ||
if (self.hasHeader('proxy-authorization')) { | ||
self.proxyAuthorization = self.getHeader('proxy-authorization') | ||
self.removeHeader('proxy-authorization') | ||
if (!self.method) { | ||
self.method = options.method || 'GET' | ||
} | ||
if (!self.method) self.method = options.method || 'GET' | ||
self.localAddress = options.localAddress | ||
if (!self.qsLib) { | ||
self.qsLib = (options.useQuerystring ? querystring : qs) | ||
} | ||
debug(options) | ||
if (!self.pool && self.pool !== false) self.pool = globalPool | ||
if (!self.pool && self.pool !== false) { | ||
self.pool = globalPool | ||
} | ||
self.dests = self.dests || [] | ||
@@ -204,3 +375,5 @@ self.__isRequestRequest = true | ||
self.callback = function () { | ||
if (self._callbackCalled) return // Print a warning maybe? | ||
if (self._callbackCalled) { | ||
return // Print a warning maybe? | ||
} | ||
self._callbackCalled = true | ||
@@ -213,4 +386,4 @@ self._callback.apply(self, arguments) | ||
if (self.url && !self.uri) { | ||
// People use this property instead all the time so why not just support it. | ||
// People use this property instead all the time, so support it | ||
if (!self.uri && self.url) { | ||
self.uri = self.url | ||
@@ -220,9 +393,32 @@ delete self.url | ||
// A URI is needed by this point, throw if we haven't been able to get one | ||
if (!self.uri) { | ||
// this will throw if unhandled but is handleable when in a redirect | ||
return self.emit('error', new Error("options.uri is a required argument")) | ||
} else if (typeof self.uri === "string") { | ||
return self.emit('error', new Error('options.uri is a required argument')) | ||
} | ||
// If a string URI/URL was given, parse it into a URL object | ||
if(typeof self.uri === 'string') { | ||
self.uri = url.parse(self.uri) | ||
} | ||
// DEPRECATED: Warning for users of the old Unix Sockets URL Scheme | ||
if (self.uri.protocol === 'unix:') { | ||
return self.emit('error', new Error('`unix://` URL scheme is no longer supported. Please use the format `http://unix:SOCKET:PATH`')) | ||
} | ||
// Support Unix Sockets | ||
if(self.uri.host === 'unix') { | ||
// Get the socket & request paths from the URL | ||
var unixParts = self.uri.path.split(':') | ||
, host = unixParts[0] | ||
, path = unixParts[1] | ||
// Apply unix properties to request | ||
self.socketPath = host | ||
self.uri.pathname = path | ||
self.uri.path = path | ||
self.uri.host = host | ||
self.uri.hostname = host | ||
self.uri.isUnix = true | ||
} | ||
if (self.strictSSL === false) { | ||
@@ -233,48 +429,3 @@ self.rejectUnauthorized = false | ||
if(!self.hasOwnProperty('proxy')) { | ||
// check for HTTP(S)_PROXY environment variables | ||
if(self.uri.protocol === "http:") { | ||
self.proxy = process.env.HTTP_PROXY || process.env.http_proxy || null; | ||
} else if(self.uri.protocol === "https:") { | ||
self.proxy = process.env.HTTPS_PROXY || process.env.https_proxy || | ||
process.env.HTTP_PROXY || process.env.http_proxy || null; | ||
} | ||
// respect NO_PROXY environment variables | ||
// ref: http://lynx.isc.org/current/breakout/lynx_help/keystrokes/environments.html | ||
var noProxy = process.env.NO_PROXY || process.env.no_proxy || null | ||
// easy case first - if NO_PROXY is '*' | ||
if (noProxy === '*') { | ||
self.proxy = null | ||
} else if (noProxy !== null) { | ||
var noProxyItem, hostname, port, noProxyItemParts, noProxyHost, noProxyPort, noProxyList | ||
// canonicalize the hostname, so that 'oogle.com' won't match 'google.com' | ||
hostname = self.uri.hostname.replace(/^\.*/, '.').toLowerCase() | ||
noProxyList = noProxy.split(',') | ||
for (var i = 0, len = noProxyList.length; i < len; i++) { | ||
noProxyItem = noProxyList[i].trim().toLowerCase() | ||
// no_proxy can be granular at the port level, which complicates things a bit. | ||
if (noProxyItem.indexOf(':') > -1) { | ||
noProxyItemParts = noProxyItem.split(':', 2) | ||
noProxyHost = noProxyItemParts[0].replace(/^\.*/, '.') | ||
noProxyPort = noProxyItemParts[1] | ||
port = self.uri.port || (self.uri.protocol === 'https:' ? '443' : '80') | ||
if (port === noProxyPort && hostname.indexOf(noProxyHost) === hostname.length - noProxyHost.length) { | ||
// we've found a match - ports are same and host ends with no_proxy entry. | ||
self.proxy = null | ||
break | ||
} | ||
} else { | ||
noProxyItem = noProxyItem.replace(/^\.*/, '.') | ||
if (hostname.indexOf(noProxyItem) === hostname.length - noProxyItem.length) { | ||
self.proxy = null | ||
break | ||
} | ||
} | ||
} | ||
} | ||
self.proxy = getProxyFromURI(self.uri) | ||
} | ||
@@ -290,4 +441,4 @@ | ||
if (!self.uri.host && self.uri.protocol !== 'unix:') { | ||
// Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar | ||
if (!(self.uri.host || (self.uri.hostname && self.uri.port)) && !self.uri.isUnix) { | ||
// Invalid URI: it may generate lot of bad errors, like 'TypeError: Cannot call method `indexOf` of undefined' in CookieJar | ||
// Detect and reject it as soon as possible | ||
@@ -309,16 +460,19 @@ var faultyUri = url.format(self.uri) | ||
self.allowRedirect = (typeof self.followRedirect === 'function') ? self.followRedirect : function(response) { | ||
return true; | ||
}; | ||
self.followRedirect = (self.followRedirect !== undefined) ? !!self.followRedirect : true | ||
return true | ||
} | ||
self.followRedirects = (self.followRedirect !== undefined) ? !!self.followRedirect : true | ||
self.followAllRedirects = (self.followAllRedirects !== undefined) ? self.followAllRedirects : false | ||
if (self.followRedirect || self.followAllRedirects) | ||
if (self.followRedirects || self.followAllRedirects) { | ||
self.redirects = self.redirects || [] | ||
} | ||
self.setHost = false | ||
if (!self.hasHeader('host')) { | ||
self.setHeader('host', self.uri.hostname) | ||
var hostHeaderName = self.originalHostHeaderName || 'host' | ||
self.setHeader(hostHeaderName, self.uri.hostname) | ||
if (self.uri.port) { | ||
if ( !(self.uri.port === 80 && self.uri.protocol === 'http:') && | ||
!(self.uri.port === 443 && self.uri.protocol === 'https:') ) | ||
self.setHeader('host', self.getHeader('host') + (':' + self.uri.port) ) | ||
!(self.uri.port === 443 && self.uri.protocol === 'https:') ) { | ||
self.setHeader(hostHeaderName, self.getHeader('host') + (':' + self.uri.port) ) | ||
} | ||
} | ||
@@ -343,323 +497,234 @@ self.setHost = true | ||
self.clientErrorHandler = function (error) { | ||
if (self._aborted) return | ||
if (self.req && self.req._reusedSocket && error.code === 'ECONNRESET' | ||
&& self.agent.addRequestNoreuse) { | ||
self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } | ||
self.start() | ||
self.req.end() | ||
return | ||
} | ||
if (self.timeout && self.timeoutTimer) { | ||
clearTimeout(self.timeoutTimer) | ||
self.timeoutTimer = null | ||
} | ||
self.emit('error', error) | ||
if (options.form) { | ||
self.form(options.form) | ||
} | ||
self._parserErrorHandler = function (error) { | ||
if (this.res) { | ||
if (this.res.request) { | ||
this.res.request.emit('error', error) | ||
if (options.formData) { | ||
var formData = options.formData | ||
var requestForm = self.form() | ||
var appendFormValue = function (key, value) { | ||
if (value.hasOwnProperty('value') && value.hasOwnProperty('options')) { | ||
requestForm.append(key, value.value, value.options) | ||
} else { | ||
this.res.emit('error', error) | ||
requestForm.append(key, value) | ||
} | ||
} else { | ||
this._httpMessage.emit('error', error) | ||
} | ||
} | ||
self._buildRequest = function(){ | ||
var self = this; | ||
if (options.form) { | ||
self.form(options.form) | ||
} | ||
if (options.formData) { | ||
var formData = options.formData | ||
var requestForm = self.form() | ||
for (var formKey in formData) { | ||
if (formData.hasOwnProperty(formKey)) { | ||
requestForm.append(formKey, formData[formKey]) | ||
for (var formKey in formData) { | ||
if (formData.hasOwnProperty(formKey)) { | ||
var formValue = formData[formKey] | ||
if (formValue instanceof Array) { | ||
for (var j = 0; j < formValue.length; j++) { | ||
appendFormValue(formKey, formValue[j]) | ||
} | ||
} else { | ||
appendFormValue(formKey, formValue) | ||
} | ||
} | ||
} | ||
} | ||
if (options.qs) self.qs(options.qs) | ||
if (options.qs) { | ||
self.qs(options.qs) | ||
} | ||
if (self.uri.path) { | ||
self.path = self.uri.path | ||
} else { | ||
self.path = self.uri.pathname + (self.uri.search || "") | ||
} | ||
if (self.uri.path) { | ||
self.path = self.uri.path | ||
} else { | ||
self.path = self.uri.pathname + (self.uri.search || '') | ||
} | ||
if (self.path.length === 0) self.path = '/' | ||
if (self.path.length === 0) { | ||
self.path = '/' | ||
} | ||
// Auth must happen last in case signing is dependent on other headers | ||
if (options.oauth) { | ||
self.oauth(options.oauth) | ||
} | ||
// Auth must happen last in case signing is dependent on other headers | ||
if (options.oauth) { | ||
self.oauth(options.oauth) | ||
} | ||
if (options.aws) { | ||
self.aws(options.aws) | ||
} | ||
if (options.aws) { | ||
self.aws(options.aws) | ||
} | ||
if (options.hawk) { | ||
self.hawk(options.hawk) | ||
} | ||
if (options.hawk) { | ||
self.hawk(options.hawk) | ||
} | ||
if (options.httpSignature) { | ||
self.httpSignature(options.httpSignature) | ||
} | ||
if (options.httpSignature) { | ||
self.httpSignature(options.httpSignature) | ||
if (options.auth) { | ||
if (Object.prototype.hasOwnProperty.call(options.auth, 'username')) { | ||
options.auth.user = options.auth.username | ||
} | ||
if (Object.prototype.hasOwnProperty.call(options.auth, 'password')) { | ||
options.auth.pass = options.auth.password | ||
} | ||
if (options.auth) { | ||
if (Object.prototype.hasOwnProperty.call(options.auth, 'username')) options.auth.user = options.auth.username | ||
if (Object.prototype.hasOwnProperty.call(options.auth, 'password')) options.auth.pass = options.auth.password | ||
self.auth( | ||
options.auth.user, | ||
options.auth.pass, | ||
options.auth.sendImmediately, | ||
options.auth.bearer | ||
) | ||
} | ||
self.auth( | ||
options.auth.user, | ||
options.auth.pass, | ||
options.auth.sendImmediately, | ||
options.auth.bearer | ||
) | ||
} | ||
if (self.gzip && !self.hasHeader('accept-encoding')) { | ||
self.setHeader('accept-encoding', 'gzip') | ||
} | ||
if (self.gzip && !self.hasHeader('accept-encoding')) { | ||
self.setHeader('accept-encoding', 'gzip') | ||
} | ||
if (self.uri.auth && !self.hasHeader('authorization')) { | ||
var uriAuthPieces = self.uri.auth.split(':').map(function(item){ return querystring.unescape(item) }) | ||
self.auth(uriAuthPieces[0], uriAuthPieces.slice(1).join(':'), true) | ||
} | ||
if (self.uri.auth && !self.hasHeader('authorization')) { | ||
var uriAuthPieces = self.uri.auth.split(':').map(function(item){ return querystring.unescape(item) }) | ||
self.auth(uriAuthPieces[0], uriAuthPieces.slice(1).join(':'), true) | ||
} | ||
if (!self.tunnel && self.proxy && self.proxy.auth && !self.hasHeader('proxy-authorization')) { | ||
var proxyAuthPieces = self.proxy.auth.split(':').map(function(item){ | ||
return querystring.unescape(item) | ||
}) | ||
var authHeader = 'Basic ' + toBase64(proxyAuthPieces.join(':')) | ||
self.setHeader('proxy-authorization', authHeader) | ||
} | ||
if (self.proxy && !self.tunnel) { | ||
if (self.proxy.auth && !self.proxyAuthorization) { | ||
var proxyAuthPieces = self.proxy.auth.split(':').map(function(item){ | ||
return querystring.unescape(item) | ||
}) | ||
var authHeader = 'Basic ' + toBase64(proxyAuthPieces.join(':')) | ||
self.proxyAuthorization = authHeader | ||
} | ||
if (self.proxyAuthorization) | ||
self.setHeader('proxy-authorization', self.proxyAuthorization) | ||
} | ||
if (self.proxy && !self.tunnel) { | ||
self.path = (self.uri.protocol + '//' + self.uri.host + self.path) | ||
} | ||
if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path) | ||
if (options.json) { | ||
self.json(options.json) | ||
} else if (options.multipart) { | ||
self.boundary = uuid() | ||
self.multipart(options.multipart) | ||
} | ||
if (options.json) { | ||
self.json(options.json) | ||
} else if (options.multipart) { | ||
self.boundary = uuid() | ||
self.multipart(options.multipart) | ||
} | ||
if (self.body) { | ||
var length = 0 | ||
if (!Buffer.isBuffer(self.body)) { | ||
if (Array.isArray(self.body)) { | ||
for (var i = 0; i < self.body.length; i++) { | ||
length += self.body[i].length | ||
} | ||
} else { | ||
self.body = new Buffer(self.body) | ||
length = self.body.length | ||
if (self.body) { | ||
var length = 0 | ||
if (!Buffer.isBuffer(self.body)) { | ||
if (Array.isArray(self.body)) { | ||
for (var i = 0; i < self.body.length; i++) { | ||
length += self.body[i].length | ||
} | ||
} else { | ||
self.body = new Buffer(self.body) | ||
length = self.body.length | ||
} | ||
if (length) { | ||
if (!self.hasHeader('content-length')) self.setHeader('content-length', length) | ||
} else { | ||
throw new Error('Argument error, options.body.') | ||
} else { | ||
length = self.body.length | ||
} | ||
if (length) { | ||
if (!self.hasHeader('content-length')) { | ||
self.setHeader('content-length', length) | ||
} | ||
} else { | ||
throw new Error('Argument error, options.body.') | ||
} | ||
} | ||
var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol | ||
, defaultModules = {'http:':http, 'https:':https, 'unix:':http} | ||
, httpModules = self.httpModules || {} | ||
; | ||
self.httpModule = httpModules[protocol] || defaultModules[protocol] | ||
var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol | ||
, defaultModules = {'http:':http, 'https:':https} | ||
, httpModules = self.httpModules || {} | ||
if (!self.httpModule) return this.emit('error', new Error("Invalid protocol: " + protocol)) | ||
self.httpModule = httpModules[protocol] || defaultModules[protocol] | ||
if (options.ca) self.ca = options.ca | ||
if (!self.httpModule) { | ||
return self.emit('error', new Error('Invalid protocol: ' + protocol)) | ||
} | ||
if (!self.agent) { | ||
if (options.agentOptions) self.agentOptions = options.agentOptions | ||
if (options.ca) { | ||
self.ca = options.ca | ||
} | ||
if (options.agentClass) { | ||
self.agentClass = options.agentClass | ||
} else if (options.forever) { | ||
self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL | ||
} else { | ||
self.agentClass = self.httpModule.Agent | ||
} | ||
if (!self.agent) { | ||
if (options.agentOptions) { | ||
self.agentOptions = options.agentOptions | ||
} | ||
if (self.pool === false) { | ||
self.agent = false | ||
if (options.agentClass) { | ||
self.agentClass = options.agentClass | ||
} else if (options.forever) { | ||
self.agentClass = protocol === 'http:' ? ForeverAgent : ForeverAgent.SSL | ||
} else { | ||
self.agent = self.agent || self.getAgent() | ||
if (self.maxSockets) { | ||
// Don't use our pooling if node has the refactored client | ||
self.agent.maxSockets = self.maxSockets | ||
} | ||
if (self.pool.maxSockets) { | ||
// Don't use our pooling if node has the refactored client | ||
self.agent.maxSockets = self.pool.maxSockets | ||
} | ||
self.agentClass = self.httpModule.Agent | ||
} | ||
} | ||
self.on('pipe', function (src) { | ||
if (self.ntick && self._started) throw new Error("You cannot pipe to this stream after the outbound request has started.") | ||
self.src = src | ||
if (isReadStream(src)) { | ||
if (!self.hasHeader('content-type')) self.setHeader('content-type', mime.lookup(src.path)) | ||
} else { | ||
if (src.headers) { | ||
for (var i in src.headers) { | ||
if (!self.hasHeader(i)) { | ||
self.setHeader(i, src.headers[i]) | ||
} | ||
} | ||
} | ||
if (self._json && !self.hasHeader('content-type')) | ||
self.setHeader('content-type', 'application/json') | ||
if (src.method && !self.explicitMethod) { | ||
self.method = src.method | ||
} | ||
if (self.pool === false) { | ||
self.agent = false | ||
} else { | ||
self.agent = self.agent || self.getNewAgent() | ||
} | ||
self.on('pipe', function (src) { | ||
if (self.ntick && self._started) { | ||
throw new Error('You cannot pipe to this stream after the outbound request has started.') | ||
} | ||
self.src = src | ||
if (isReadStream(src)) { | ||
if (!self.hasHeader('content-type')) { | ||
self.setHeader('content-type', mime.lookup(src.path)) | ||
} | ||
// self.on('pipe', function () { | ||
// console.error("You have already piped to this stream. Pipeing twice is likely to break the request.") | ||
// }) | ||
}) | ||
process.nextTick(function () { | ||
if (self._aborted) return | ||
var end = function () { | ||
if (self._form) { | ||
self._form.pipe(self) | ||
} | ||
if (self.body) { | ||
if (Array.isArray(self.body)) { | ||
self.body.forEach(function (part) { | ||
self.write(part) | ||
}) | ||
} else { | ||
self.write(self.body) | ||
} else { | ||
if (src.headers) { | ||
for (var i in src.headers) { | ||
if (!self.hasHeader(i)) { | ||
self.setHeader(i, src.headers[i]) | ||
} | ||
self.end() | ||
} else if (self.requestBodyStream) { | ||
console.warn("options.requestBodyStream is deprecated, please pass the request object to stream.pipe.") | ||
self.requestBodyStream.pipe(self) | ||
} else if (!self.src) { | ||
if (self.method !== 'GET' && typeof self.method !== 'undefined') { | ||
self.setHeader('content-length', 0) | ||
} | ||
self.end() | ||
} | ||
} | ||
if (self._form && !self.hasHeader('content-length')) { | ||
// Before ending the request, we had to compute the length of the whole form, asyncly | ||
self.setHeader(self._form.getHeaders()) | ||
self._form.getLength(function (err, length) { | ||
if (!err) { | ||
self.setHeader('content-length', length) | ||
} | ||
end() | ||
}) | ||
} else { | ||
end() | ||
if (self._json && !self.hasHeader('content-type')) { | ||
self.setHeader('content-type', 'application/json') | ||
} | ||
if (src.method && !self.explicitMethod) { | ||
self.method = src.method | ||
} | ||
} | ||
self.ntick = true | ||
}) | ||
// self.on('pipe', function () { | ||
// console.error('You have already piped to this stream. Pipeing twice is likely to break the request.') | ||
// }) | ||
}) | ||
} // End _buildRequest | ||
self._handleUnixSocketURI = function(self){ | ||
// Parse URI and extract a socket path (tested as a valid socket using net.connect), and a http style path suffix | ||
// Thus http requests can be made to a socket using the uri unix://tmp/my.socket/urlpath | ||
// and a request for '/urlpath' will be sent to the unix socket at /tmp/my.socket | ||
self.unixsocket = true; | ||
var full_path = self.uri.href.replace(self.uri.protocol + '/', ''); | ||
var lookup = full_path.split('/'); | ||
var lookup_table = {}; | ||
do { lookup_table[lookup.join('/')] = {} } while(lookup.pop()) | ||
for (var r in lookup_table){ | ||
try_next(r); | ||
defer(function () { | ||
if (self._aborted) { | ||
return | ||
} | ||
function try_next(table_row) { | ||
var client = net.connect( table_row ); | ||
client.path = table_row | ||
client.on('error', function(){ lookup_table[this.path].error_connecting = true; this.end(); }); | ||
client.on('connect', function(){ lookup_table[this.path].error_connecting = false; this.end(); }); | ||
table_row.client = client; | ||
var end = function () { | ||
if (self._form) { | ||
self._form.pipe(self) | ||
} | ||
if (self._multipart) { | ||
self._multipart.pipe(self) | ||
} | ||
if (self.body) { | ||
self.write(self.body) | ||
self.end() | ||
} else if (self.requestBodyStream) { | ||
console.warn('options.requestBodyStream is deprecated, please pass the request object to stream.pipe.') | ||
self.requestBodyStream.pipe(self) | ||
} else if (!self.src) { | ||
if (self.method !== 'GET' && typeof self.method !== 'undefined') { | ||
self.setHeader('content-length', 0) | ||
} | ||
self.end() | ||
} | ||
} | ||
wait_for_socket_response(); | ||
var response_counter = 0; | ||
function wait_for_socket_response(){ | ||
var detach; | ||
if(typeof setImmediate === 'undefined') detach = process.nextTick | ||
else detach = setImmediate; | ||
detach(function(){ | ||
// counter to prevent infinite blocking waiting for an open socket to be found. | ||
response_counter++; | ||
var trying = false; | ||
for (r in lookup_table){ | ||
if(typeof lookup_table[r].error_connecting === 'undefined') | ||
trying = true; | ||
if (self._form && !self.hasHeader('content-length')) { | ||
// Before ending the request, we had to compute the length of the whole form, asyncly | ||
self.setHeader(self._form.getHeaders()) | ||
self._form.getLength(function (err, length) { | ||
if (!err) { | ||
self.setHeader('content-length', length) | ||
} | ||
if(trying && response_counter < 1000) | ||
wait_for_socket_response() | ||
else | ||
set_socket_properties(); | ||
end() | ||
}) | ||
} else { | ||
end() | ||
} | ||
function set_socket_properties(){ | ||
var host; | ||
for (r in lookup_table){ | ||
if(lookup_table[r].error_connecting === false){ | ||
host = r | ||
} | ||
} | ||
if(!host){ | ||
self.emit('error', new Error("Failed to connect to any socket in " + full_path)) | ||
} | ||
var path = full_path.replace(host, '') | ||
self.ntick = true | ||
}) | ||
self.socketPath = host | ||
self.uri.pathname = path | ||
self.uri.href = path | ||
self.uri.path = path | ||
self.host = '' | ||
self.hostname = '' | ||
delete self.host | ||
delete self.hostname | ||
self._buildRequest(); | ||
} | ||
} | ||
// Intercept UNIX protocol requests to change properties to match socket | ||
if(/^unix:/.test(self.uri.protocol)){ | ||
self._handleUnixSocketURI(self); | ||
} else { | ||
self._buildRequest(); | ||
} | ||
} | ||
@@ -678,3 +743,5 @@ | ||
if (self.proxy) { | ||
if (self.setupTunnel()) return | ||
if (self.setupTunnel()) { | ||
return | ||
} | ||
} | ||
@@ -696,3 +763,5 @@ | ||
// if there's an agent, we need to get a new one. | ||
if (self.agent) self.agent = self.getAgent() | ||
if (self.agent) { | ||
self.agent = self.getNewAgent() | ||
} | ||
@@ -717,3 +786,3 @@ } else { | ||
self.agent = null | ||
self.agent = self.getAgent() | ||
self.agent = self.getNewAgent() | ||
} | ||
@@ -723,19 +792,30 @@ } | ||
Request.prototype.getAgent = function () { | ||
var Agent = this.agentClass | ||
Request.prototype.getNewAgent = function () { | ||
var self = this | ||
var Agent = self.agentClass | ||
var options = {} | ||
if (this.agentOptions) { | ||
for (var i in this.agentOptions) { | ||
options[i] = this.agentOptions[i] | ||
if (self.agentOptions) { | ||
for (var i in self.agentOptions) { | ||
options[i] = self.agentOptions[i] | ||
} | ||
} | ||
if (this.ca) options.ca = this.ca | ||
if (this.ciphers) options.ciphers = this.ciphers | ||
if (this.secureProtocol) options.secureProtocol = this.secureProtocol | ||
if (this.secureOptions) options.secureOptions = this.secureOptions | ||
if (typeof this.rejectUnauthorized !== 'undefined') options.rejectUnauthorized = this.rejectUnauthorized | ||
if (self.ca) { | ||
options.ca = self.ca | ||
} | ||
if (self.ciphers) { | ||
options.ciphers = self.ciphers | ||
} | ||
if (self.secureProtocol) { | ||
options.secureProtocol = self.secureProtocol | ||
} | ||
if (self.secureOptions) { | ||
options.secureOptions = self.secureOptions | ||
} | ||
if (typeof self.rejectUnauthorized !== 'undefined') { | ||
options.rejectUnauthorized = self.rejectUnauthorized | ||
} | ||
if (this.cert && this.key) { | ||
options.key = this.key | ||
options.cert = this.cert | ||
if (self.cert && self.key) { | ||
options.key = self.key | ||
options.cert = self.cert | ||
} | ||
@@ -746,21 +826,18 @@ | ||
// different types of agents are in different pools | ||
if (Agent !== this.httpModule.Agent) { | ||
if (Agent !== self.httpModule.Agent) { | ||
poolKey += Agent.name | ||
} | ||
if (!this.httpModule.globalAgent) { | ||
// node 0.4.x | ||
options.host = this.host | ||
options.port = this.port | ||
if (poolKey) poolKey += ':' | ||
poolKey += this.host + ':' + this.port | ||
// ca option is only relevant if proxy or destination are https | ||
var proxy = self.proxy | ||
if (typeof proxy === 'string') { | ||
proxy = url.parse(proxy) | ||
} | ||
var isHttps = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:' | ||
// ca option is only relevant if proxy or destination are https | ||
var proxy = this.proxy | ||
if (typeof proxy === 'string') proxy = url.parse(proxy) | ||
var isHttps = (proxy && proxy.protocol === 'https:') || this.uri.protocol === 'https:' | ||
if (isHttps) { | ||
if (options.ca) { | ||
if (poolKey) poolKey += ':' | ||
if (poolKey) { | ||
poolKey += ':' | ||
} | ||
poolKey += options.ca | ||
@@ -770,11 +847,16 @@ } | ||
if (typeof options.rejectUnauthorized !== 'undefined') { | ||
if (poolKey) poolKey += ':' | ||
if (poolKey) { | ||
poolKey += ':' | ||
} | ||
poolKey += options.rejectUnauthorized | ||
} | ||
if (options.cert) | ||
if (options.cert) { | ||
poolKey += options.cert.toString('ascii') + options.key.toString('ascii') | ||
} | ||
if (options.ciphers) { | ||
if (poolKey) poolKey += ':' | ||
if (poolKey) { | ||
poolKey += ':' | ||
} | ||
poolKey += options.ciphers | ||
@@ -784,3 +866,5 @@ } | ||
if (options.secureProtocol) { | ||
if (poolKey) poolKey += ':' | ||
if (poolKey) { | ||
poolKey += ':' | ||
} | ||
poolKey += options.secureProtocol | ||
@@ -790,3 +874,5 @@ } | ||
if (options.secureOptions) { | ||
if (poolKey) poolKey += ':' | ||
if (poolKey) { | ||
poolKey += ':' | ||
} | ||
poolKey += options.secureOptions | ||
@@ -796,14 +882,20 @@ } | ||
if (this.pool === globalPool && !poolKey && Object.keys(options).length === 0 && this.httpModule.globalAgent) { | ||
if (self.pool === globalPool && !poolKey && Object.keys(options).length === 0 && self.httpModule.globalAgent) { | ||
// not doing anything special. Use the globalAgent | ||
return this.httpModule.globalAgent | ||
return self.httpModule.globalAgent | ||
} | ||
// we're using a stored agent. Make sure it's protocol-specific | ||
poolKey = this.uri.protocol + poolKey | ||
poolKey = self.uri.protocol + poolKey | ||
// generate a new agent for this setting if none yet exists | ||
if (!this.pool[poolKey]) this.pool[poolKey] = new Agent(options) | ||
if (!self.pool[poolKey]) { | ||
self.pool[poolKey] = new Agent(options) | ||
// properly set maxSockets on new agents | ||
if (self.pool.maxSockets) { | ||
self.pool[poolKey].maxSockets = self.pool.maxSockets | ||
} | ||
} | ||
return this.pool[poolKey] | ||
return self.pool[poolKey] | ||
} | ||
@@ -816,3 +908,5 @@ | ||
if (self._aborted) return | ||
if (self._aborted) { | ||
return | ||
} | ||
@@ -836,3 +930,3 @@ self._started = true | ||
debug('make request', self.uri.href) | ||
self.req = self.httpModule.request(reqOptions, self.onResponse.bind(self)) | ||
self.req = self.httpModule.request(reqOptions) | ||
@@ -842,5 +936,5 @@ if (self.timeout && !self.timeoutTimer) { | ||
self.abort() | ||
var e = new Error("ETIMEDOUT") | ||
e.code = "ETIMEDOUT" | ||
self.emit("error", e) | ||
var e = new Error('ETIMEDOUT') | ||
e.code = 'ETIMEDOUT' | ||
self.emit('error', e) | ||
}, self.timeout) | ||
@@ -854,5 +948,5 @@ | ||
self.req.abort() | ||
var e = new Error("ESOCKETTIMEDOUT") | ||
e.code = "ESOCKETTIMEDOUT" | ||
self.emit("error", e) | ||
var e = new Error('ESOCKETTIMEDOUT') | ||
e.code = 'ESOCKETTIMEDOUT' | ||
self.emit('error', e) | ||
} | ||
@@ -863,3 +957,4 @@ }) | ||
self.req.on('error', self.clientErrorHandler) | ||
self.req.on('response', self.onRequestResponse.bind(self)) | ||
self.req.on('error', self.onRequestError.bind(self)) | ||
self.req.on('drain', function() { | ||
@@ -873,17 +968,39 @@ self.emit('drain') | ||
self.on('end', function() { | ||
if ( self.req.connection ) self.req.connection.removeListener('error', self._parserErrorHandler) | ||
if ( self.req.connection ) { | ||
self.req.connection.removeListener('error', connectionErrorHandler) | ||
} | ||
}) | ||
self.emit('request', self.req) | ||
} | ||
Request.prototype.onResponse = function (response) { | ||
Request.prototype.onRequestError = function (error) { | ||
var self = this | ||
debug('onResponse', self.uri.href, response.statusCode, response.headers) | ||
if (self._aborted) { | ||
return | ||
} | ||
if (self.req && self.req._reusedSocket && error.code === 'ECONNRESET' | ||
&& self.agent.addRequestNoreuse) { | ||
self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } | ||
self.start() | ||
self.req.end() | ||
return | ||
} | ||
if (self.timeout && self.timeoutTimer) { | ||
clearTimeout(self.timeoutTimer) | ||
self.timeoutTimer = null | ||
} | ||
self.emit('error', error) | ||
} | ||
Request.prototype.onRequestResponse = function (response) { | ||
var self = this | ||
debug('onRequestResponse', self.uri.href, response.statusCode, response.headers) | ||
response.on('end', function() { | ||
debug('response end', self.uri.href, response.statusCode, response.headers) | ||
}); | ||
}) | ||
// The check on response.connection is a workaround for browserify. | ||
if (response.connection && response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) { | ||
if (response.connection && response.connection.listeners('error').indexOf(connectionErrorHandler) === -1) { | ||
response.connection.setMaxListeners(0) | ||
response.connection.once('error', self._parserErrorHandler) | ||
response.connection.once('error', connectionErrorHandler) | ||
} | ||
@@ -895,5 +1012,8 @@ if (self._aborted) { | ||
} | ||
if (self._paused) response.pause() | ||
// response.resume should be defined, but check anyway before calling. Workaround for browserify. | ||
else if (response.resume) response.resume() | ||
if (self._paused) { | ||
response.pause() | ||
} else if (response.resume) { | ||
// response.resume should be defined, but check anyway before calling. Workaround for browserify. | ||
response.resume() | ||
} | ||
@@ -909,3 +1029,3 @@ self.response = response | ||
debug('strict ssl error', self.uri.href) | ||
var sslErr = response.hasOwnProperty('client') ? response.client.authorizationError : self.uri.href + " does not support SSL"; | ||
var sslErr = response.hasOwnProperty('client') ? response.client.authorizationError : self.uri.href + ' does not support SSL' | ||
self.emit('error', new Error('SSL Error: ' + sslErr)) | ||
@@ -915,3 +1035,13 @@ return | ||
if (self.setHost) self.removeHeader('host') | ||
// Save the original host before any redirect (if it changes, we need to | ||
// remove any authorization headers). Also remember the case of the header | ||
// name because lots of broken servers expect Host instead of host and we | ||
// want the caller to be able to specify this. | ||
self.originalHost = self.getHeader('host') | ||
if (!self.originalHostHeaderName) { | ||
self.originalHostHeaderName = self.hasHeader('host') | ||
} | ||
if (self.setHost) { | ||
self.removeHeader('host') | ||
} | ||
if (self.timeout && self.timeoutTimer) { | ||
@@ -922,9 +1052,9 @@ clearTimeout(self.timeoutTimer) | ||
var targetCookieJar = (self._jar && self._jar.setCookie) ? self._jar : globalCookieJar; | ||
var targetCookieJar = (self._jar && self._jar.setCookie) ? self._jar : globalCookieJar | ||
var addCookie = function (cookie) { | ||
//set the cookie if it's domain in the href's domain. | ||
try { | ||
targetCookieJar.setCookie(cookie, self.uri.href, {ignoreError: true}); | ||
targetCookieJar.setCookie(cookie, self.uri.href, {ignoreError: true}) | ||
} catch (e) { | ||
self.emit('error', e); | ||
self.emit('error', e) | ||
} | ||
@@ -937,4 +1067,7 @@ } | ||
var headerName = response.caseless.has('set-cookie') | ||
if (Array.isArray(response.headers[headerName])) response.headers[headerName].forEach(addCookie) | ||
else addCookie(response.headers[headerName]) | ||
if (Array.isArray(response.headers[headerName])) { | ||
response.headers[headerName].forEach(addCookie) | ||
} else { | ||
addCookie(response.headers[headerName]) | ||
} | ||
} | ||
@@ -949,3 +1082,3 @@ | ||
redirectTo = location | ||
} else if (self.followRedirect) { | ||
} else if (self.followRedirects) { | ||
switch (self.method) { | ||
@@ -996,4 +1129,6 @@ case 'PATCH': | ||
var match = re.exec(authHeader) | ||
if (!match) break | ||
challenge[match[1]] = match[2] || match[3]; | ||
if (!match) { | ||
break | ||
} | ||
challenge[match[1]] = match[2] || match[3] | ||
} | ||
@@ -1044,6 +1179,8 @@ | ||
// to us at this point. | ||
if (self._paused) response.resume() | ||
if (self._paused) { | ||
response.resume() | ||
} | ||
if (self._redirectsFollowed >= self.maxRedirects) { | ||
self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop " + self.uri.href)) | ||
self.emit('error', new Error('Exceeded maxRedirects. Probably stuck in a redirect loop ' + self.uri.href)) | ||
return | ||
@@ -1070,3 +1207,5 @@ } | ||
) | ||
if (self.followAllRedirects && response.statusCode !== 401 && response.statusCode !== 307) self.method = 'GET' | ||
if (self.followAllRedirects && response.statusCode !== 401 && response.statusCode !== 307) { | ||
self.method = 'GET' | ||
} | ||
// self.method = 'GET' // Force all redirects to use GET || commented out fixes #215 | ||
@@ -1086,6 +1225,12 @@ delete self.src | ||
self.removeHeader('content-length') | ||
if (self.uri.hostname !== self.originalHost.split(':')[0]) { | ||
// Remove authorization if changing hostnames (but not if just | ||
// changing ports or protocols). This matches the behavior of curl: | ||
// https://github.com/bagder/curl/blob/6beb0eee/lib/http.c#L710 | ||
self.removeHeader('authorization') | ||
} | ||
} | ||
} | ||
self.emit('redirect'); | ||
self.emit('redirect') | ||
@@ -1099,3 +1244,5 @@ self.init() | ||
response.on('close', function () { | ||
if (!self._ended) self.response.emit('end') | ||
if (!self._ended) { | ||
self.response.emit('end') | ||
} | ||
}) | ||
@@ -1109,6 +1256,6 @@ | ||
if (self.gzip) { | ||
var contentEncoding = response.headers["content-encoding"] || "identity" | ||
var contentEncoding = response.headers['content-encoding'] || 'identity' | ||
contentEncoding = contentEncoding.trim().toLowerCase() | ||
if (contentEncoding === "gzip") { | ||
if (contentEncoding === 'gzip') { | ||
dataStream = zlib.createGunzip() | ||
@@ -1119,4 +1266,4 @@ response.pipe(dataStream) | ||
// ignore any invalid values to preserve backwards-compatibility | ||
if (contentEncoding !== "identity") { | ||
debug("ignoring unrecognized Content-Encoding " + contentEncoding) | ||
if (contentEncoding !== 'identity') { | ||
debug('ignoring unrecognized Content-Encoding ' + contentEncoding) | ||
} | ||
@@ -1131,3 +1278,3 @@ dataStream = response | ||
if (self.dests.length !== 0) { | ||
console.error("Ignoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.") | ||
console.error('Ignoring encoding parameter as this stream is being piped to another stream which makes the encoding option invalid.') | ||
} else if (dataStream.setEncoding) { | ||
@@ -1149,13 +1296,13 @@ dataStream.setEncoding(self.encoding) | ||
dataStream.on("data", function (chunk) { | ||
dataStream.on('data', function (chunk) { | ||
self._destdata = true | ||
self.emit("data", chunk) | ||
self.emit('data', chunk) | ||
}) | ||
dataStream.on("end", function (chunk) { | ||
self.emit("end", chunk) | ||
dataStream.on('end', function (chunk) { | ||
self.emit('end', chunk) | ||
}) | ||
dataStream.on("error", function (error) { | ||
self.emit("error", error) | ||
dataStream.on('error', function (error) { | ||
self.emit('error', error) | ||
}) | ||
dataStream.on("close", function () {self.emit("close")}) | ||
dataStream.on('close', function () {self.emit('close')}) | ||
@@ -1165,8 +1312,11 @@ if (self.callback) { | ||
, strings = [] | ||
; | ||
self.on("data", function (chunk) { | ||
if (Buffer.isBuffer(chunk)) buffer.append(chunk) | ||
else strings.push(chunk) | ||
self.on('data', function (chunk) { | ||
if (Buffer.isBuffer(chunk)) { | ||
buffer.append(chunk) | ||
} else { | ||
strings.push(chunk) | ||
} | ||
}) | ||
self.on("end", function () { | ||
self.on('end', function () { | ||
debug('end event', self.uri.href) | ||
@@ -1190,3 +1340,3 @@ if (self._aborted) { | ||
// Strip this value out when the encoding is set to 'utf8', as upstream consumers won't expect it and it breaks JSON.parse(). | ||
if (self.encoding === 'utf8' && strings[0].length > 0 && strings[0][0] === "\uFEFF") { | ||
if (self.encoding === 'utf8' && strings[0].length > 0 && strings[0][0] === '\uFEFF') { | ||
strings[0] = strings[0].substring(1) | ||
@@ -1204,3 +1354,3 @@ } | ||
if(typeof response.body === 'undefined' && !self._json) { | ||
response.body = ""; | ||
response.body = '' | ||
} | ||
@@ -1212,3 +1362,3 @@ self.emit('complete', response, response.body) | ||
else{ | ||
self.on("end", function () { | ||
self.on('end', function () { | ||
if (self._aborted) { | ||
@@ -1218,4 +1368,4 @@ debug('aborted', self.uri.href) | ||
} | ||
self.emit('complete', response); | ||
}); | ||
self.emit('complete', response) | ||
}) | ||
} | ||
@@ -1227,16 +1377,18 @@ } | ||
Request.prototype.abort = function () { | ||
this._aborted = true | ||
var self = this | ||
self._aborted = true | ||
if (this.req) { | ||
this.req.abort() | ||
if (self.req) { | ||
self.req.abort() | ||
} | ||
else if (this.response) { | ||
this.response.abort() | ||
else if (self.response) { | ||
self.response.abort() | ||
} | ||
this.emit("abort") | ||
self.emit('abort') | ||
} | ||
Request.prototype.pipeDest = function (dest) { | ||
var response = this.response | ||
var self = this | ||
var response = self.response | ||
// Called after the response is received | ||
@@ -1246,4 +1398,8 @@ if (dest.headers && !dest.headersSent) { | ||
var ctname = response.caseless.has('content-type') | ||
if (dest.setHeader) dest.setHeader(ctname, response.headers[ctname]) | ||
else dest.headers[ctname] = response.headers[ctname] | ||
if (dest.setHeader) { | ||
dest.setHeader(ctname, response.headers[ctname]) | ||
} | ||
else { | ||
dest.headers[ctname] = response.headers[ctname] | ||
} | ||
} | ||
@@ -1253,4 +1409,7 @@ | ||
var clname = response.caseless.has('content-length') | ||
if (dest.setHeader) dest.setHeader(clname, response.headers[clname]) | ||
else dest.headers[clname] = response.headers[clname] | ||
if (dest.setHeader) { | ||
dest.setHeader(clname, response.headers[clname]) | ||
} else { | ||
dest.headers[clname] = response.headers[clname] | ||
} | ||
} | ||
@@ -1262,3 +1421,3 @@ } | ||
// of the response doesn't represent the piped content, so don't pass it. | ||
if (!this.gzip || i !== 'content-encoding') { | ||
if (!self.gzip || i !== 'content-encoding') { | ||
dest.setHeader(i, response.headers[i]) | ||
@@ -1269,9 +1428,15 @@ } | ||
} | ||
if (this.pipefilter) this.pipefilter(response, dest) | ||
if (self.pipefilter) { | ||
self.pipefilter(response, dest) | ||
} | ||
} | ||
Request.prototype.qs = function (q, clobber) { | ||
var self = this | ||
var base | ||
if (!clobber && this.uri.query) base = qs.parse(this.uri.query) | ||
else base = {} | ||
if (!clobber && self.uri.query) { | ||
base = self.qsLib.parse(self.uri.query) | ||
} else { | ||
base = {} | ||
} | ||
@@ -1282,25 +1447,26 @@ for (var i in q) { | ||
if (qs.stringify(base) === ''){ | ||
return this | ||
if (self.qsLib.stringify(base) === ''){ | ||
return self | ||
} | ||
this.uri = url.parse(this.uri.href.split('?')[0] + '?' + qs.stringify(base)) | ||
this.url = this.uri | ||
this.path = this.uri.path | ||
self.uri = url.parse(self.uri.href.split('?')[0] + '?' + self.qsLib.stringify(base)) | ||
self.url = self.uri | ||
self.path = self.uri.path | ||
return this | ||
return self | ||
} | ||
Request.prototype.form = function (form) { | ||
var self = this | ||
if (form) { | ||
this.setHeader('content-type', 'application/x-www-form-urlencoded; charset=utf-8') | ||
this.body = (typeof form === 'string') ? form.toString('utf8') : qs.stringify(form).toString('utf8') | ||
return this | ||
self.setHeader('content-type', 'application/x-www-form-urlencoded') | ||
self.body = (typeof form === 'string') ? form.toString('utf8') : self.qsLib.stringify(form).toString('utf8') | ||
return self | ||
} | ||
// create form-data object | ||
this._form = new FormData() | ||
return this._form | ||
self._form = new FormData() | ||
return self._form | ||
} | ||
Request.prototype.multipart = function (multipart) { | ||
var self = this | ||
self.body = [] | ||
self._multipart = new CombinedStream() | ||
@@ -1310,10 +1476,12 @@ if (!self.hasHeader('content-type')) { | ||
} else { | ||
var headerName = self.hasHeader('content-type'); | ||
var headerName = self.hasHeader('content-type') | ||
self.setHeader(headerName, self.headers[headerName].split(';')[0] + '; boundary=' + self.boundary) | ||
} | ||
if (!multipart.forEach) throw new Error('Argument error, options.multipart.') | ||
if (!multipart.forEach) { | ||
throw new Error('Argument error, options.multipart.') | ||
} | ||
if (self.preambleCRLF) { | ||
self.body.push(new Buffer('\r\n')) | ||
self._multipart.append('\r\n') | ||
} | ||
@@ -1323,17 +1491,19 @@ | ||
var body = part.body | ||
if(typeof body === 'undefined') throw new Error('Body attribute missing in multipart.') | ||
delete part.body | ||
if(typeof body === 'undefined') { | ||
throw new Error('Body attribute missing in multipart.') | ||
} | ||
var preamble = '--' + self.boundary + '\r\n' | ||
Object.keys(part).forEach(function (key) { | ||
if (key === 'body') { return } | ||
preamble += key + ': ' + part[key] + '\r\n' | ||
}) | ||
preamble += '\r\n' | ||
self.body.push(new Buffer(preamble)) | ||
self.body.push(new Buffer(body)) | ||
self.body.push(new Buffer('\r\n')) | ||
self._multipart.append(preamble) | ||
self._multipart.append(body) | ||
self._multipart.append('\r\n') | ||
}) | ||
self.body.push(new Buffer('--' + self.boundary + '--')) | ||
self._multipart.append('--' + self.boundary + '--') | ||
if (self.postambleCRLF) { | ||
self.body.push(new Buffer('\r\n')) | ||
self._multipart.append('\r\n') | ||
} | ||
@@ -1346,27 +1516,38 @@ | ||
if (!self.hasHeader('accept')) self.setHeader('accept', 'application/json') | ||
if (!self.hasHeader('accept')) { | ||
self.setHeader('accept', 'application/json') | ||
} | ||
this._json = true | ||
self._json = true | ||
if (typeof val === 'boolean') { | ||
if (typeof this.body === 'object') { | ||
this.body = safeStringify(this.body) | ||
if (!self.hasHeader('content-type')) | ||
if (typeof self.body === 'object') { | ||
self.body = safeStringify(self.body) | ||
if (!self.hasHeader('content-type')) { | ||
self.setHeader('content-type', 'application/json') | ||
} | ||
} | ||
} else { | ||
this.body = safeStringify(val) | ||
if (!self.hasHeader('content-type')) | ||
self.body = safeStringify(val) | ||
if (!self.hasHeader('content-type')) { | ||
self.setHeader('content-type', 'application/json') | ||
} | ||
} | ||
return this | ||
return self | ||
} | ||
Request.prototype.getHeader = function (name, headers) { | ||
var self = this | ||
var result, re, match | ||
if (!headers) headers = this.headers | ||
if (!headers) { | ||
headers = self.headers | ||
} | ||
Object.keys(headers).forEach(function (key) { | ||
if (key.length !== name.length) return | ||
if (key.length !== name.length) { | ||
return | ||
} | ||
re = new RegExp(name, 'i') | ||
match = key.match(re) | ||
if (match) result = headers[key] | ||
if (match) { | ||
result = headers[key] | ||
} | ||
}) | ||
@@ -1378,5 +1559,6 @@ return result | ||
Request.prototype.auth = function (user, pass, sendImmediately, bearer) { | ||
var self = this | ||
if (bearer !== undefined) { | ||
this._bearer = bearer | ||
this._hasAuth = true | ||
self._bearer = bearer | ||
self._hasAuth = true | ||
if (sendImmediately || typeof sendImmediately === 'undefined') { | ||
@@ -1386,6 +1568,6 @@ if (typeof bearer === 'function') { | ||
} | ||
this.setHeader('authorization', 'Bearer ' + bearer) | ||
this._sentAuth = true | ||
self.setHeader('authorization', 'Bearer ' + bearer) | ||
self._sentAuth = true | ||
} | ||
return this | ||
return self | ||
} | ||
@@ -1395,30 +1577,32 @@ if (typeof user !== 'string' || (pass !== undefined && typeof pass !== 'string')) { | ||
} | ||
this._user = user | ||
this._pass = pass | ||
this._hasAuth = true | ||
self._user = user | ||
self._pass = pass | ||
self._hasAuth = true | ||
var header = typeof pass !== 'undefined' ? user + ':' + pass : user | ||
if (sendImmediately || typeof sendImmediately === 'undefined') { | ||
this.setHeader('authorization', 'Basic ' + toBase64(header)) | ||
this._sentAuth = true | ||
self.setHeader('authorization', 'Basic ' + toBase64(header)) | ||
self._sentAuth = true | ||
} | ||
return this | ||
return self | ||
} | ||
Request.prototype.aws = function (opts, now) { | ||
var self = this | ||
if (!now) { | ||
this._aws = opts | ||
return this | ||
self._aws = opts | ||
return self | ||
} | ||
var date = new Date() | ||
this.setHeader('date', date.toUTCString()) | ||
self.setHeader('date', date.toUTCString()) | ||
var auth = | ||
{ key: opts.key | ||
, secret: opts.secret | ||
, verb: this.method.toUpperCase() | ||
, verb: self.method.toUpperCase() | ||
, date: date | ||
, contentType: this.getHeader('content-type') || '' | ||
, md5: this.getHeader('content-md5') || '' | ||
, amazonHeaders: aws.canonicalizeHeaders(this.headers) | ||
, contentType: self.getHeader('content-type') || '' | ||
, md5: self.getHeader('content-md5') || '' | ||
, amazonHeaders: aws.canonicalizeHeaders(self.headers) | ||
} | ||
var path = this.uri.path; | ||
var path = self.uri.path | ||
if (opts.bucket && path) { | ||
@@ -1434,47 +1618,58 @@ auth.resource = '/' + opts.bucket + path | ||
auth.resource = aws.canonicalizeResource(auth.resource) | ||
this.setHeader('authorization', aws.authorization(auth)) | ||
self.setHeader('authorization', aws.authorization(auth)) | ||
return this | ||
return self | ||
} | ||
Request.prototype.httpSignature = function (opts) { | ||
var req = this | ||
var self = this | ||
httpSignature.signRequest({ | ||
getHeader: function(header) { | ||
return getHeader(header, req.headers) | ||
return getHeader(header, self.headers) | ||
}, | ||
setHeader: function(header, value) { | ||
req.setHeader(header, value) | ||
self.setHeader(header, value) | ||
}, | ||
method: this.method, | ||
path: this.path | ||
method: self.method, | ||
path: self.path | ||
}, opts) | ||
debug('httpSignature authorization', this.getHeader('authorization')) | ||
debug('httpSignature authorization', self.getHeader('authorization')) | ||
return this | ||
return self | ||
} | ||
Request.prototype.hawk = function (opts) { | ||
this.setHeader('Authorization', hawk.client.header(this.uri, this.method, opts).field) | ||
var self = this | ||
self.setHeader('Authorization', hawk.client.header(self.uri, self.method, opts).field) | ||
} | ||
Request.prototype.oauth = function (_oauth) { | ||
var self = this | ||
var form, query | ||
if (this.hasHeader('content-type') && | ||
this.getHeader('content-type').slice(0, 'application/x-www-form-urlencoded'.length) === | ||
if (self.hasHeader('content-type') && | ||
self.getHeader('content-type').slice(0, 'application/x-www-form-urlencoded'.length) === | ||
'application/x-www-form-urlencoded' | ||
) { | ||
form = this.body | ||
form = self.body | ||
} | ||
if (this.uri.query) { | ||
query = this.uri.query | ||
if (self.uri.query) { | ||
query = self.uri.query | ||
} | ||
var oa = {} | ||
for (var i in _oauth) oa['oauth_' + i] = _oauth[i] | ||
if ('oauth_realm' in oa) delete oa.oauth_realm | ||
for (var i in _oauth) { | ||
oa['oauth_' + i] = _oauth[i] | ||
} | ||
if ('oauth_realm' in oa) { | ||
delete oa.oauth_realm | ||
} | ||
if (!oa.oauth_version) { | ||
oa.oauth_version = '1.0' | ||
} | ||
if (!oa.oauth_timestamp) { | ||
oa.oauth_timestamp = Math.floor( Date.now() / 1000 ).toString() | ||
} | ||
if (!oa.oauth_nonce) { | ||
oa.oauth_nonce = uuid().replace(/-/g, '') | ||
} | ||
if (!oa.oauth_version) oa.oauth_version = '1.0' | ||
if (!oa.oauth_timestamp) oa.oauth_timestamp = Math.floor( Date.now() / 1000 ).toString() | ||
if (!oa.oauth_nonce) oa.oauth_nonce = uuid().replace(/-/g, '') | ||
oa.oauth_signature_method = 'HMAC-SHA1' | ||
@@ -1487,18 +1682,19 @@ | ||
var baseurl = this.uri.protocol + '//' + this.uri.host + this.uri.pathname | ||
var params = qs.parse([].concat(query, form, qs.stringify(oa)).join('&')) | ||
var signature = oauth.hmacsign(this.method, baseurl, params, consumer_secret, token_secret) | ||
var baseurl = self.uri.protocol + '//' + self.uri.host + self.uri.pathname | ||
var params = self.qsLib.parse([].concat(query, form, self.qsLib.stringify(oa)).join('&')) | ||
var signature = oauth.hmacsign(self.method, baseurl, params, consumer_secret, token_secret) | ||
var realm = _oauth.realm ? 'realm="' + _oauth.realm + '",' : ''; | ||
var realm = _oauth.realm ? 'realm="' + _oauth.realm + '",' : '' | ||
var authHeader = 'OAuth ' + realm + | ||
Object.keys(oa).sort().map(function (i) {return i + '="' + oauth.rfc3986(oa[i]) + '"'}).join(',') | ||
authHeader += ',oauth_signature="' + oauth.rfc3986(signature) + '"' | ||
this.setHeader('Authorization', authHeader) | ||
return this | ||
self.setHeader('Authorization', authHeader) | ||
return self | ||
} | ||
Request.prototype.jar = function (jar) { | ||
var self = this | ||
var cookies | ||
if (this._redirectsFollowed === 0) { | ||
this.originalCookieHeader = this.getHeader('cookie') | ||
if (self._redirectsFollowed === 0) { | ||
self.originalCookieHeader = self.getHeader('cookie') | ||
} | ||
@@ -1509,9 +1705,9 @@ | ||
cookies = false | ||
this._disableCookies = true | ||
self._disableCookies = true | ||
} else { | ||
var targetCookieJar = (jar && jar.getCookieString) ? jar : globalCookieJar; | ||
var urihref = this.uri.href | ||
var targetCookieJar = (jar && jar.getCookieString) ? jar : globalCookieJar | ||
var urihref = self.uri.href | ||
//fetch cookie in the Specified host | ||
if (targetCookieJar) { | ||
cookies = targetCookieJar.getCookieString(urihref); | ||
cookies = targetCookieJar.getCookieString(urihref) | ||
} | ||
@@ -1522,11 +1718,11 @@ } | ||
if (cookies && cookies.length) { | ||
if (this.originalCookieHeader) { | ||
if (self.originalCookieHeader) { | ||
// Don't overwrite existing Cookie header | ||
this.setHeader('cookie', this.originalCookieHeader + '; ' + cookies) | ||
self.setHeader('cookie', self.originalCookieHeader + '; ' + cookies) | ||
} else { | ||
this.setHeader('cookie', cookies) | ||
self.setHeader('cookie', cookies) | ||
} | ||
} | ||
this._jar = jar | ||
return this | ||
self._jar = jar | ||
return self | ||
} | ||
@@ -1537,15 +1733,17 @@ | ||
Request.prototype.pipe = function (dest, opts) { | ||
if (this.response) { | ||
if (this._destdata) { | ||
throw new Error("You cannot pipe after data has been emitted from the response.") | ||
} else if (this._ended) { | ||
throw new Error("You cannot pipe after the response has been ended.") | ||
var self = this | ||
if (self.response) { | ||
if (self._destdata) { | ||
throw new Error('You cannot pipe after data has been emitted from the response.') | ||
} else if (self._ended) { | ||
throw new Error('You cannot pipe after the response has been ended.') | ||
} else { | ||
stream.Stream.prototype.pipe.call(this, dest, opts) | ||
this.pipeDest(dest) | ||
stream.Stream.prototype.pipe.call(self, dest, opts) | ||
self.pipeDest(dest) | ||
return dest | ||
} | ||
} else { | ||
this.dests.push(dest) | ||
stream.Stream.prototype.pipe.call(this, dest, opts) | ||
self.dests.push(dest) | ||
stream.Stream.prototype.pipe.call(self, dest, opts) | ||
return dest | ||
@@ -1555,21 +1753,41 @@ } | ||
Request.prototype.write = function () { | ||
if (!this._started) this.start() | ||
return this.req.write.apply(this.req, arguments) | ||
var self = this | ||
if (!self._started) { | ||
self.start() | ||
} | ||
return self.req.write.apply(self.req, arguments) | ||
} | ||
Request.prototype.end = function (chunk) { | ||
if (chunk) this.write(chunk) | ||
if (!this._started) this.start() | ||
this.req.end() | ||
var self = this | ||
if (chunk) { | ||
self.write(chunk) | ||
} | ||
if (!self._started) { | ||
self.start() | ||
} | ||
self.req.end() | ||
} | ||
Request.prototype.pause = function () { | ||
if (!this.response) this._paused = true | ||
else this.response.pause.apply(this.response, arguments) | ||
var self = this | ||
if (!self.response) { | ||
self._paused = true | ||
} else { | ||
self.response.pause.apply(self.response, arguments) | ||
} | ||
} | ||
Request.prototype.resume = function () { | ||
if (!this.response) this._paused = false | ||
else this.response.resume.apply(this.response, arguments) | ||
var self = this | ||
if (!self.response) { | ||
self._paused = false | ||
} else { | ||
self.response.resume.apply(self.response, arguments) | ||
} | ||
} | ||
Request.prototype.destroy = function () { | ||
if (!this._ended) this.end() | ||
else if (this.response) this.response.destroy() | ||
var self = this | ||
if (!self._ended) { | ||
self.end() | ||
} else if (self.response) { | ||
self.response.destroy() | ||
} | ||
} | ||
@@ -1580,52 +1798,5 @@ | ||
// Helpers | ||
Request.defaultProxyHeaderExclusiveList = | ||
defaultProxyHeaderExclusiveList.slice() | ||
// Return a simpler request object to allow serialization | ||
function requestToJSON() { | ||
return { | ||
uri: this.uri, | ||
method: this.method, | ||
headers: this.headers | ||
} | ||
} | ||
// Return a simpler response object to allow serialization | ||
function responseToJSON() { | ||
return { | ||
statusCode: this.statusCode, | ||
body: this.body, | ||
headers: this.headers, | ||
request: requestToJSON.call(this.request) | ||
} | ||
} | ||
function filterForNonReserved(reserved, options) { | ||
// Filter out properties that are not reserved. | ||
// Reserved values are passed in at call site. | ||
var object = {} | ||
for (var i in options) { | ||
var notReserved = (reserved.indexOf(i) === -1) | ||
if (notReserved) { | ||
object[i] = options[i] | ||
} | ||
} | ||
return object | ||
} | ||
function filterOutReservedFunctions(reserved, options) { | ||
// Filter out properties that are functions and are reserved. | ||
// Reserved values are passed in at call site. | ||
var object = {} | ||
for (var i in options) { | ||
var isReserved = !(reserved.indexOf(i) === -1) | ||
var isFunction = (typeof options[i] === 'function') | ||
if (!(isReserved && isFunction)) { | ||
object[i] = options[i] | ||
} | ||
} | ||
return object | ||
} | ||
// Exports | ||
@@ -1632,0 +1803,0 @@ |
@@ -71,4 +71,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz" | ||
} |
@@ -61,4 +61,3 @@ { | ||
"_shasum": "06e1ea8082c2cb14e39806e22e2f6f757f92af39", | ||
"_resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz" | ||
} |
@@ -35,3 +35,3 @@ { | ||
}, | ||
"_from": "inherits@2", | ||
"_from": "inherits@~2.0.1", | ||
"_npmVersion": "1.3.8", | ||
@@ -38,0 +38,0 @@ "_npmUser": { |
@@ -48,4 +48,3 @@ { | ||
"_shasum": "d82388ae9c960becbea0c73bb9eb79b6c6ce9aeb", | ||
"_resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.5.0.tgz" | ||
} |
@@ -53,7 +53,3 @@ { | ||
"_from": "sigmund@~1.0.0", | ||
"_resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz", | ||
"bugs": { | ||
"url": "https://github.com/isaacs/sigmund/issues" | ||
}, | ||
"homepage": "https://github.com/isaacs/sigmund" | ||
"_resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.0.tgz" | ||
} |
@@ -55,4 +55,3 @@ { | ||
"_shasum": "c74e780574f63c6f9a090e90efbe6ef53a6a756a", | ||
"_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz" | ||
} |
@@ -51,5 +51,3 @@ { | ||
"_shasum": "eea3033f0c3728139de7b57ab1b0d6d89c353c63", | ||
"_resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-0.0.7.tgz", | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/isaacs/fstream-ignore" | ||
"_resolved": "https://registry.npmjs.org/fstream-ignore/-/fstream-ignore-0.0.7.tgz" | ||
} |
@@ -53,3 +53,3 @@ { | ||
"_shasum": "a0306d9b0940e0fc512d33b5df1014e88e0637a3", | ||
"_from": "graceful-fs@~3.0.2", | ||
"_from": "graceful-fs@3", | ||
"_npmVersion": "1.4.28", | ||
@@ -70,4 +70,3 @@ "_npmUser": { | ||
}, | ||
"_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" | ||
} |
@@ -35,3 +35,3 @@ { | ||
}, | ||
"_from": "inherits@~2.0.0", | ||
"_from": "inherits@~2.0.1", | ||
"_npmVersion": "1.3.8", | ||
@@ -38,0 +38,0 @@ "_npmUser": { |
@@ -55,4 +55,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/fstream/-/fstream-0.1.31.tgz" | ||
} |
@@ -62,5 +62,3 @@ { | ||
"_shasum": "15a4806a57547cb2d2dbf27f42e89a8c3451b364", | ||
"_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/isaacs/node-graceful-fs" | ||
"_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz" | ||
} |
@@ -50,8 +50,3 @@ { | ||
"_from": "once@~1.1.1", | ||
"_resolved": "https://registry.npmjs.org/once/-/once-1.1.1.tgz", | ||
"bugs": { | ||
"url": "https://github.com/isaacs/once/issues" | ||
}, | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/isaacs/once" | ||
"_resolved": "https://registry.npmjs.org/once/-/once-1.1.1.tgz" | ||
} |
@@ -52,4 +52,3 @@ { | ||
"_shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538", | ||
"_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz", | ||
"scripts": {} | ||
"_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz" | ||
} |
@@ -35,3 +35,3 @@ { | ||
}, | ||
"_from": "inherits@2", | ||
"_from": "inherits@~2.0.1", | ||
"_npmVersion": "1.3.8", | ||
@@ -38,0 +38,0 @@ "_npmUser": { |
@@ -50,6 +50,3 @@ { | ||
"_shasum": "8a18acfca9a8f4177e09abfc6038939b05d1eedf", | ||
"_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", | ||
"bugs": { | ||
"url": "https://github.com/juliangruber/isarray/issues" | ||
} | ||
"_resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" | ||
} |
@@ -52,4 +52,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz" | ||
} |
{ | ||
"name": "readable-stream", | ||
"version": "1.0.33-1", | ||
"version": "1.0.33", | ||
"description": "Streams2, a user-land copy of the stream library from Node.js v0.10.x", | ||
@@ -36,3 +36,3 @@ "main": "readable.js", | ||
"license": "MIT", | ||
"gitHead": "cd9bc3fbcdc82211c5649b5170706b10c65c8479", | ||
"gitHead": "0bf97a117c5646556548966409ebc57a6dda2638", | ||
"bugs": { | ||
@@ -42,6 +42,6 @@ "url": "https://github.com/isaacs/readable-stream/issues" | ||
"homepage": "https://github.com/isaacs/readable-stream", | ||
"_id": "readable-stream@1.0.33-1", | ||
"_shasum": "40d0d91338691291a9117c05d78adb5497c37810", | ||
"_id": "readable-stream@1.0.33", | ||
"_shasum": "3a360dd66c1b1d7fd4705389860eda1d0f61126c", | ||
"_from": "readable-stream@~1.0.2", | ||
"_npmVersion": "1.4.23", | ||
"_npmVersion": "1.4.28", | ||
"_npmUser": { | ||
@@ -66,8 +66,7 @@ "name": "rvagg", | ||
"dist": { | ||
"shasum": "40d0d91338691291a9117c05d78adb5497c37810", | ||
"tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz" | ||
"shasum": "3a360dd66c1b1d7fd4705389860eda1d0f61126c", | ||
"tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz" | ||
}, | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33-1.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.33.tgz" | ||
} |
@@ -1,3 +0,4 @@ | ||
require('stream'); // hack to fix a circular dependency issue when used with browserify | ||
var Stream = require('stream'); // hack to fix a circular dependency issue when used with browserify | ||
exports = module.exports = require('./lib/_stream_readable.js'); | ||
exports.Stream = Stream; | ||
exports.Readable = exports; | ||
@@ -4,0 +5,0 @@ exports.Writable = require('./lib/_stream_writable.js'); |
@@ -5,4 +5,4 @@ # readable-stream | ||
[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true)](https://nodei.co/npm/readable-stream/) | ||
[![NPM](https://nodei.co/npm-dl/readable-stream.png)](https://nodei.co/npm/readable-stream/) | ||
[![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) | ||
[![NPM](https://nodei.co/npm-dl/readable-stream.png?&months=6&height=3)](https://nodei.co/npm/readable-stream/) | ||
@@ -9,0 +9,0 @@ This package is a mirror of the Streams2 and Streams3 implementations in Node-core. |
@@ -35,3 +35,3 @@ { | ||
}, | ||
"_from": "inherits@2", | ||
"_from": "inherits@~2.0.1", | ||
"_npmVersion": "1.3.8", | ||
@@ -38,0 +38,0 @@ "_npmUser": { |
@@ -52,4 +52,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/tar/-/tar-0.1.20.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/tar/-/tar-0.1.20.tgz" | ||
} |
@@ -44,8 +44,3 @@ { | ||
"_from": "uid-number@0.0.3", | ||
"_resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.3.tgz", | ||
"bugs": { | ||
"url": "https://github.com/isaacs/uid-number/issues" | ||
}, | ||
"readme": "ERROR: No README data found!", | ||
"homepage": "https://github.com/isaacs/uid-number" | ||
"_resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.3.tgz" | ||
} |
@@ -53,7 +53,3 @@ { | ||
"_shasum": "c2c401c02dd366138645e917b3a6baa256a9dcab", | ||
"_resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-2.0.0.tgz", | ||
"bugs": { | ||
"url": "https://github.com/ForbesLindesay/tar-pack/issues" | ||
}, | ||
"homepage": "https://github.com/ForbesLindesay/tar-pack" | ||
"_resolved": "https://registry.npmjs.org/tar-pack/-/tar-pack-2.0.0.tgz" | ||
} |
@@ -52,4 +52,3 @@ { | ||
"_shasum": "9088ab5ae1e861f4d81b176b4a8046080703deed", | ||
"_resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz", | ||
"homepage": "https://github.com/isaacs/block-stream" | ||
"_resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.7.tgz" | ||
} |
@@ -69,4 +69,3 @@ { | ||
}, | ||
"_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz" | ||
} |
@@ -55,4 +55,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.2.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.2.tgz" | ||
} |
@@ -49,4 +49,3 @@ { | ||
"_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1", | ||
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", | ||
"homepage": "https://github.com/isaacs/inherits" | ||
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz" | ||
} |
@@ -53,4 +53,3 @@ { | ||
"directories": {}, | ||
"_resolved": "https://registry.npmjs.org/tar/-/tar-1.0.1.tgz", | ||
"readme": "ERROR: No README data found!" | ||
"_resolved": "https://registry.npmjs.org/tar/-/tar-1.0.1.tgz" | ||
} |
{ | ||
"name": "node-pre-gyp", | ||
"description": "Node.js native addon binary install tool", | ||
"version" : "0.5.29", | ||
"version" : "0.5.30", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "native", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
58661
201
3053745
31