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