/node_modules/request/forever.js
JavaScript | 103 lines | 82 code | 13 blank | 8 comment | 23 complexity | fe32e57be097509d95316e64112d2b7e MD5 | raw file
Possible License(s): Apache-2.0, MIT
1module.exports = ForeverAgent 2ForeverAgent.SSL = ForeverAgentSSL 3 4var util = require('util') 5 , Agent = require('http').Agent 6 , net = require('net') 7 , tls = require('tls') 8 , AgentSSL = require('https').Agent 9 10function ForeverAgent(options) { 11 var self = this 12 self.options = options || {} 13 self.requests = {} 14 self.sockets = {} 15 self.freeSockets = {} 16 self.maxSockets = self.options.maxSockets || Agent.defaultMaxSockets 17 self.minSockets = self.options.minSockets || ForeverAgent.defaultMinSockets 18 self.on('free', function(socket, host, port) { 19 var name = host + ':' + port 20 if (self.requests[name] && self.requests[name].length) { 21 self.requests[name].shift().onSocket(socket) 22 } else if (self.sockets[name].length < self.minSockets) { 23 if (!self.freeSockets[name]) self.freeSockets[name] = [] 24 self.freeSockets[name].push(socket) 25 26 // if an error happens while we don't use the socket anyway, meh, throw the socket away 27 function onIdleError() { 28 socket.destroy() 29 } 30 socket._onIdleError = onIdleError 31 socket.on('error', onIdleError) 32 } else { 33 // If there are no pending requests just destroy the 34 // socket and it will get removed from the pool. This 35 // gets us out of timeout issues and allows us to 36 // default to Connection:keep-alive. 37 socket.destroy(); 38 } 39 }) 40 41} 42util.inherits(ForeverAgent, Agent) 43 44ForeverAgent.defaultMinSockets = 5 45 46 47ForeverAgent.prototype.createConnection = net.createConnection 48ForeverAgent.prototype.addRequestNoreuse = Agent.prototype.addRequest 49ForeverAgent.prototype.addRequest = function(req, host, port) { 50 var name = host + ':' + port 51 if (this.freeSockets[name] && this.freeSockets[name].length > 0 && !req.useChunkedEncodingByDefault) { 52 var idleSocket = this.freeSockets[name].pop() 53 idleSocket.removeListener('error', idleSocket._onIdleError) 54 delete idleSocket._onIdleError 55 req._reusedSocket = true 56 req.onSocket(idleSocket) 57 } else { 58 this.addRequestNoreuse(req, host, port) 59 } 60} 61 62ForeverAgent.prototype.removeSocket = function(s, name, host, port) { 63 if (this.sockets[name]) { 64 var index = this.sockets[name].indexOf(s); 65 if (index !== -1) { 66 this.sockets[name].splice(index, 1); 67 } 68 } else if (this.sockets[name] && this.sockets[name].length === 0) { 69 // don't leak 70 delete this.sockets[name]; 71 delete this.requests[name]; 72 } 73 74 if (this.freeSockets[name]) { 75 var index = this.freeSockets[name].indexOf(s) 76 if (index !== -1) { 77 this.freeSockets[name].splice(index, 1) 78 if (this.freeSockets[name].length === 0) { 79 delete this.freeSockets[name] 80 } 81 } 82 } 83 84 if (this.requests[name] && this.requests[name].length) { 85 // If we have pending requests and a socket gets closed a new one 86 // needs to be created to take over in the pool for the one that closed. 87 this.createSocket(name, host, port).emit('free'); 88 } 89} 90 91function ForeverAgentSSL (options) { 92 ForeverAgent.call(this, options) 93} 94util.inherits(ForeverAgentSSL, ForeverAgent) 95 96ForeverAgentSSL.prototype.createConnection = createConnectionSSL 97ForeverAgentSSL.prototype.addRequestNoreuse = AgentSSL.prototype.addRequest 98 99function createConnectionSSL (port, host, options) { 100 options.port = port 101 options.host = host 102 return tls.connect(options) 103}