@@ -13,6 +13,7 @@ import (
13
13
"net/http/httputil"
14
14
"net/url"
15
15
"strconv"
16
+ "strings"
16
17
"testing"
17
18
18
19
"github.com/gin-gonic/gin"
@@ -136,6 +137,17 @@ func TestGzipPNG(t *testing.T) {
136
137
assert .Equal (t , w .Body .String (), "this is a PNG!" )
137
138
}
138
139
140
+ func TestWriteString (t * testing.T ) {
141
+ testC , _ := gin .CreateTestContext (httptest .NewRecorder ())
142
+ gz := gzipWriter {
143
+ ResponseWriter : testC .Writer ,
144
+ writer : gzip .NewWriter (testC .Writer ),
145
+ }
146
+ n , err := gz .WriteString ("test" )
147
+ assert .NoError (t , err )
148
+ assert .Equal (t , 4 , n )
149
+ }
150
+
139
151
func TestExcludedPathsAndExtensions (t * testing.T ) {
140
152
tests := []struct {
141
153
path string
@@ -377,6 +389,138 @@ func TestCustomShouldCompressFn(t *testing.T) {
377
389
assert .Equal (t , testResponse , w .Body .String ())
378
390
}
379
391
392
+ func TestMinLengthShortResponse (t * testing.T ) {
393
+ req , _ := http .NewRequestWithContext (context .Background (), "GET" , "/" , nil )
394
+ req .Header .Add (headerAcceptEncoding , "gzip" )
395
+
396
+ router := gin .New ()
397
+ router .Use (Gzip (DefaultCompression , WithMinLength (2048 )))
398
+ router .GET ("/" , func (c * gin.Context ) {
399
+ c .String (200 , testResponse )
400
+ })
401
+
402
+ w := httptest .NewRecorder ()
403
+ router .ServeHTTP (w , req )
404
+
405
+ assert .Equal (t , 200 , w .Code )
406
+ assert .Equal (t , "" , w .Header ().Get (headerContentEncoding ))
407
+ assert .Equal (t , "19" , w .Header ().Get ("Content-Length" ))
408
+ assert .Equal (t , testResponse , w .Body .String ())
409
+ }
410
+
411
+ func TestMinLengthLongResponse (t * testing.T ) {
412
+ req , _ := http .NewRequestWithContext (context .Background (), "GET" , "/" , nil )
413
+ req .Header .Add (headerAcceptEncoding , "gzip" )
414
+
415
+ router := gin .New ()
416
+ router .Use (Gzip (DefaultCompression , WithMinLength (2048 )))
417
+ router .GET ("/" , func (c * gin.Context ) {
418
+ c .String (200 , strings .Repeat ("a" , 2048 ))
419
+ })
420
+
421
+ w := httptest .NewRecorder ()
422
+ router .ServeHTTP (w , req )
423
+
424
+ assert .Equal (t , 200 , w .Code )
425
+ assert .Equal (t , "gzip" , w .Header ().Get (headerContentEncoding ))
426
+ assert .NotEqual (t , "2048" , w .Header ().Get ("Content-Length" ))
427
+ assert .Less (t , w .Body .Len (), 2048 )
428
+ }
429
+
430
+ func TestMinLengthMultiWriteResponse (t * testing.T ) {
431
+ req , _ := http .NewRequestWithContext (context .Background (), "GET" , "/" , nil )
432
+ req .Header .Add (headerAcceptEncoding , "gzip" )
433
+
434
+ router := gin .New ()
435
+ router .Use (Gzip (DefaultCompression , WithMinLength (2048 )))
436
+ router .GET ("/" , func (c * gin.Context ) {
437
+ c .String (200 , strings .Repeat ("a" , 1024 ))
438
+ c .String (200 , strings .Repeat ("b" , 1024 ))
439
+ })
440
+
441
+ w := httptest .NewRecorder ()
442
+ router .ServeHTTP (w , req )
443
+
444
+ assert .Equal (t , 200 , w .Code )
445
+ assert .Equal (t , "gzip" , w .Header ().Get (headerContentEncoding ))
446
+ assert .NotEqual (t , "2048" , w .Header ().Get ("Content-Length" ))
447
+ assert .Less (t , w .Body .Len (), 2048 )
448
+ }
449
+
450
+ // Note this test intentionally triggers gzipping even when the actual response doesn't meet min length. This is because
451
+ // we use the Content-Length header as the primary determinant of compression to avoid the cost of buffering.
452
+ func TestMinLengthUsesContentLengthHeaderInsteadOfBuffering (t * testing.T ) {
453
+ req , _ := http .NewRequestWithContext (context .Background (), "GET" , "/" , nil )
454
+ req .Header .Add (headerAcceptEncoding , "gzip" )
455
+
456
+ router := gin .New ()
457
+ router .Use (Gzip (DefaultCompression , WithMinLength (2048 )))
458
+ router .GET ("/" , func (c * gin.Context ) {
459
+ c .Header ("Content-Length" , "2048" )
460
+ c .String (200 , testResponse )
461
+ })
462
+
463
+ w := httptest .NewRecorder ()
464
+ router .ServeHTTP (w , req )
465
+
466
+ assert .Equal (t , 200 , w .Code )
467
+ assert .Equal (t , "gzip" , w .Header ().Get (headerContentEncoding ))
468
+ assert .NotEmpty (t , w .Header ().Get ("Content-Length" ))
469
+ assert .NotEqual (t , "19" , w .Header ().Get ("Content-Length" ))
470
+ }
471
+
472
+ // Note this test intentionally does not trigger gzipping even when the actual response meets min length. This is
473
+ // because we use the Content-Length header as the primary determinant of compression to avoid the cost of buffering.
474
+ func TestMinLengthMultiWriteResponseUsesContentLengthHeaderInsteadOfBuffering (t * testing.T ) {
475
+ req , _ := http .NewRequestWithContext (context .Background (), "GET" , "/" , nil )
476
+ req .Header .Add (headerAcceptEncoding , "gzip" )
477
+
478
+ router := gin .New ()
479
+ router .Use (Gzip (DefaultCompression , WithMinLength (1024 )))
480
+ router .GET ("/" , func (c * gin.Context ) {
481
+ c .Header ("Content-Length" , "999" )
482
+ c .String (200 , strings .Repeat ("a" , 1024 ))
483
+ c .String (200 , strings .Repeat ("b" , 1024 ))
484
+ })
485
+
486
+ w := httptest .NewRecorder ()
487
+ router .ServeHTTP (w , req )
488
+
489
+ assert .Equal (t , 200 , w .Code )
490
+ assert .NotEqual (t , "gzip" , w .Header ().Get (headerContentEncoding )) // no gzip due to Content-Length header
491
+ assert .Equal (t , "2048" , w .Header ().Get ("Content-Length" ))
492
+ }
493
+
494
+ func TestMinLengthWithInvalidContentLengthHeader (t * testing.T ) {
495
+ req , _ := http .NewRequestWithContext (context .Background (), "GET" , "/" , nil )
496
+ req .Header .Add (headerAcceptEncoding , "gzip" )
497
+
498
+ router := gin .New ()
499
+ router .Use (Gzip (DefaultCompression , WithMinLength (2048 )))
500
+ router .GET ("/" , func (c * gin.Context ) {
501
+ c .Header ("Content-Length" , "xyz" )
502
+ c .String (200 , testResponse )
503
+ })
504
+
505
+ w := httptest .NewRecorder ()
506
+ router .ServeHTTP (w , req )
507
+
508
+ assert .Equal (t , 200 , w .Code )
509
+ assert .Equal (t , "" , w .Header ().Get (headerContentEncoding ))
510
+ assert .Equal (t , "19" , w .Header ().Get ("Content-Length" ))
511
+ }
512
+
513
+ func TestFlush (t * testing.T ) {
514
+ testC , _ := gin .CreateTestContext (httptest .NewRecorder ())
515
+ gz := gzipWriter {
516
+ ResponseWriter : testC .Writer ,
517
+ writer : gzip .NewWriter (testC .Writer ),
518
+ }
519
+ _ , _ = gz .WriteString ("test" )
520
+ gz .Flush ()
521
+ assert .True (t , gz .Written ())
522
+ }
523
+
380
524
type hijackableResponse struct {
381
525
Hijacked bool
382
526
header http.Header
0 commit comments