diff options
Diffstat (limited to 'deps/npm/node_modules/request/main.js')
-rw-r--r-- | deps/npm/node_modules/request/main.js | 158 |
1 files changed, 127 insertions, 31 deletions
diff --git a/deps/npm/node_modules/request/main.js b/deps/npm/node_modules/request/main.js index 5c14264163..f651202740 100644 --- a/deps/npm/node_modules/request/main.js +++ b/deps/npm/node_modules/request/main.js @@ -26,6 +26,7 @@ var http = require('http') , Cookie = require('./vendor/cookie') , CookieJar = require('./vendor/cookie/jar') , cookieJar = new CookieJar + , tunnel = require('./tunnel') ; if (process.logging) { @@ -133,6 +134,20 @@ Request.prototype.init = function (options) { } if (self.proxy) { if (typeof self.proxy == 'string') self.proxy = url.parse(self.proxy) + + // do the HTTP CONNECT dance using koichik/node-tunnel + if (http.globalAgent && self.uri.protocol === "https:") { + self.tunnel = true + var tunnelFn = self.proxy.protocol === "http:" + ? tunnel.httpsOverHttp : tunnel.httpsOverHttps + + var tunnelOptions = { proxy: { host: self.proxy.hostname + , port: +self.proxy.port } + , ca: this.ca } + + self.agent = tunnelFn(tunnelOptions) + self.tunnel = true + } } self._redirectsFollowed = self._redirectsFollowed || 0 @@ -163,7 +178,7 @@ Request.prototype.init = function (options) { else if (self.uri.protocol == 'https:') {self.uri.port = 443} } - if (self.proxy) { + if (self.proxy && !self.tunnel) { self.port = self.proxy.port self.host = self.proxy.hostname } else { @@ -177,9 +192,12 @@ Request.prototype.init = function (options) { } self.clientErrorHandler = function (error) { + if (self._aborted) return + if (self.setHost) delete self.headers.host - if (self.req._reusedSocket && error.code === 'ECONNRESET') { - self.agent = {addRequest: ForeverAgent.prototype.addRequestNoreuse.bind(self.agent)} + if (self.req._reusedSocket && error.code === 'ECONNRESET' + && self.agent.addRequestNoreuse) { + self.agent = { addRequest: self.agent.addRequestNoreuse.bind(self.agent) } self.start() self.req.end() return @@ -204,7 +222,7 @@ Request.prototype.init = function (options) { if (self.uri.auth && !self.headers.authorization) { self.headers.authorization = "Basic " + toBase64(self.uri.auth.split(':').map(function(item){ return qs.unescape(item)}).join(':')) } - if (self.proxy && self.proxy.auth && !self.headers['proxy-authorization']) { + 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 qs.unescape(item)}).join(':')) } @@ -218,7 +236,7 @@ Request.prototype.init = function (options) { if (self.path.length === 0) self.path = '/' - if (self.proxy) 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) @@ -247,7 +265,7 @@ Request.prototype.init = function (options) { } } - var protocol = self.proxy ? self.proxy.protocol : self.uri.protocol + var protocol = self.proxy && !self.tunnel ? self.proxy.protocol : self.uri.protocol , defaultModules = {'http:':http, 'https:':https} , httpModules = self.httpModules || {} ; @@ -255,17 +273,30 @@ Request.prototype.init = function (options) { if (!self.httpModule) throw new Error("Invalid protocol") + if (options.ca) self.ca = options.ca + + if (!self.agent) { + if (options.agentOptions) self.agentOptions = options.agentOptions + + 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.pool === false) { self.agent = false } else { + self.agent = self.agent || self.getAgent() if (self.maxSockets) { // Don't use our pooling if node has the refactored client - self.agent = self.agent || self.httpModule.globalAgent || self.getAgent(self.host, self.port) self.agent.maxSockets = self.maxSockets } if (self.pool.maxSockets) { // Don't use our pooling if node has the refactored client - self.agent = self.agent || self.httpModule.globalAgent || self.getAgent(self.host, self.port) self.agent.maxSockets = self.pool.maxSockets } } @@ -295,6 +326,8 @@ Request.prototype.init = function (options) { }) process.nextTick(function () { + if (self._aborted) return + if (self.body) { if (Array.isArray(self.body)) { self.body.forEach(function(part) { @@ -314,19 +347,61 @@ Request.prototype.init = function (options) { self.ntick = true }) } -Request.prototype.getAgent = function (host, port) { - if (!this.pool[host+':'+port]) { - this.pool[host+':'+port] = new this.httpModule.Agent({host:host, port:port}) + +Request.prototype.getAgent = function () { + var Agent = this.agentClass + var options = {} + if (this.agentOptions) { + for (var i in this.agentOptions) { + options[i] = this.agentOptions[i] + } + } + if (this.ca) options.ca = this.ca + + var poolKey = '' + + // different types of agents are in different pools + if (Agent !== this.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 } - return this.pool[host+':'+port] + + if (options.ca) { + if (poolKey) poolKey += ':' + poolKey += options.ca + } + + if (!poolKey && Agent === this.httpModule.Agent && this.httpModule.globalAgent) { + // not doing anything special. Use the globalAgent + return this.httpModule.globalAgent + } + + // already generated an agent for this setting + if (this.pool[poolKey]) return this.pool[poolKey] + + return this.pool[poolKey] = new Agent(options) } + Request.prototype.start = function () { var self = this + + if (self._aborted) return + self._started = true self.method = self.method || 'GET' self.href = self.uri.href if (log) log('%method %href', self) self.req = self.httpModule.request(self, function (response) { + if (self._aborted) return + if (self._paused) response.pause() + self.response = response response.request = self @@ -353,7 +428,7 @@ Request.prototype.start = function () { if (response.statusCode >= 300 && response.statusCode < 400 && (self.followAllRedirects || - (self.followRedirect && (self.method !== 'PUT' && self.method !== 'POST'))) && + (self.followRedirect && (self.method !== 'PUT' && self.method !== 'POST' && self.method !== 'DELETE'))) && response.headers.location) { if (self._redirectsFollowed >= self.maxRedirects) { self.emit('error', new Error("Exceeded maxRedirects. Probably stuck in a redirect loop.")) @@ -423,6 +498,8 @@ Request.prototype.start = function () { bodyLen += chunk.length }) self.on("end", function () { + if (self._aborted) return + if (buffer.length && Buffer.isBuffer(buffer[0])) { var body = new Buffer(bodyLen) var i = 0 @@ -439,7 +516,7 @@ Request.prototype.start = function () { response.body = buffer.join('') } - if (self.json) { + if (self._json) { try { response.body = JSON.parse(response.body) } catch (e) {} @@ -461,20 +538,36 @@ Request.prototype.start = function () { // Set additional timeout on socket - in case if remote // server freeze after sending headers - self.req.setTimeout(self.timeout, function(){ - if (self.req) { - self.req.abort() - var e = new Error("ESOCKETTIMEDOUT") - e.code = "ESOCKETTIMEDOUT" - self.emit("error", e) - } - }); + if (self.req.setTimeout) { // only works on node 0.6+ + self.req.setTimeout(self.timeout, function(){ + if (self.req) { + self.req.abort() + var e = new Error("ESOCKETTIMEDOUT") + e.code = "ESOCKETTIMEDOUT" + self.emit("error", e) + } + }) + } } self.req.on('error', self.clientErrorHandler) self.emit('request', self.req) } + +Request.prototype.abort = function() { + this._aborted = true; + + if (this.req) { + this.req.abort() + } + else if (this.response) { + this.response.abort() + } + + this.emit("abort") +} + Request.prototype.pipeDest = function (dest) { var response = this.response // Called after the response is received @@ -554,6 +647,7 @@ Request.prototype.multipart = function (multipart) { Request.prototype.json = function (val) { this.setHeader('content-type', 'application/json') this.setHeader('accept', 'application/json') + this._json = true if (typeof val === 'boolean') { if (typeof this.body === 'object') this.body = JSON.stringify(this.body) } else { @@ -659,22 +753,20 @@ Request.prototype.pipe = function (dest, opts) { } Request.prototype.write = function () { if (!this._started) this.start() - if (!this.req) throw new Error("This request has been piped before http.request() was called.") this.req.write.apply(this.req, arguments) } Request.prototype.end = function (chunk) { if (chunk) this.write(chunk) if (!this._started) this.start() - if (!this.req) throw new Error("This request has been piped before http.request() was called.") this.req.end() } Request.prototype.pause = function () { - if (!this.response) throw new Error("This request has been piped before http.request() was called.") - this.response.pause.apply(this.response, arguments) + if (!this.response) this._paused = true + else this.response.pause.apply(this.response, arguments) } Request.prototype.resume = function () { - if (!this.response) throw new Error("This request has been piped before http.request() was called.") - this.response.resume.apply(this.response, arguments) + if (!this.response) this._paused = false + else this.response.resume.apply(this.response, arguments) } Request.prototype.destroy = function () { if (!this._ended) this.end() @@ -735,12 +827,13 @@ request.defaults = function (options) { request.forever = function (agentOptions, optionsArg) { var options = {} - if (agentOptions) { + if (optionsArg) { for (option in optionsArg) { options[option] = optionsArg[option] } } - options.agent = new ForeverAgent(agentOptions) + if (agentOptions) options.agentOptions = agentOptions + options.forever = true return request.defaults(options) } @@ -758,7 +851,10 @@ request.put = function (uri, options, callback) { request.head = function (uri, options, callback) { var params = initParams(uri, options, callback); params.options.method = 'HEAD' - if (options.body || options.requestBodyStream || options.json || options.multipart) { + 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.") } return request(params.uri, params.options, params.callback) |