@@ -305,6 +305,192 @@ describe('compression()', function () {
305
305
. expect ( 200 , done )
306
306
} )
307
307
308
+ it ( 'should support removeListener("drain") after on("drain"); stream present' , function ( done ) {
309
+ // compression doesn't proxy listenerCount() to the compression stream, so
310
+ // instead watch for a MaxListenersExceededWarning
311
+ var hasWarned = false
312
+ var onWarning = function ( ) {
313
+ hasWarned = true
314
+ }
315
+ process . on ( 'warning' , onWarning )
316
+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
317
+ res . setHeader ( 'Content-Type' , 'text/plain' )
318
+ var len = bytes ( '40kb' )
319
+ var buf = Buffer . alloc ( len , '.' )
320
+ res . write ( buf )
321
+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
322
+ var listener = function ( ) { }
323
+ res . on ( 'drain' , listener )
324
+ res . removeListener ( 'drain' , listener )
325
+ }
326
+ res . end ( )
327
+ } )
328
+
329
+ request ( server )
330
+ . get ( '/' )
331
+ . set ( 'Accept-Encoding' , 'gzip' )
332
+ . expect ( function ( ) {
333
+ process . removeListener ( 'warning' , onWarning )
334
+ assert . ok ( ! hasWarned )
335
+ } )
336
+ . expect ( 200 , done )
337
+ } )
338
+
339
+ it ( 'should support removeListener("drain") after addListener("drain")' , function ( done ) {
340
+ var hasWarned = false
341
+ var onWarning = function ( ) {
342
+ hasWarned = true
343
+ }
344
+ process . on ( 'warning' , onWarning )
345
+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
346
+ res . setHeader ( 'Content-Type' , 'text/plain' )
347
+ var len = bytes ( '40kb' )
348
+ var buf = Buffer . alloc ( len , '.' )
349
+ res . write ( buf )
350
+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
351
+ var listener = function ( ) { }
352
+ res . addListener ( 'drain' , listener )
353
+ res . removeListener ( 'drain' , listener )
354
+ }
355
+ res . end ( )
356
+ } )
357
+
358
+ request ( server )
359
+ . get ( '/' )
360
+ . set ( 'Accept-Encoding' , 'gzip' )
361
+ . expect ( function ( ) {
362
+ process . removeListener ( 'warning' , onWarning )
363
+ assert . ok ( ! hasWarned )
364
+ } )
365
+ . expect ( 200 , done )
366
+ } )
367
+
368
+ it ( 'should support off("drain") after addListener("drain")' , function ( done ) {
369
+ if ( ! require ( 'events' ) . EventEmitter . prototype . off ) { // off was added in Node.js v10
370
+ this . skip ( )
371
+ }
372
+ var hasWarned = false
373
+ var onWarning = function ( ) {
374
+ hasWarned = true
375
+ }
376
+ process . on ( 'warning' , onWarning )
377
+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
378
+ res . setHeader ( 'Content-Type' , 'text/plain' )
379
+ var len = bytes ( '40kb' )
380
+ var buf = Buffer . alloc ( len , '.' )
381
+ res . write ( buf )
382
+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
383
+ var listener = function ( ) { }
384
+ res . addListener ( 'drain' , listener )
385
+ res . off ( 'drain' , listener )
386
+ }
387
+ res . end ( )
388
+ } )
389
+
390
+ request ( server )
391
+ . get ( '/' )
392
+ . set ( 'Accept-Encoding' , 'gzip' )
393
+ . expect ( function ( ) {
394
+ process . removeListener ( 'warning' , onWarning )
395
+ assert . ok ( ! hasWarned )
396
+ } )
397
+ . expect ( 200 , done )
398
+ } )
399
+
400
+ it ( 'should support removeListener("drain"); buffered' , function ( done ) {
401
+ // Variant of above tests for scenario when the listener is buffered (stream
402
+ // is not yet present).
403
+ var hasWarned = false
404
+ var onWarning = function ( ) {
405
+ hasWarned = true
406
+ }
407
+ process . on ( 'warning' , onWarning )
408
+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
409
+ res . setHeader ( 'Content-Type' , 'text/plain' )
410
+ res . on ( 'end' , function ( ) { } )
411
+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
412
+ var listener = function ( ) { }
413
+ res . on ( 'drain' , listener )
414
+ res . removeListener ( 'drain' , listener )
415
+ }
416
+ res . end ( )
417
+ } )
418
+
419
+ request ( server )
420
+ . get ( '/' )
421
+ . set ( 'Accept-Encoding' , 'gzip' )
422
+ . expect ( function ( ) {
423
+ process . removeListener ( 'warning' , onWarning )
424
+ assert . ok ( ! hasWarned )
425
+ } )
426
+ . expect ( 200 , done )
427
+ } )
428
+
429
+ it ( 'should support removeListener("drain"); multiple bindings of same listener, buffered' , function ( done ) {
430
+ // Variant of above test for scenario when the listener is buffered (stream
431
+ // is not yet present) and the same listener is added two or more times.
432
+ var hasWarned = false
433
+ var onWarning = function ( ) {
434
+ hasWarned = true
435
+ }
436
+ process . on ( 'warning' , onWarning )
437
+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
438
+ res . setHeader ( 'Content-Type' , 'text/plain' )
439
+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
440
+ var listener = function ( ) { }
441
+ res . on ( 'drain' , listener )
442
+ res . on ( 'drain' , listener )
443
+ res . removeListener ( 'drain' , listener )
444
+ }
445
+ res . end ( )
446
+ } )
447
+
448
+ request ( server )
449
+ . get ( '/' )
450
+ . set ( 'Accept-Encoding' , 'gzip' )
451
+ . expect ( function ( ) {
452
+ process . removeListener ( 'warning' , onWarning )
453
+ assert . ok ( ! hasWarned )
454
+ } )
455
+ . expect ( 200 , done )
456
+ } )
457
+
458
+ it ( 'should not leak event listeners when res.unpipe() is used (#135)' , function ( done ) {
459
+ // unpipe and stream.Readable were added in v0.9.4
460
+ var stream = require ( 'stream' )
461
+ if ( ! ( stream . Readable && stream . Readable . prototype . unpipe ) ) {
462
+ this . skip ( )
463
+ }
464
+
465
+ var hasWarned = false
466
+ var onWarning = function ( ) {
467
+ hasWarned = true
468
+ }
469
+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
470
+ var times = 0
471
+ var int = setInterval ( function ( ) {
472
+ var rs = require ( 'fs' ) . createReadStream ( 'does not exist' )
473
+ rs . on ( 'error' , function ( e ) {
474
+ rs . unpipe ( res )
475
+ } )
476
+ rs . pipe ( res )
477
+ if ( times ++ > res . getMaxListeners ( ) ) {
478
+ clearInterval ( int )
479
+ res . end ( 'hello, world' )
480
+ }
481
+ } )
482
+ } )
483
+
484
+ request ( server )
485
+ . get ( '/' )
486
+ . set ( 'Accept-Encoding' , 'gzip' )
487
+ . expect ( function ( ) {
488
+ process . removeListener ( 'warning' , onWarning )
489
+ assert . ok ( ! hasWarned )
490
+ } )
491
+ . expect ( 200 , done )
492
+ } )
493
+
308
494
describe ( 'threshold' , function ( ) {
309
495
it ( 'should not compress responses below the threshold size' , function ( done ) {
310
496
var server = createServer ( { threshold : '1kb' } , function ( req , res ) {
@@ -669,6 +855,13 @@ function createServer (opts, fn) {
669
855
return
670
856
}
671
857
858
+ if ( typeof res . getMaxListeners !== 'function' ) {
859
+ // Added in v0.11.2
860
+ res . getMaxListeners = function getMaxListeners ( ) {
861
+ return 10
862
+ }
863
+ }
864
+
672
865
fn ( req , res )
673
866
} )
674
867
} )
0 commit comments