Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into fix-auth-post
Browse files Browse the repository at this point in the history
Conflicts:
	index.js
  • Loading branch information
nylen committed Apr 13, 2013
2 parents a375ac1 + 93e7c20 commit 5f036e6
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 53 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ The first argument can be either a url or an options object. The only required o
* `strictSSL` - Set to `true` to require that 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.
* `jar` - Set to `false` if you don't want cookies to be remembered for future use or define your custom cookie jar (see examples section)
* `aws` - object containing aws signing information, should have the properties `key` and `secret` as well as `bucket` unless you're specifying your bucket as part of the path, or you are making a request that doesn't use a bucket (i.e. GET Services)
* `localAddress` - Local interface to bind for network connections.
The callback argument gets 3 arguments. The first is an error when applicable (usually from the http.Client option not the http.ClientRequest object). The second in an http.ClientResponse object. The third is the response body String or Buffer.
Expand Down
109 changes: 56 additions & 53 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var http = require('http')
, qs = require('qs')
, querystring = require('querystring')
, crypto = require('crypto')

, oauth = require('oauth-sign')
, hawk = require('hawk')
, aws = require('aws-sign')
Expand All @@ -32,7 +32,7 @@ var http = require('http')

, ForeverAgent = require('forever-agent')
, FormData = require('form-data')

, Cookie = require('cookie-jar')
, CookieJar = Cookie.Jar
, cookieJar = new CookieJar
Expand Down Expand Up @@ -104,7 +104,7 @@ function Request (options) {
if (typeof options === 'string') {
options = {uri:options}
}

var reserved = Object.keys(Request.prototype)
for (var i in options) {
if (reserved.indexOf(i) === -1) {
Expand All @@ -115,7 +115,7 @@ function Request (options) {
}
}
}

this.init(options)
}
util.inherits(Request, stream.Stream)
Expand All @@ -125,14 +125,15 @@ Request.prototype.init = function (options) {
// this function is called from both the constructor and on redirect.
var self = this
if (!options) options = {}

if (!self.method) self.method = options.method || 'GET'

self.localAddress = options.localAddress

debug(options)
if (!self.pool && self.pool !== false) self.pool = globalPool
self.dests = self.dests || []
self.__isRequestRequest = true

// Protect against double callback
if (!self._callback && self.callback) {
self._callback = self.callback
Expand All @@ -157,7 +158,11 @@ Request.prototype.init = function (options) {
} else {
if (typeof self.uri == "string") self.uri = url.parse(self.uri)
}


if (self.strictSSL === false) {
self.rejectUnauthorized = false
}

if (self.proxy) {
if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy)

Expand All @@ -169,8 +174,9 @@ Request.prototype.init = function (options) {
var tunnelOptions = { proxy: { host: self.proxy.hostname
, port: +self.proxy.port
, proxyAuth: self.proxy.auth
, headers: { Host: self.uri.hostname + ':' +
, headers: { Host: self.uri.hostname + ':' +
(self.uri.port || self.uri.protocol === 'https:' ? 443 : 80) }}
, rejectUnauthorized: self.rejectUnauthorized
, ca: this.ca }

self.agent = tunnelFn(tunnelOptions)
Expand Down Expand Up @@ -212,7 +218,7 @@ Request.prototype.init = function (options) {
}
self.setHost = true
}

self.jar(self._jar || options.jar)

if (!self.uri.pathname) {self.uri.pathname = '/'}
Expand All @@ -231,7 +237,7 @@ Request.prototype.init = function (options) {

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) }
Expand Down Expand Up @@ -261,7 +267,7 @@ Request.prototype.init = function (options) {
if (options.form) {
self.form(options.form)
}

if (options.qs) self.qs(options.qs)

if (self.uri.path) {
Expand All @@ -277,11 +283,11 @@ Request.prototype.init = function (options) {
if (options.oauth) {
self.oauth(options.oauth)
}

if (options.aws) {
self.aws(options.aws)
}

if (options.hawk) {
self.hawk(options.hawk)
}
Expand All @@ -301,7 +307,7 @@ Request.prototype.init = function (options) {
self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return querystring.unescape(item)}).join(':'))
}


if (self.proxy && !self.tunnel) self.path = (self.uri.protocol + '//' + self.uri.host + self.path)

if (options.json) {
Expand Down Expand Up @@ -354,10 +360,6 @@ Request.prototype.init = function (options) {
self.agentClass = self.httpModule.Agent
}
}

if (self.strictSSL === false) {
self.rejectUnauthorized = false
}

if (self.pool === false) {
self.agent = false
Expand Down Expand Up @@ -401,7 +403,7 @@ Request.prototype.init = function (options) {

process.nextTick(function () {
if (self._aborted) return

if (self._form) {
self.setHeaders(self._form.getHeaders())
self._form.pipe(self)
Expand Down Expand Up @@ -445,6 +447,7 @@ Request.prototype._updateProtocol = function () {
var tunnelOptions = { proxy: { host: self.proxy.hostname
, port: +self.proxy.port
, proxyAuth: self.proxy.auth }
, rejectUnauthorized: self.rejectUnauthorized
, ca: self.ca }
self.agent = tunnelFn(tunnelOptions)
return
Expand Down Expand Up @@ -588,7 +591,7 @@ Request.prototype.start = function () {
e.code = "ETIMEDOUT"
self.emit("error", e)
}, self.timeout)

// Set additional timeout on socket - in case if remote
// server freeze after sending headers
if (self.req.setTimeout) { // only works on node 0.6+
Expand All @@ -602,7 +605,7 @@ Request.prototype.start = function () {
})
}
}

self.req.on('error', self.clientErrorHandler)
self.req.on('drain', function() {
self.emit('drain')
Expand All @@ -618,7 +621,7 @@ Request.prototype.onResponse = function (response) {
response.on('end', function() {
debug('response end', self.uri.href, response.statusCode, response.headers)
});

if (response.connection.listeners('error').indexOf(self._parserErrorHandler) === -1) {
response.connection.once('error', self._parserErrorHandler)
}
Expand Down Expand Up @@ -867,14 +870,14 @@ Request.prototype.onResponse = function (response) {

Request.prototype.abort = function () {
this._aborted = true

if (this.req) {
this.req.abort()
}
else if (this.response) {
this.response.abort()
}

this.emit("abort")
}

Expand Down Expand Up @@ -911,26 +914,26 @@ Request.prototype.qs = function (q, clobber) {
var base
if (!clobber && this.uri.query) base = qs.parse(this.uri.query)
else base = {}

for (var i in q) {
base[i] = q[i]
}

if (qs.stringify(base) === ''){
return this
}

this.uri = url.parse(this.uri.href.split('?')[0] + '?' + qs.stringify(base))
this.url = this.uri

return this
}
Request.prototype.form = function (form) {
if (form) {
this.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8'
this.body = qs.stringify(form).toString('utf8')
return this
}
}
// create form-data object
this._form = new FormData()
return this._form
Expand All @@ -950,7 +953,7 @@ Request.prototype.multipart = function (multipart) {
if (self.preambleCRLF) {
self.body.push(new Buffer('\r\n'))
}

multipart.forEach(function (part) {
var body = part.body
if(body == null) throw Error('Body attribute missing in multipart.')
Expand Down Expand Up @@ -999,7 +1002,7 @@ function getHeader(name, headers) {
return result
}
Request.prototype.auth = function (user, pass, sendImmediately) {
if (typeof user !== 'string' || typeof pass !== 'string') {
if (typeof user !== 'string' || (pass !== undefined && typeof pass !== 'string')) {
throw new Error('auth() received invalid user or password')
}
this._user = user
Expand Down Expand Up @@ -1038,7 +1041,7 @@ Request.prototype.aws = function (opts, now) {
}
auth.resource = aws.canonicalizeResource(auth.resource)
this.setHeader('authorization', aws.authorization(auth))

return this
}

Expand All @@ -1048,25 +1051,25 @@ Request.prototype.hawk = function (opts) {

Request.prototype.oauth = function (_oauth) {
var form
if (this.headers['content-type'] &&
if (this.headers['content-type'] &&
this.headers['content-type'].slice(0, 'application/x-www-form-urlencoded'.length) ===
'application/x-www-form-urlencoded'
'application/x-www-form-urlencoded'
) {
form = qs.parse(this.body)
}
if (this.uri.query) {
form = qs.parse(this.uri.query)
}
}
if (!form) form = {}
var oa = {}
for (var i in form) oa[i] = form[i]
for (var i in _oauth) oa['oauth_'+i] = _oauth[i]
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'

var consumer_secret = oa.oauth_consumer_secret
delete oa.oauth_consumer_secret
var token_secret = oa.oauth_token_secret
Expand All @@ -1075,11 +1078,11 @@ Request.prototype.oauth = function (_oauth) {

var baseurl = this.uri.protocol + '//' + this.uri.host + this.uri.pathname
var signature = oauth.hmacsign(this.method, baseurl, oa, consumer_secret, token_secret)

// oa.oauth_signature = signature
for (var i in form) {
if ( i.slice(0, 'oauth_') in _oauth) {
// skip
// skip
} else {
delete oa['oauth_'+i]
if (i !== 'x_auth_mode') delete oa[i]
Expand All @@ -1093,11 +1096,11 @@ Request.prototype.oauth = function (_oauth) {
}
Request.prototype.jar = function (jar) {
var cookies

if (this._redirectsFollowed === 0) {
this.originalCookieHeader = this.headers.cookie
}

if (jar === false) {
// disable cookies
cookies = false
Expand All @@ -1109,7 +1112,7 @@ Request.prototype.jar = function (jar) {
// fetch cookie from the global cookie jar
cookies = cookieJar.get({ url: this.uri.href })
}

if (cookies && cookies.length) {
var cookieString = cookies.map(function (c) {
return c.name + "=" + c.value
Expand Down Expand Up @@ -1266,9 +1269,9 @@ request.patch = function (uri, options, callback) {
request.head = function (uri, options, callback) {
var params = initParams(uri, options, callback)
params.options.method = 'HEAD'
if (params.options.body ||
params.options.requestBodyStream ||
(params.options.json && typeof params.options.json !== 'boolean') ||
if (params.options.body ||
params.options.requestBodyStream ||
(params.options.json && typeof params.options.json !== 'boolean') ||
params.options.multipart) {
throw new Error("HTTP HEAD requests MUST NOT include a request body.")
}
Expand All @@ -1293,23 +1296,23 @@ request.cookie = function (str) {

// Safe toJSON

function getSafe (self, uuid) {
function getSafe (self, uuid) {
if (typeof self === 'object' || typeof self === 'function') var safe = {}
if (Array.isArray(self)) var safe = []

var recurse = []

Object.defineProperty(self, uuid, {})

var attrs = Object.keys(self).filter(function (i) {
if (i === uuid) return false
if (i === uuid) return false
if ( (typeof self[i] !== 'object' && typeof self[i] !== 'function') || self[i] === null) return true
return !(Object.getOwnPropertyDescriptor(self[i], uuid))
})


for (var i=0;i<attrs.length;i++) {
if ( (typeof self[attrs[i]] !== 'object' && typeof self[attrs[i]] !== 'function') ||
if ( (typeof self[attrs[i]] !== 'object' && typeof self[attrs[i]] !== 'function') ||
self[attrs[i]] === null
) {
safe[attrs[i]] = self[attrs[i]]
Expand All @@ -1322,7 +1325,7 @@ function getSafe (self, uuid) {
for (var i=0;i<recurse.length;i++) {
safe[recurse[i]] = getSafe(self[recurse[i]], uuid)
}

return safe
}

Expand Down
9 changes: 9 additions & 0 deletions tests/test-localAddress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
var request = request = require('../index')
, assert = require('assert')
;

request.get({
uri: 'http://www.google.com', localAddress: '127.0.0.1'
}, function(err) {
assert.equal(err.code, 'ENETUNREACH')
})

0 comments on commit 5f036e6

Please sign in to comment.