1
+ import assert from 'assert' ;
1
2
import * as fs from 'fs' ;
2
3
import * as net from 'net' ;
3
4
import * as tls from 'tls' ;
4
- import * as url from 'url' ;
5
5
import * as http from 'http' ;
6
6
import * as https from 'https' ;
7
- import assert from 'assert ' ;
8
- import listen from 'async-listen' ;
9
- import { Agent , AgentConnectOpts } from '../src' ;
7
+ import { once } from 'events ' ;
8
+ import { listen } from 'async-listen' ;
9
+ import { Agent , AgentConnectOpts , req , json } from '../src' ;
10
10
11
11
const sleep = ( n : number ) => new Promise ( ( r ) => setTimeout ( r , n ) ) ;
12
12
13
- const req = ( opts : https . RequestOptions ) : Promise < http . IncomingMessage > =>
14
- new Promise ( ( resolve , reject ) => {
15
- ( opts . protocol === 'https:' ? https : http )
16
- . request ( opts , resolve )
17
- . once ( 'error' , reject )
18
- . end ( ) ;
19
- } ) ;
20
-
21
13
const sslOptions = {
22
14
key : fs . readFileSync ( `${ __dirname } /ssl-cert-snakeoil.key` ) ,
23
15
cert : fs . readFileSync ( `${ __dirname } /ssl-cert-snakeoil.pem` ) ,
24
16
} ;
25
17
26
- function json ( res : http . IncomingMessage ) : Promise < Record < string , string > > {
27
- return new Promise ( ( resolve ) => {
28
- let data = '' ;
29
- res . setEncoding ( 'utf8' ) ;
30
- res . on ( 'data' , ( b ) => {
31
- data += b ;
32
- } ) ;
33
- res . on ( 'end' , ( ) => resolve ( JSON . parse ( data ) ) ) ;
34
- } ) ;
35
- }
36
-
37
18
describe ( 'Agent (TypeScript)' , ( ) => {
38
19
describe ( 'subclass' , ( ) => {
39
20
it ( 'should be extendable (direct return)' , ( ) => {
@@ -91,8 +72,9 @@ describe('Agent (TypeScript)', () => {
91
72
const { port } = addr ;
92
73
93
74
try {
94
- const info = url . parse ( `http://127.0.0.1:${ port } /foo` ) ;
95
- const res = await req ( { agent, ...info } ) ;
75
+ const res = await req ( `http://127.0.0.1:${ port } /foo` , {
76
+ agent,
77
+ } ) ;
96
78
assert . equal ( 'bar' , res . headers [ 'x-foo' ] ) ;
97
79
assert . equal ( '/foo' , res . headers [ 'x-url' ] ) ;
98
80
assert ( gotReq ) ;
@@ -130,8 +112,9 @@ describe('Agent (TypeScript)', () => {
130
112
agent . defaultPort = port ;
131
113
132
114
try {
133
- const info = url . parse ( `http://127.0.0.1:${ port } /foo` ) ;
134
- const res = await req ( { agent, ...info } ) ;
115
+ const res = await req ( `http://127.0.0.1:${ port } /foo` , {
116
+ agent,
117
+ } ) ;
135
118
const body = await json ( res ) ;
136
119
assert . equal ( body . host , '127.0.0.1' ) ;
137
120
} finally {
@@ -172,8 +155,9 @@ describe('Agent (TypeScript)', () => {
172
155
const { port } = addr ;
173
156
174
157
try {
175
- const info = url . parse ( `http://127.0.0.1:${ port } /foo` ) ;
176
- const res = await req ( { agent, ...info } ) ;
158
+ const res = await req ( `http://127.0.0.1:${ port } /foo` , {
159
+ agent,
160
+ } ) ;
177
161
assert . equal ( 'bar' , res . headers [ 'x-foo' ] ) ;
178
162
assert . equal ( '/foo' , res . headers [ 'x-url' ] ) ;
179
163
assert ( gotReq ) ;
@@ -197,8 +181,7 @@ describe('Agent (TypeScript)', () => {
197
181
const agent = new MyAgent ( ) ;
198
182
199
183
try {
200
- const info = url . parse ( 'http://127.0.0.1/throws' ) ;
201
- await req ( { agent, ...info } ) ;
184
+ await req ( 'http://127.0.0.1/throws' , { agent } ) ;
202
185
} catch ( err : unknown ) {
203
186
gotError = true ;
204
187
assert . equal ( ( err as Error ) . message , 'bad' ) ;
@@ -223,8 +206,7 @@ describe('Agent (TypeScript)', () => {
223
206
const agent = new MyAgent ( ) ;
224
207
225
208
try {
226
- const info = url . parse ( 'http://127.0.0.1/throws' ) ;
227
- await req ( { agent, ...info } ) ;
209
+ await req ( 'http://127.0.0.1/throws' , { agent } ) ;
228
210
} catch ( err : unknown ) {
229
211
gotError = true ;
230
212
assert . equal ( ( err as Error ) . message , 'bad' ) ;
@@ -233,6 +215,72 @@ describe('Agent (TypeScript)', () => {
233
215
assert ( gotError ) ;
234
216
assert ( gotCallback ) ;
235
217
} ) ;
218
+
219
+ it ( 'should support `keepAlive: true`' , async ( ) => {
220
+ let reqCount1 = 0 ;
221
+ let reqCount2 = 0 ;
222
+ let connectCount = 0 ;
223
+
224
+ class MyAgent extends Agent {
225
+ async connect (
226
+ _req : http . ClientRequest ,
227
+ opts : AgentConnectOpts
228
+ ) {
229
+ connectCount ++ ;
230
+ assert ( opts . secureEndpoint === false ) ;
231
+ return net . connect ( opts ) ;
232
+ }
233
+ }
234
+ const agent = new MyAgent ( { keepAlive : true } ) ;
235
+
236
+ const server1 = http . createServer ( ( req , res ) => {
237
+ expect ( req . headers . connection ) . toEqual ( 'keep-alive' ) ;
238
+ reqCount1 ++ ;
239
+ res . end ( ) ;
240
+ } ) ;
241
+ const addr1 = ( await listen ( server1 ) ) as URL ;
242
+
243
+ const server2 = http . createServer ( ( req , res ) => {
244
+ expect ( req . headers . connection ) . toEqual ( 'keep-alive' ) ;
245
+ reqCount2 ++ ;
246
+ res . end ( ) ;
247
+ } ) ;
248
+ const addr2 = ( await listen ( server2 ) ) as URL ;
249
+
250
+ try {
251
+ const res = await req ( new URL ( '/foo' , addr1 ) , { agent } ) ;
252
+ expect ( reqCount1 ) . toEqual ( 1 ) ;
253
+ expect ( connectCount ) . toEqual ( 1 ) ;
254
+ expect ( res . headers . connection ) . toEqual ( 'keep-alive' ) ;
255
+ res . resume ( ) ;
256
+ const s1 = res . socket ;
257
+
258
+ await once ( s1 , 'free' ) ;
259
+
260
+ const res2 = await req ( new URL ( '/another' , addr1 ) , { agent } ) ;
261
+ expect ( reqCount1 ) . toEqual ( 2 ) ;
262
+ expect ( connectCount ) . toEqual ( 1 ) ;
263
+ expect ( res2 . headers . connection ) . toEqual ( 'keep-alive' ) ;
264
+ assert ( res2 . socket === s1 ) ;
265
+
266
+ res2 . resume ( ) ;
267
+ await once ( res2 . socket , 'free' ) ;
268
+
269
+ // This is a different host, so a new socket should be used
270
+ const res3 = await req ( new URL ( '/another' , addr2 ) , { agent } ) ;
271
+ expect ( reqCount2 ) . toEqual ( 1 ) ;
272
+ expect ( connectCount ) . toEqual ( 2 ) ;
273
+ expect ( res3 . headers . connection ) . toEqual ( 'keep-alive' ) ;
274
+ assert ( res3 . socket !== s1 ) ;
275
+
276
+ res3 . resume ( ) ;
277
+ await once ( res3 . socket , 'free' ) ;
278
+ } finally {
279
+ agent . destroy ( ) ;
280
+ server1 . close ( ) ;
281
+ server2 . close ( ) ;
282
+ }
283
+ } ) ;
236
284
} ) ;
237
285
238
286
describe ( '"https" module' , ( ) => {
@@ -268,11 +316,9 @@ describe('Agent (TypeScript)', () => {
268
316
const { port } = addr ;
269
317
270
318
try {
271
- const info = url . parse ( `https://127.0.0.1:${ port } /foo` ) ;
272
- const res = await req ( {
319
+ const res = await req ( `https://127.0.0.1:${ port } /foo` , {
273
320
agent,
274
321
rejectUnauthorized : false ,
275
- ...info ,
276
322
} ) ;
277
323
assert . equal ( 'bar' , res . headers [ 'x-foo' ] ) ;
278
324
assert . equal ( '/foo' , res . headers [ 'x-url' ] ) ;
@@ -328,11 +374,9 @@ describe('Agent (TypeScript)', () => {
328
374
const { port } = addr ;
329
375
330
376
try {
331
- const info = url . parse ( `https://127.0.0.1:${ port } /foo` ) ;
332
- const res = await req ( {
377
+ const res = await req ( `https://127.0.0.1:${ port } /foo` , {
333
378
agent : agent1 ,
334
379
rejectUnauthorized : false ,
335
- ...info ,
336
380
} ) ;
337
381
assert . equal ( 'bar' , res . headers [ 'x-foo' ] ) ;
338
382
assert . equal ( '/foo' , res . headers [ 'x-url' ] ) ;
@@ -376,11 +420,9 @@ describe('Agent (TypeScript)', () => {
376
420
agent . defaultPort = port ;
377
421
378
422
try {
379
- const info = url . parse ( `https://127.0.0.1:${ port } /foo` ) ;
380
- const res = await req ( {
423
+ const res = await req ( `https://127.0.0.1:${ port } /foo` , {
381
424
agent,
382
425
rejectUnauthorized : false ,
383
- ...info ,
384
426
} ) ;
385
427
const body = await json ( res ) ;
386
428
assert . equal ( body . host , '127.0.0.1' ) ;
@@ -389,5 +431,56 @@ describe('Agent (TypeScript)', () => {
389
431
server . close ( ) ;
390
432
}
391
433
} ) ;
434
+
435
+ it ( 'should support `keepAlive: true`' , async ( ) => {
436
+ let gotReq = false ;
437
+ let connectCount = 0 ;
438
+
439
+ class MyAgent extends Agent {
440
+ async connect (
441
+ _req : http . ClientRequest ,
442
+ opts : AgentConnectOpts
443
+ ) {
444
+ connectCount ++ ;
445
+ assert ( opts . secureEndpoint === true ) ;
446
+ return tls . connect ( opts ) ;
447
+ }
448
+ }
449
+ const agent = new MyAgent ( { keepAlive : true } ) ;
450
+
451
+ const server = https . createServer ( sslOptions , ( req , res ) => {
452
+ gotReq = true ;
453
+ res . end ( ) ;
454
+ } ) ;
455
+ const addr = ( await listen ( server ) ) as URL ;
456
+
457
+ try {
458
+ const res = await req ( new URL ( '/foo' , addr ) , {
459
+ agent,
460
+ rejectUnauthorized : false ,
461
+ } ) ;
462
+ assert ( gotReq ) ;
463
+ expect ( connectCount ) . toEqual ( 1 ) ;
464
+ expect ( res . headers . connection ) . toEqual ( 'keep-alive' ) ;
465
+ res . resume ( ) ;
466
+ const s1 = res . socket ;
467
+
468
+ await once ( s1 , 'free' ) ;
469
+
470
+ const res2 = await req ( new URL ( '/another' , addr ) , {
471
+ agent,
472
+ rejectUnauthorized : false ,
473
+ } ) ;
474
+ expect ( connectCount ) . toEqual ( 1 ) ;
475
+ expect ( res2 . headers . connection ) . toEqual ( 'keep-alive' ) ;
476
+ assert ( res2 . socket === s1 ) ;
477
+
478
+ res2 . resume ( ) ;
479
+ await once ( res2 . socket , 'free' ) ;
480
+ } finally {
481
+ agent . destroy ( ) ;
482
+ server . close ( ) ;
483
+ }
484
+ } ) ;
392
485
} ) ;
393
486
} ) ;
1 commit comments
vercel[bot] commentedon May 3, 2023
Successfully deployed to the following URLs:
proxy-agents – ./
proxy-agents.vercel.app
proxy-agents-git-main-tootallnate.vercel.app
proxy-agents-tootallnate.vercel.app