@@ -9,6 +9,14 @@ use std::future::Future;
9
9
use std:: pin:: Pin ;
10
10
use std:: task:: { Context , Poll } ;
11
11
12
+ #[ cfg( any(
13
+ feature = "gzip" ,
14
+ feature = "zstd" ,
15
+ feature = "brotli" ,
16
+ feature = "deflate"
17
+ ) ) ]
18
+ use futures_util:: stream:: Fuse ;
19
+
12
20
#[ cfg( feature = "gzip" ) ]
13
21
use async_compression:: tokio:: bufread:: GzipDecoder ;
14
22
@@ -92,19 +100,19 @@ enum Inner {
92
100
93
101
/// A `Gzip` decoder will uncompress the gzipped response content before returning it.
94
102
#[ cfg( feature = "gzip" ) ]
95
- Gzip ( Pin < Box < FramedRead < GzipDecoder < PeekableIoStreamReader > , BytesCodec > > > ) ,
103
+ Gzip ( Pin < Box < Fuse < FramedRead < GzipDecoder < PeekableIoStreamReader > , BytesCodec > > > > ) ,
96
104
97
105
/// A `Brotli` decoder will uncompress the brotlied response content before returning it.
98
106
#[ cfg( feature = "brotli" ) ]
99
- Brotli ( Pin < Box < FramedRead < BrotliDecoder < PeekableIoStreamReader > , BytesCodec > > > ) ,
107
+ Brotli ( Pin < Box < Fuse < FramedRead < BrotliDecoder < PeekableIoStreamReader > , BytesCodec > > > > ) ,
100
108
101
109
/// A `Zstd` decoder will uncompress the zstd compressed response content before returning it.
102
110
#[ cfg( feature = "zstd" ) ]
103
- Zstd ( Pin < Box < FramedRead < ZstdDecoder < PeekableIoStreamReader > , BytesCodec > > > ) ,
111
+ Zstd ( Pin < Box < Fuse < FramedRead < ZstdDecoder < PeekableIoStreamReader > , BytesCodec > > > > ) ,
104
112
105
113
/// A `Deflate` decoder will uncompress the deflated response content before returning it.
106
114
#[ cfg( feature = "deflate" ) ]
107
- Deflate ( Pin < Box < FramedRead < ZlibDecoder < PeekableIoStreamReader > , BytesCodec > > > ) ,
115
+ Deflate ( Pin < Box < Fuse < FramedRead < ZlibDecoder < PeekableIoStreamReader > , BytesCodec > > > > ) ,
108
116
109
117
/// A decoder that doesn't have a value yet.
110
118
#[ cfg( any(
@@ -336,34 +344,58 @@ impl HttpBody for Decoder {
336
344
}
337
345
#[ cfg( feature = "gzip" ) ]
338
346
Inner :: Gzip ( ref mut decoder) => {
339
- match futures_core:: ready!( Pin :: new( decoder) . poll_next( cx) ) {
347
+ match futures_core:: ready!( Pin :: new( & mut * decoder) . poll_next( cx) ) {
340
348
Some ( Ok ( bytes) ) => Poll :: Ready ( Some ( Ok ( Frame :: data ( bytes. freeze ( ) ) ) ) ) ,
341
349
Some ( Err ( err) ) => Poll :: Ready ( Some ( Err ( crate :: error:: decode_io ( err) ) ) ) ,
342
- None => Poll :: Ready ( None ) ,
350
+ None => {
351
+ // poll inner connection until EOF after gzip stream is finished
352
+ poll_inner_should_be_empty (
353
+ decoder. get_mut ( ) . get_mut ( ) . get_mut ( ) . get_mut ( ) ,
354
+ cx,
355
+ )
356
+ }
343
357
}
344
358
}
345
359
#[ cfg( feature = "brotli" ) ]
346
360
Inner :: Brotli ( ref mut decoder) => {
347
- match futures_core:: ready!( Pin :: new( decoder) . poll_next( cx) ) {
361
+ match futures_core:: ready!( Pin :: new( & mut * decoder) . poll_next( cx) ) {
348
362
Some ( Ok ( bytes) ) => Poll :: Ready ( Some ( Ok ( Frame :: data ( bytes. freeze ( ) ) ) ) ) ,
349
363
Some ( Err ( err) ) => Poll :: Ready ( Some ( Err ( crate :: error:: decode_io ( err) ) ) ) ,
350
- None => Poll :: Ready ( None ) ,
364
+ None => {
365
+ // poll inner connection until EOF after brotli stream is finished
366
+ poll_inner_should_be_empty (
367
+ decoder. get_mut ( ) . get_mut ( ) . get_mut ( ) . get_mut ( ) ,
368
+ cx,
369
+ )
370
+ }
351
371
}
352
372
}
353
373
#[ cfg( feature = "zstd" ) ]
354
374
Inner :: Zstd ( ref mut decoder) => {
355
- match futures_core:: ready!( Pin :: new( decoder) . poll_next( cx) ) {
375
+ match futures_core:: ready!( Pin :: new( & mut * decoder) . poll_next( cx) ) {
356
376
Some ( Ok ( bytes) ) => Poll :: Ready ( Some ( Ok ( Frame :: data ( bytes. freeze ( ) ) ) ) ) ,
357
377
Some ( Err ( err) ) => Poll :: Ready ( Some ( Err ( crate :: error:: decode_io ( err) ) ) ) ,
358
- None => Poll :: Ready ( None ) ,
378
+ None => {
379
+ // poll inner connection until EOF after zstd stream is finished
380
+ poll_inner_should_be_empty (
381
+ decoder. get_mut ( ) . get_mut ( ) . get_mut ( ) . get_mut ( ) ,
382
+ cx,
383
+ )
384
+ }
359
385
}
360
386
}
361
387
#[ cfg( feature = "deflate" ) ]
362
388
Inner :: Deflate ( ref mut decoder) => {
363
- match futures_core:: ready!( Pin :: new( decoder) . poll_next( cx) ) {
389
+ match futures_core:: ready!( Pin :: new( & mut * decoder) . poll_next( cx) ) {
364
390
Some ( Ok ( bytes) ) => Poll :: Ready ( Some ( Ok ( Frame :: data ( bytes. freeze ( ) ) ) ) ) ,
365
391
Some ( Err ( err) ) => Poll :: Ready ( Some ( Err ( crate :: error:: decode_io ( err) ) ) ) ,
366
- None => Poll :: Ready ( None ) ,
392
+ None => {
393
+ // poll inner connection until EOF after deflate stream is finished
394
+ poll_inner_should_be_empty (
395
+ decoder. get_mut ( ) . get_mut ( ) . get_mut ( ) . get_mut ( ) ,
396
+ cx,
397
+ )
398
+ }
367
399
}
368
400
}
369
401
}
@@ -384,6 +416,34 @@ impl HttpBody for Decoder {
384
416
}
385
417
}
386
418
419
+ #[ cfg( any(
420
+ feature = "gzip" ,
421
+ feature = "zstd" ,
422
+ feature = "brotli" ,
423
+ feature = "deflate"
424
+ ) ) ]
425
+ fn poll_inner_should_be_empty (
426
+ inner : & mut PeekableIoStream ,
427
+ cx : & mut Context ,
428
+ ) -> Poll < Option < Result < Frame < Bytes > , crate :: Error > > > {
429
+ // poll inner connection until EOF after deflate stream is finished
430
+ // loop in case of empty frames
431
+ let mut inner = Pin :: new ( inner) ;
432
+ loop {
433
+ match futures_core:: ready!( inner. as_mut( ) . poll_next( cx) ) {
434
+ // ignore any empty frames
435
+ Some ( Ok ( bytes) ) if bytes. is_empty ( ) => continue ,
436
+ Some ( Ok ( _) ) => {
437
+ return Poll :: Ready ( Some ( Err ( crate :: error:: decode (
438
+ "there are extra bytes after body has been decompressed" ,
439
+ ) ) ) )
440
+ }
441
+ Some ( Err ( err) ) => return Poll :: Ready ( Some ( Err ( crate :: error:: decode_io ( err) ) ) ) ,
442
+ None => return Poll :: Ready ( None ) ,
443
+ }
444
+ }
445
+ }
446
+
387
447
#[ cfg( any(
388
448
feature = "gzip" ,
389
449
feature = "zstd" ,
@@ -426,25 +486,37 @@ impl Future for Pending {
426
486
427
487
match self . 1 {
428
488
#[ cfg( feature = "brotli" ) ]
429
- DecoderType :: Brotli => Poll :: Ready ( Ok ( Inner :: Brotli ( Box :: pin ( FramedRead :: new (
430
- BrotliDecoder :: new ( StreamReader :: new ( _body) ) ,
431
- BytesCodec :: new ( ) ,
432
- ) ) ) ) ) ,
489
+ DecoderType :: Brotli => Poll :: Ready ( Ok ( Inner :: Brotli ( Box :: pin (
490
+ FramedRead :: new (
491
+ BrotliDecoder :: new ( StreamReader :: new ( _body) ) ,
492
+ BytesCodec :: new ( ) ,
493
+ )
494
+ . fuse ( ) ,
495
+ ) ) ) ) ,
433
496
#[ cfg( feature = "zstd" ) ]
434
- DecoderType :: Zstd => Poll :: Ready ( Ok ( Inner :: Zstd ( Box :: pin ( FramedRead :: new (
435
- ZstdDecoder :: new ( StreamReader :: new ( _body) ) ,
436
- BytesCodec :: new ( ) ,
437
- ) ) ) ) ) ,
497
+ DecoderType :: Zstd => Poll :: Ready ( Ok ( Inner :: Zstd ( Box :: pin (
498
+ FramedRead :: new (
499
+ ZstdDecoder :: new ( StreamReader :: new ( _body) ) ,
500
+ BytesCodec :: new ( ) ,
501
+ )
502
+ . fuse ( ) ,
503
+ ) ) ) ) ,
438
504
#[ cfg( feature = "gzip" ) ]
439
- DecoderType :: Gzip => Poll :: Ready ( Ok ( Inner :: Gzip ( Box :: pin ( FramedRead :: new (
440
- GzipDecoder :: new ( StreamReader :: new ( _body) ) ,
441
- BytesCodec :: new ( ) ,
442
- ) ) ) ) ) ,
505
+ DecoderType :: Gzip => Poll :: Ready ( Ok ( Inner :: Gzip ( Box :: pin (
506
+ FramedRead :: new (
507
+ GzipDecoder :: new ( StreamReader :: new ( _body) ) ,
508
+ BytesCodec :: new ( ) ,
509
+ )
510
+ . fuse ( ) ,
511
+ ) ) ) ) ,
443
512
#[ cfg( feature = "deflate" ) ]
444
- DecoderType :: Deflate => Poll :: Ready ( Ok ( Inner :: Deflate ( Box :: pin ( FramedRead :: new (
445
- ZlibDecoder :: new ( StreamReader :: new ( _body) ) ,
446
- BytesCodec :: new ( ) ,
447
- ) ) ) ) ) ,
513
+ DecoderType :: Deflate => Poll :: Ready ( Ok ( Inner :: Deflate ( Box :: pin (
514
+ FramedRead :: new (
515
+ ZlibDecoder :: new ( StreamReader :: new ( _body) ) ,
516
+ BytesCodec :: new ( ) ,
517
+ )
518
+ . fuse ( ) ,
519
+ ) ) ) ) ,
448
520
}
449
521
}
450
522
}
0 commit comments