@@ -36,13 +36,20 @@ var EventEmitter = require('events').EventEmitter;
36
36
// concerned with managing a connection pool.
37
37
38
38
function Agent ( options ) {
39
+ if ( ! ( this instanceof Agent ) )
40
+ return new Agent ( options ) ;
41
+
39
42
EventEmitter . call ( this ) ;
40
43
41
44
var self = this ;
42
45
self . options = options || { } ;
43
46
self . requests = { } ;
44
47
self . sockets = { } ;
48
+ self . freeSockets = { } ;
49
+ self . keepAliveMsecs = self . options . keepAliveMsecs || 1000 ;
50
+ self . keepAlive = self . options . keepAlive || false ;
45
51
self . maxSockets = self . options . maxSockets || Agent . defaultMaxSockets ;
52
+
46
53
self . on ( 'free' , function ( socket , host , port , localAddress ) {
47
54
var name = host + ':' + port ;
48
55
if ( localAddress ) {
@@ -57,11 +64,31 @@ function Agent(options) {
57
64
delete self . requests [ name ] ;
58
65
}
59
66
} else {
60
- // If there are no pending requests just destroy the
61
- // socket and it will get removed from the pool. This
62
- // gets us out of timeout issues and allows us to
63
- // default to Connection:keep-alive.
64
- socket . destroy ( ) ;
67
+ // If there are no pending requests, then put it in
68
+ // the freeSockets pool, but only if we're allowed to do so.
69
+ var req = socket . _httpMessage ;
70
+ if ( req &&
71
+ req . shouldKeepAlive &&
72
+ ! socket . destroyed &&
73
+ self . options . keepAlive ) {
74
+ var freeSockets = self . freeSockets [ name ] ;
75
+ var count = freeSockets ? freeSockets . length : 0 ;
76
+ if ( self . sockets [ name ] )
77
+ count += self . sockets [ name ] . length ;
78
+
79
+ if ( count > self . maxSockets ) {
80
+ socket . destroy ( ) ;
81
+ } else {
82
+ freeSockets = freeSockets || [ ] ;
83
+ self . freeSockets [ name ] = freeSockets ;
84
+ socket . setKeepAlive ( true , self . keepAliveMsecs ) ;
85
+ socket . unref ( ) ;
86
+ socket . _httpMessage = null ;
87
+ freeSockets . push ( socket ) ;
88
+ }
89
+ } else {
90
+ socket . destroy ( ) ;
91
+ }
65
92
}
66
93
} ) ;
67
94
self . createConnection = net . createConnection ;
@@ -70,7 +97,7 @@ function Agent(options) {
70
97
util . inherits ( Agent , EventEmitter ) ;
71
98
exports . Agent = Agent ;
72
99
73
- Agent . defaultMaxSockets = 5 ;
100
+ Agent . defaultMaxSockets = Infinity ;
74
101
75
102
Agent . prototype . defaultPort = 80 ;
76
103
Agent . prototype . addRequest = function ( req , host , port , localAddress ) {
@@ -81,7 +108,18 @@ Agent.prototype.addRequest = function(req, host, port, localAddress) {
81
108
if ( ! this . sockets [ name ] ) {
82
109
this . sockets [ name ] = [ ] ;
83
110
}
84
- if ( this . sockets [ name ] . length < this . maxSockets ) {
111
+
112
+ if ( this . freeSockets [ name ] && this . freeSockets [ name ] . length ) {
113
+ // we have a free socket, so use that.
114
+ var socket = this . freeSockets [ name ] . shift ( ) ;
115
+
116
+ // don't leak
117
+ if ( ! this . freeSockets [ name ] . length )
118
+ delete this . freeSockets [ name ] ;
119
+
120
+ socket . ref ( ) ;
121
+ req . onSocket ( socket ) ;
122
+ } else if ( this . sockets [ name ] . length < this . maxSockets ) {
85
123
// If we are under maxSockets create a new one.
86
124
req . onSocket ( this . createSocket ( name , host , port , localAddress , req ) ) ;
87
125
} else {
@@ -158,5 +196,16 @@ Agent.prototype.removeSocket = function(s, name, host, port, localAddress) {
158
196
}
159
197
} ;
160
198
199
+ Agent . prototype . destroy = function ( ) {
200
+ var sets = [ this . freeSockets , this . sockets ] ;
201
+ sets . forEach ( function ( set ) {
202
+ Object . keys ( set ) . forEach ( function ( name ) {
203
+ set [ name ] . forEach ( function ( socket ) {
204
+ socket . destroy ( ) ;
205
+ } ) ;
206
+ } ) ;
207
+ } ) ;
208
+ } ;
209
+
161
210
var globalAgent = new Agent ( ) ;
162
211
exports . globalAgent = globalAgent ;
0 commit comments