@@ -24,6 +24,7 @@ var url = require('url');
24
24
var util = require ( 'util' ) ;
25
25
var EventEmitter = require ( 'events' ) . EventEmitter ;
26
26
var ClientRequest = require ( '_http_client' ) . ClientRequest ;
27
+ var debug = util . debuglog ( 'http' ) ;
27
28
28
29
// New Agent code.
29
30
@@ -44,7 +45,12 @@ function Agent(options) {
44
45
EventEmitter . call ( this ) ;
45
46
46
47
var self = this ;
48
+
49
+ self . defaultPort = 80 ;
50
+ self . protocol = 'http:' ;
51
+
47
52
self . options = util . _extend ( { } , options ) ;
53
+
48
54
// don't confuse net and make it think that we're connecting to a pipe
49
55
self . options . path = null ;
50
56
self . requests = { } ;
@@ -54,11 +60,9 @@ function Agent(options) {
54
60
self . keepAlive = self . options . keepAlive || false ;
55
61
self . maxSockets = self . options . maxSockets || Agent . defaultMaxSockets ;
56
62
57
- self . on ( 'free' , function ( socket , host , port , localAddress ) {
58
- var name = host + ':' + port ;
59
- if ( localAddress ) {
60
- name += ':' + localAddress ;
61
- }
63
+ self . on ( 'free' , function ( socket , options ) {
64
+ var name = self . getName ( options ) ;
65
+ debug ( 'agent.on(free)' , name ) ;
62
66
63
67
if ( ! socket . destroyed &&
64
68
self . requests [ name ] && self . requests [ name ] . length ) {
@@ -103,18 +107,38 @@ exports.Agent = Agent;
103
107
Agent . defaultMaxSockets = Infinity ;
104
108
105
109
Agent . prototype . createConnection = net . createConnection ;
106
- Agent . prototype . defaultPort = 80 ;
107
- Agent . prototype . protocol = 'http:' ;
108
- Agent . prototype . addRequest = function ( req , host , port , localAddress ) {
109
- var name = host + ':' + port ;
110
- if ( localAddress ) {
111
- name += ':' + localAddress ;
112
- }
110
+
111
+ // Get the key for a given set of request options
112
+ Agent . prototype . getName = function ( options ) {
113
+ var name = '' ;
114
+
115
+ if ( options . host )
116
+ name += options . host ;
117
+ else
118
+ name += 'localhost' ;
119
+
120
+ name += ':' ;
121
+ if ( options . port )
122
+ name += options . port ;
123
+ name += ':' ;
124
+ if ( options . localAddress )
125
+ name += options . localAddress ;
126
+ name += ':' ;
127
+ return name ;
128
+ } ;
129
+
130
+ Agent . prototype . addRequest = function ( req , options ) {
131
+ var host = options . host ;
132
+ var port = options . port ;
133
+ var localAddress = options . localAddress ;
134
+
135
+ var name = this . getName ( options ) ;
113
136
if ( ! this . sockets [ name ] ) {
114
137
this . sockets [ name ] = [ ] ;
115
138
}
116
139
117
140
if ( this . freeSockets [ name ] && this . freeSockets [ name ] . length ) {
141
+ debug ( 'have free socket' ) ;
118
142
// we have a free socket, so use that.
119
143
var socket = this . freeSockets [ name ] . shift ( ) ;
120
144
@@ -125,9 +149,11 @@ Agent.prototype.addRequest = function(req, host, port, localAddress) {
125
149
socket . ref ( ) ;
126
150
req . onSocket ( socket ) ;
127
151
} else if ( this . sockets [ name ] . length < this . maxSockets ) {
152
+ debug ( 'call onSocket' ) ;
128
153
// If we are under maxSockets create a new one.
129
- req . onSocket ( this . createSocket ( name , host , port , localAddress , req ) ) ;
154
+ req . onSocket ( this . createSocket ( req , options ) ) ;
130
155
} else {
156
+ debug ( 'wait for socket' ) ;
131
157
// We are over limit so we'll add it to the queue.
132
158
if ( ! this . requests [ name ] ) {
133
159
this . requests [ name ] = [ ] ;
@@ -136,45 +162,49 @@ Agent.prototype.addRequest = function(req, host, port, localAddress) {
136
162
}
137
163
} ;
138
164
139
- Agent . prototype . createSocket = function ( name , host , port , localAddress , req ) {
165
+ Agent . prototype . createSocket = function ( req , options ) {
140
166
var self = this ;
141
- var options = util . _extend ( { } , self . options ) ;
142
- options . port = port ;
143
- options . host = host ;
144
- options . localAddress = localAddress ;
167
+ options = util . _extend ( { } , options ) ;
168
+ options = util . _extend ( options , self . options ) ;
145
169
146
- options . servername = host ;
170
+ options . servername = options . host ;
147
171
if ( req ) {
148
172
var hostHeader = req . getHeader ( 'host' ) ;
149
173
if ( hostHeader ) {
150
174
options . servername = hostHeader . replace ( / : .* $ / , '' ) ;
151
175
}
152
176
}
153
177
178
+ var name = self . getName ( options ) ;
179
+
180
+ debug ( 'createConnection' , name , options ) ;
154
181
var s = self . createConnection ( options ) ;
155
182
if ( ! self . sockets [ name ] ) {
156
183
self . sockets [ name ] = [ ] ;
157
184
}
158
185
this . sockets [ name ] . push ( s ) ;
186
+ debug ( 'sockets' , name , this . sockets [ name ] . length ) ;
159
187
160
188
function onFree ( ) {
161
- self . emit ( 'free' , s , host , port , localAddress ) ;
189
+ self . emit ( 'free' , s , options ) ;
162
190
}
163
191
s . on ( 'free' , onFree ) ;
164
192
165
193
function onClose ( err ) {
194
+ debug ( 'CLIENT socket onClose' ) ;
166
195
// This is the only place where sockets get removed from the Agent.
167
196
// If you want to remove a socket from the pool, just close it.
168
197
// All socket errors end in a close event anyway.
169
- self . removeSocket ( s , name , host , port , localAddress ) ;
198
+ self . removeSocket ( s , options ) ;
170
199
}
171
200
s . on ( 'close' , onClose ) ;
172
201
173
202
function onRemove ( ) {
174
203
// We need this function for cases like HTTP 'upgrade'
175
- // (defined by WebSockets) where we need to remove a socket from the pool
176
- // because it'll be locked up indefinitely
177
- self . removeSocket ( s , name , host , port , localAddress ) ;
204
+ // (defined by WebSockets) where we need to remove a socket from the
205
+ // pool because it'll be locked up indefinitely
206
+ debug ( 'CLIENT socket onRemove' ) ;
207
+ self . removeSocket ( s , options ) ;
178
208
s . removeListener ( 'close' , onClose ) ;
179
209
s . removeListener ( 'free' , onFree ) ;
180
210
s . removeListener ( 'agentRemove' , onRemove ) ;
@@ -183,7 +213,9 @@ Agent.prototype.createSocket = function(name, host, port, localAddress, req) {
183
213
return s ;
184
214
} ;
185
215
186
- Agent . prototype . removeSocket = function ( s , name , host , port , localAddress ) {
216
+ Agent . prototype . removeSocket = function ( s , options ) {
217
+ var name = this . getName ( options ) ;
218
+ debug ( 'removeSocket' , name ) ;
187
219
if ( this . sockets [ name ] ) {
188
220
var index = this . sockets [ name ] . indexOf ( s ) ;
189
221
if ( index !== - 1 ) {
@@ -195,9 +227,10 @@ Agent.prototype.removeSocket = function(s, name, host, port, localAddress) {
195
227
}
196
228
}
197
229
if ( this . requests [ name ] && this . requests [ name ] . length ) {
230
+ debug ( 'removeSocket, have a request, make a socket' ) ;
198
231
var req = this . requests [ name ] [ 0 ] ;
199
- // If we have pending requests and a socket gets closed a new one
200
- this . createSocket ( name , host , port , localAddress , req ) . emit ( 'free' ) ;
232
+ // If we have pending requests and a socket gets closed make a new one
233
+ this . createSocket ( req , options ) . emit ( 'free' ) ;
201
234
}
202
235
} ;
203
236
@@ -216,6 +249,10 @@ Agent.prototype.request = function(options, cb) {
216
249
if ( typeof options === 'string' ) {
217
250
options = url . parse ( options ) ;
218
251
}
252
+ // don't try to do dns lookups of foo.com:8080, just foo.com
253
+ if ( options . hostname ) {
254
+ options . host = options . hostname ;
255
+ }
219
256
220
257
if ( options && options . path && / / . test ( options . path ) ) {
221
258
// The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/
@@ -229,11 +266,16 @@ Agent.prototype.request = function(options, cb) {
229
266
throw new Error ( 'Protocol:' + options . protocol + ' not supported.' ) ;
230
267
}
231
268
232
- options = util . _extend ( { agent : this , keepAlive : false } , options ) ;
269
+ options = util . _extend ( {
270
+ agent : this ,
271
+ keepAlive : this . keepAlive
272
+ } , options ) ;
233
273
274
+ // if it's false, then make a new one, just like this one.
234
275
if ( options . agent === false )
235
- options . agent = new Agent ( options ) ;
276
+ options . agent = new this . constructor ( options ) ;
236
277
278
+ debug ( 'agent.request' , options ) ;
237
279
return new ClientRequest ( options , cb ) ;
238
280
} ;
239
281
0 commit comments