Comparing version 2.25.0 to 2.26.0
164
index.js
@@ -96,3 +96,3 @@ // Copyright 2010-2012 Mikeal Rogers | ||
var isUrl = /^https?:/ | ||
var isUrl = /^https?:/i | ||
@@ -192,4 +192,6 @@ var globalPool = {} | ||
} | ||
if (!self.uri.pathname) {self.uri.pathname = '/'} | ||
if (!self.uri.host || !self.uri.pathname) { | ||
if (!self.uri.host) { | ||
// Invalid URI: it may generate lot of bad errors, like "TypeError: Cannot call method 'indexOf' of undefined" in CookieJar | ||
@@ -219,8 +221,8 @@ // Detect and reject it as soon as possible | ||
self.setHost = false | ||
if (!(self.headers.host || self.headers.Host)) { | ||
self.headers.host = self.uri.hostname | ||
if (!self.hasHeader('host')) { | ||
self.setHeader('host', 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.headers.host += (':'+self.uri.port) | ||
self.setHeader('host', self.getHeader('host') + (':'+self.uri.port) ) | ||
} | ||
@@ -232,3 +234,2 @@ self.setHost = true | ||
if (!self.uri.pathname) {self.uri.pathname = '/'} | ||
if (!self.uri.port) { | ||
@@ -315,8 +316,8 @@ if (self.uri.protocol == 'http:') {self.uri.port = 80} | ||
if (self.uri.auth && !self.headers.authorization) { | ||
if (self.uri.auth && !self.hasHeader('authorization')) { | ||
var authPieces = self.uri.auth.split(':').map(function(item){ return querystring.unescape(item) }) | ||
self.auth(authPieces[0], authPieces.slice(1).join(':'), true) | ||
} | ||
if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization'] && !self.tunnel) { | ||
self.headers['proxy-authorization'] = "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return querystring.unescape(item)}).join(':')) | ||
if (self.proxy && self.proxy.auth && !self.hasHeader('proxy-authorization') && !self.tunnel) { | ||
self.setHeader('proxy-authorization', "Basic " + toBase64(self.proxy.auth.split(':').map(function(item){ return querystring.unescape(item)}).join(':'))) | ||
} | ||
@@ -349,4 +350,3 @@ | ||
if (length) { | ||
if(!self.headers['content-length'] && !self.headers['Content-Length']) | ||
self.headers['content-length'] = length | ||
if (!self.hasHeader('content-length')) self.setHeader('content-length', length) | ||
} else { | ||
@@ -397,14 +397,13 @@ throw new Error('Argument error, options.body.') | ||
if (isReadStream(src)) { | ||
if (!self.headers['content-type'] && !self.headers['Content-Type']) | ||
self.headers['content-type'] = mime.lookup(src.path) | ||
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.headers[i]) { | ||
self.headers[i] = src.headers[i] | ||
if (!self.hasHeader(i)) { | ||
self.setHeader(i, src.headers[i]) | ||
} | ||
} | ||
} | ||
if (self._json && !self.headers['content-type'] && !self.headers['Content-Type']) | ||
self.headers['content-type'] = 'application/json' | ||
if (self._json && !self.hasHeader('content-type')) | ||
self.setHeader('content-type', 'application/json') | ||
if (src.method && !self.explicitMethod) { | ||
@@ -441,3 +440,3 @@ self.method = src.method | ||
if (self.method !== 'GET' && typeof self.method !== 'undefined') { | ||
self.headers['content-length'] = 0 | ||
self.setHeader('content-length', 0) | ||
} | ||
@@ -599,4 +598,4 @@ self.end() | ||
if (self.src && self.src.stat && self.src.stat.size && !self.headers['content-length'] && !self.headers['Content-Length']) { | ||
self.headers['content-length'] = self.src.stat.size | ||
if (self.src && self.src.stat && self.src.stat.size && !self.hasHeader('content-length')) { | ||
self.setHeader('content-length', self.src.stat.size) | ||
} | ||
@@ -678,3 +677,3 @@ if (self._aws) { | ||
if (self.setHost) delete self.headers.host | ||
if (self.setHost && self.hasHeader('host')) delete self.headers[self.hasHeader('host')] | ||
if (self.timeout && self.timeoutTimer) { | ||
@@ -695,13 +694,15 @@ clearTimeout(self.timeoutTimer) | ||
if (response.headers['set-cookie'] && (!self._disableCookies)) { | ||
if (Array.isArray(response.headers['set-cookie'])) response.headers['set-cookie'].forEach(addCookie) | ||
else addCookie(response.headers['set-cookie']) | ||
if (hasHeader('set-cookie', response.headers) && (!self._disableCookies)) { | ||
var headerName = hasHeader('set-cookie', response.headers) | ||
if (Array.isArray(response.headers[headerName])) response.headers[headerName].forEach(addCookie) | ||
else addCookie(response.headers[headerName]) | ||
} | ||
var redirectTo = null | ||
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) { | ||
debug('redirect', response.headers.location) | ||
if (response.statusCode >= 300 && response.statusCode < 400 && hasHeader('location', response.headers)) { | ||
var location = response.headers[hasHeader('location', response.headers)] | ||
debug('redirect', location) | ||
if (self.followAllRedirects) { | ||
redirectTo = response.headers.location | ||
redirectTo = location | ||
} else if (self.followRedirect) { | ||
@@ -716,3 +717,3 @@ switch (self.method) { | ||
default: | ||
redirectTo = response.headers.location | ||
redirectTo = location | ||
break | ||
@@ -722,3 +723,3 @@ } | ||
} else if (response.statusCode == 401 && self._hasAuth && !self._sentAuth) { | ||
var authHeader = response.headers['www-authenticate'] | ||
var authHeader = response.headers[hasHeader('www-authenticate', response.headers)] | ||
var authVerb = authHeader && authHeader.split(' ')[0] | ||
@@ -817,5 +818,5 @@ debug('reauth', authVerb) | ||
if (self.headers) { | ||
delete self.headers.host | ||
delete self.headers['content-type'] | ||
delete self.headers['content-length'] | ||
if (self.hasHeader('host')) delete self.headers[self.hasHeader('host')] | ||
if (self.hasHeader('content-type')) delete self.headers[self.hasHeader('content-type')] | ||
if (self.hasHeader('content-length')) delete self.headers[self.hasHeader('content-length')] | ||
} | ||
@@ -938,7 +939,14 @@ } | ||
// Called after the response is received | ||
if (dest.headers) { | ||
dest.headers['content-type'] = response.headers['content-type'] | ||
if (response.headers['content-length']) { | ||
dest.headers['content-length'] = response.headers['content-length'] | ||
if (dest.headers && !dest.headersSent) { | ||
if (hasHeader('content-type', response.headers)) { | ||
var ctname = hasHeader('content-type', response.headers) | ||
if (dest.setHeader) dest.setHeader(ctname, response.headers[ctname]) | ||
else dest.headers[ctname] = response.headers[ctname] | ||
} | ||
if (hasHeader('content-length', response.headers)) { | ||
var clname = hasHeader('content-length', response.headers) | ||
if (dest.setHeader) dest.setHeader(clname, response.headers[clname]) | ||
else dest.headers[clname] = response.headers[clname] | ||
} | ||
} | ||
@@ -957,4 +965,4 @@ if (dest.setHeader && !dest.headersSent) { | ||
if (clobber === undefined) clobber = true | ||
if (clobber || !this.headers.hasOwnProperty(name)) this.headers[name] = value | ||
else this.headers[name] += ',' + value | ||
if (clobber || !this.hasHeader(name)) this.headers[name] = value | ||
else this.headers[this.hasHeader(name)] += ',' + value | ||
return this | ||
@@ -966,2 +974,15 @@ } | ||
} | ||
Request.prototype.hasHeader = function (header, headers) { | ||
var headers = Object.keys(headers || this.headers) | ||
, lheaders = headers.map(function (h) {return h.toLowerCase()}) | ||
; | ||
header = header.toLowerCase() | ||
for (var i=0;i<lheaders.length;i++) { | ||
if (lheaders[i] === header) return headers[i] | ||
} | ||
return false | ||
} | ||
var hasHeader = Request.prototype.hasHeader | ||
Request.prototype.qs = function (q, clobber) { | ||
@@ -988,3 +1009,3 @@ var base | ||
if (form) { | ||
this.headers['content-type'] = 'application/x-www-form-urlencoded; charset=utf-8' | ||
this.setHeader('content-type', 'application/x-www-form-urlencoded; charset=utf-8') | ||
this.body = qs.stringify(form).toString('utf8') | ||
@@ -1001,6 +1022,6 @@ return this | ||
if (!self.headers['content-type']) { | ||
self.headers['content-type'] = 'multipart/related; boundary=' + self.boundary | ||
if (!self.hasHeader('content-type')) { | ||
self.setHeader('content-type', 'multipart/related; boundary=' + self.boundary) | ||
} else { | ||
self.headers['content-type'] = self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary | ||
self.setHeader('content-type', self.headers['content-type'].split(';')[0] + '; boundary=' + self.boundary) | ||
} | ||
@@ -1031,13 +1052,9 @@ | ||
Request.prototype.json = function (val) { | ||
var self = this; | ||
var setAcceptHeader = function() { | ||
if (!self.headers['accept'] && !self.headers['Accept']) { | ||
self.setHeader('accept', 'application/json') | ||
} | ||
} | ||
setAcceptHeader(); | ||
var self = this | ||
if (!self.hasHeader('accept')) self.setHeader('accept', 'application/json') | ||
this._json = true | ||
if (typeof val === 'boolean') { | ||
if (typeof this.body === 'object') { | ||
setAcceptHeader(); | ||
this.body = safeStringify(this.body) | ||
@@ -1047,3 +1064,2 @@ self.setHeader('content-type', 'application/json') | ||
} else { | ||
setAcceptHeader(); | ||
this.body = safeStringify(val) | ||
@@ -1054,11 +1070,14 @@ self.setHeader('content-type', 'application/json') | ||
} | ||
function getHeader(name, headers) { | ||
var result, re, match | ||
Object.keys(headers).forEach(function (key) { | ||
re = new RegExp(name, 'i') | ||
match = key.match(re) | ||
if (match) result = headers[key] | ||
}) | ||
return result | ||
Request.prototype.getHeader = function (name, headers) { | ||
var result, re, match | ||
if (!headers) headers = this.headers | ||
Object.keys(headers).forEach(function (key) { | ||
re = new RegExp(name, 'i') | ||
match = key.match(re) | ||
if (match) result = headers[key] | ||
}) | ||
return result | ||
} | ||
var getHeader = Request.prototype.getHeader | ||
Request.prototype.auth = function (user, pass, sendImmediately) { | ||
@@ -1071,4 +1090,5 @@ if (typeof user !== 'string' || (pass !== undefined && typeof pass !== 'string')) { | ||
this._hasAuth = true | ||
var header = typeof pass !== 'undefined' ? user + ':' + pass : user | ||
if (sendImmediately || typeof sendImmediately == 'undefined') { | ||
this.setHeader('authorization', 'Basic ' + toBase64(user + ':' + pass)) | ||
this.setHeader('authorization', 'Basic ' + toBase64(header)) | ||
this._sentAuth = true | ||
@@ -1090,4 +1110,4 @@ } | ||
, date: date | ||
, contentType: getHeader('content-type', this.headers) || '' | ||
, md5: getHeader('content-md5', this.headers) || '' | ||
, contentType: this.getHeader('content-type') || '' | ||
, md5: this.getHeader('content-md5') || '' | ||
, amazonHeaders: aws.canonicalizeHeaders(this.headers) | ||
@@ -1121,3 +1141,3 @@ } | ||
}, opts) | ||
debug('httpSignature authorization', getHeader('authorization', this.headers)) | ||
debug('httpSignature authorization', this.getHeader('authorization')) | ||
@@ -1128,3 +1148,3 @@ return this | ||
Request.prototype.hawk = function (opts) { | ||
this.headers.Authorization = hawk.client.header(this.uri, this.method, opts).field | ||
this.setHeader('Authorization', hawk.client.header(this.uri, this.method, opts).field) | ||
} | ||
@@ -1134,4 +1154,4 @@ | ||
var form | ||
if (this.headers['content-type'] && | ||
this.headers['content-type'].slice(0, 'application/x-www-form-urlencoded'.length) === | ||
if (this.hasHeader('content-type') && | ||
this.getHeader('content-type').slice(0, 'application/x-www-form-urlencoded'.length) === | ||
'application/x-www-form-urlencoded' | ||
@@ -1173,5 +1193,5 @@ ) { | ||
oa.oauth_timestamp = timestamp | ||
this.headers.Authorization = | ||
'OAuth '+Object.keys(oa).sort().map(function (i) {return i+'="'+oauth.rfc3986(oa[i])+'"'}).join(',') | ||
this.headers.Authorization += ',oauth_signature="' + oauth.rfc3986(signature) + '"' | ||
var authHeader = 'OAuth '+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 | ||
@@ -1183,3 +1203,3 @@ } | ||
if (this._redirectsFollowed === 0) { | ||
this.originalCookieHeader = this.headers.cookie | ||
this.originalCookieHeader = this.getHeader('cookie') | ||
} | ||
@@ -1206,5 +1226,5 @@ | ||
// Don't overwrite existing Cookie header | ||
this.headers.cookie = this.originalCookieHeader + '; ' + cookieString | ||
this.setHeader('cookie', this.originalCookieHeader + '; ' + cookieString) | ||
} else { | ||
this.headers.cookie = cookieString | ||
this.setHeader('cookie', cookieString) | ||
} | ||
@@ -1211,0 +1231,0 @@ } |
@@ -10,3 +10,3 @@ { | ||
], | ||
"version": "2.25.0", | ||
"version": "2.26.0", | ||
"author": "Mikeal Rogers <mikeal.rogers@gmail.com>", | ||
@@ -13,0 +13,0 @@ "repository": { |
@@ -1,17 +0,5 @@ | ||
# Request -- Simplified HTTP request method | ||
# Request -- Simplified HTTP client | ||
## Install | ||
[![NPM](https://nodei.co/npm/request.png)](https://nodei.co/npm/request/) | ||
<pre> | ||
npm install request | ||
</pre> | ||
Or from source: | ||
<pre> | ||
git clone git://github.com/mikeal/request.git | ||
cd request | ||
npm link | ||
</pre> | ||
## Super simple to use | ||
@@ -59,3 +47,3 @@ | ||
request.get('http://mysite.com/doodle.png').pipe(resp) | ||
} | ||
} | ||
} | ||
@@ -154,6 +142,6 @@ }) | ||
// and construct a URL that a user clicks on (like a sign in button). | ||
// The verifier is only available in the response after a user has | ||
// The verifier is only available in the response after a user has | ||
// verified with twitter that they are authorizing your app. | ||
var access_token = qs.parse(body) | ||
, oauth = | ||
, oauth = | ||
{ consumer_key: CONSUMER_KEY | ||
@@ -168,3 +156,3 @@ , consumer_secret: CONSUMER_SECRET | ||
var perm_token = qs.parse(body) | ||
, oauth = | ||
, oauth = | ||
{ consumer_key: CONSUMER_KEY | ||
@@ -176,3 +164,3 @@ , consumer_secret: CONSUMER_SECRET | ||
, url = 'https://api.twitter.com/1/users/show.json?' | ||
, params = | ||
, params = | ||
{ screen_name: perm_token.screen_name | ||
@@ -211,3 +199,3 @@ , user_id: perm_token.user_id | ||
* `pool.maxSockets` - Integer containing the maximum amount of sockets in the pool. | ||
* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request | ||
* `timeout` - Integer containing the number of milliseconds to wait for a request to respond before aborting the request | ||
* `proxy` - An HTTP proxy to be used. Support proxy Auth with Basic Auth the same way it's supported with the `url` parameter by embedding the auth info in the uri. | ||
@@ -229,4 +217,4 @@ * `oauth` - Options for OAuth HMAC-SHA1 signing, see documentation above. | ||
### request.defaults(options) | ||
### request.defaults(options) | ||
This method returns a wrapper around the normal request API that defaults to whatever options you pass in to it. | ||
@@ -306,3 +294,3 @@ | ||
, uri: 'http://mikeal.iriscouch.com/testjs/' + rand | ||
, multipart: | ||
, multipart: | ||
[ { 'content-type': 'application/json' | ||
@@ -312,3 +300,3 @@ , body: JSON.stringify({foo: 'bar', _attachments: {'message.txt': {follows: true, length: 18, 'content_type': 'text/plain' }}}) | ||
, { body: 'I am an attachment' } | ||
] | ||
] | ||
} | ||
@@ -315,0 +303,0 @@ , function (error, response, body) { |
@@ -19,2 +19,4 @@ var assert = require('assert') | ||
ok = true; | ||
} else if ( req.headers.authorization == 'Basic ' + new Buffer('justauser').toString('base64')) { | ||
ok = true; | ||
} else { | ||
@@ -130,2 +132,20 @@ // Bad auth header, don't send back WWW-Authenticate header | ||
}) | ||
}, | ||
function(next) { | ||
assert.doesNotThrow( function() { | ||
request({ | ||
'method': 'GET', | ||
'uri': 'http://localhost:6767/allow_undefined_password/', | ||
'auth': { | ||
'user': 'justauser', | ||
'pass': undefined, | ||
'sendImmediately': false | ||
} | ||
}, function(error, res, body ) { | ||
assert.equal(res.statusCode, 200); | ||
assert.equal(numBasicRequests, 10); | ||
next(); | ||
}); | ||
}) | ||
} | ||
@@ -132,0 +152,0 @@ ]; |
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
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
202076
56
3322
333
26