@@ -351,20 +351,17 @@ mod parse_response {
351351 ErrorType :: { self , * } ,
352352 } ;
353353
354- pub const INVALID_CHUNK : ErrorType = ErrorType :: new ( "InvalidChunk" ) ;
355354 pub const INCOMPLETE_BODY : ErrorType = ErrorType :: new ( "IncompleteHttpBody" ) ;
356355
357356 const MAX_HEADERS : usize = 256 ;
358357 const INIT_HEADER_BUF_SIZE : usize = 4096 ;
359- const CHUNK_DELIMITER_SIZE : usize = 2 ; // \r\n
360358
361359 #[ derive( Debug , Clone , Copy , PartialEq ) ]
362360 enum ParseState {
363361 Init ,
364362 PartialHeader ,
365363 PartialBodyContentLength ( usize , usize ) ,
366- PartialChunkedBody ( usize ) ,
367- PartialHttp10Body ( usize ) ,
364+ PartialBody ( usize ) ,
368365 Done ( usize ) ,
369366 Invalid ( httparse:: Error ) ,
370367 }
@@ -379,9 +376,7 @@ mod parse_response {
379376 fn read_body ( & self ) -> bool {
380377 matches ! (
381378 self ,
382- Self :: PartialBodyContentLength ( ..)
383- | Self :: PartialChunkedBody ( _)
384- | Self :: PartialHttp10Body ( _)
379+ Self :: PartialBodyContentLength ( ..) | Self :: PartialBody ( _)
385380 )
386381 }
387382 }
@@ -509,49 +504,15 @@ mod parse_response {
509504 }
510505 Ok ( Some ( self . buf . split_to ( end) . freeze ( ) ) )
511506 }
512- PartialChunkedBody ( seen) => {
513- let parsed = httparse:: parse_chunk_size ( & self . buf ) . map_err ( |e| {
514- self . state = Done ( seen) ;
515- Error :: explain ( INVALID_CHUNK , format ! ( "Invalid chunked encoding: {e:?}" ) )
516- } ) ?;
517- match parsed {
518- httparse:: Status :: Complete ( ( header_len, body_len) ) => {
519- // 4\r\nRust\r\n: header: "4\r\n", body: "Rust", "\r\n"
520- let total_chunk_size =
521- header_len + body_len as usize + CHUNK_DELIMITER_SIZE ;
522- if self . buf . len ( ) < total_chunk_size {
523- // wait for the full chunk to be read
524- // Note that we have to buffer the entire chunk in this design
525- Ok ( None )
526- } else {
527- if body_len == 0 {
528- self . state = Done ( seen) ;
529- } else {
530- self . state = PartialChunkedBody ( seen + body_len as usize ) ;
531- }
532- let mut chunk_bytes = self . buf . split_to ( total_chunk_size) ;
533- let mut chunk_body = chunk_bytes. split_off ( header_len) ;
534- chunk_body. truncate ( body_len as usize ) ;
535- // Note that the final 0 sized chunk will return an empty Bytes
536- // instead of not None
537- Ok ( Some ( chunk_body. freeze ( ) ) )
538- }
539- }
540- httparse:: Status :: Partial => {
541- // not even a full chunk, continue waiting for more data
542- Ok ( None )
543- }
544- }
545- }
546- PartialHttp10Body ( seen) => {
547- self . state = PartialHttp10Body ( seen + self . buf . len ( ) ) ;
507+ PartialBody ( seen) => {
508+ self . state = PartialBody ( seen + self . buf . len ( ) ) ;
548509 Ok ( Some ( self . buf . split ( ) . freeze ( ) ) )
549510 }
550511 }
551512 }
552513
553514 pub fn finish ( & mut self ) -> Result < ( ) > {
554- if let ParseState :: PartialHttp10Body ( seen) = self . state {
515+ if let ParseState :: PartialBody ( seen) = self . state {
555516 self . state = ParseState :: Done ( seen) ;
556517 }
557518 if !self . state . is_done ( ) {
@@ -572,12 +533,6 @@ mod parse_response {
572533 // these status codes cannot have body by definition
573534 return ParseState :: Done ( 0 ) ;
574535 }
575- if let Some ( encoding) = resp. headers . get ( http:: header:: TRANSFER_ENCODING ) {
576- // TODO: case sensitive?
577- if encoding. as_bytes ( ) == b"chunked" {
578- return ParseState :: PartialChunkedBody ( 0 ) ;
579- }
580- }
581536 if let Some ( cl) = resp. headers . get ( http:: header:: CONTENT_LENGTH ) {
582537 // ignore invalid header value
583538 if let Some ( cl) = std:: str:: from_utf8 ( cl. as_bytes ( ) )
@@ -591,7 +546,10 @@ mod parse_response {
591546 } ;
592547 }
593548 }
594- ParseState :: PartialHttp10Body ( 0 )
549+ // HTTP/1.0 and chunked encoding are both treated as PartialBody
550+ // The response body payload should _not_ be chunked encoded
551+ // even if the Transfer-Encoding: chunked header is added
552+ ParseState :: PartialBody ( 0 )
595553 }
596554
597555 #[ cfg( test) ]
@@ -684,7 +642,7 @@ mod parse_response {
684642
685643 #[ test]
686644 fn test_body_chunked ( ) {
687- let input = b"HTTP/1.1 200 OK\r \n Transfer-Encoding: chunked\r \n \r \n 4 \r \ n rust\r \n " ;
645+ let input = b"HTTP/1.1 200 OK\r \n Transfer-Encoding: chunked\r \n \r \n rust" ;
688646 let mut parser = ResponseParse :: new ( ) ;
689647 let output = parser. inject_data ( input) . unwrap ( ) ;
690648
@@ -700,14 +658,6 @@ mod parse_response {
700658 assert_eq ! ( data. as_ref( ) . unwrap( ) , "rust" ) ;
701659 assert ! ( !eos) ;
702660
703- let output = parser. inject_data ( b"0\r \n \r \n " ) . unwrap ( ) ;
704- assert_eq ! ( output. len( ) , 1 ) ;
705- let HttpTask :: Body ( data, eos) = & output[ 0 ] else {
706- panic ! ( "{:?}" , output) ;
707- } ;
708- assert_eq ! ( data. as_ref( ) . unwrap( ) , "" ) ;
709- assert ! ( eos) ;
710-
711661 parser. finish ( ) . unwrap ( ) ;
712662 }
713663
@@ -755,8 +705,8 @@ mod parse_response {
755705 }
756706
757707 #[ test]
758- fn test_body_chunked_early ( ) {
759- let input = b"HTTP/1.1 200 OK\r \n Transfer-Encoding: chunked\r \n \r \n 4 \r \n rust \r \n " ;
708+ fn test_body_chunked_partial_chunk ( ) {
709+ let input = b"HTTP/1.1 200 OK\r \n Transfer-Encoding: chunked\r \n \r \n ru " ;
760710 let mut parser = ResponseParse :: new ( ) ;
761711 let output = parser. inject_data ( input) . unwrap ( ) ;
762712
@@ -769,75 +719,15 @@ mod parse_response {
769719 let HttpTask :: Body ( data, eos) = & output[ 1 ] else {
770720 panic ! ( "{:?}" , output) ;
771721 } ;
772- assert_eq ! ( data. as_ref( ) . unwrap( ) , "rust " ) ;
722+ assert_eq ! ( data. as_ref( ) . unwrap( ) , "ru " ) ;
773723 assert ! ( !eos) ;
774724
775- parser. finish ( ) . unwrap_err ( ) ;
776- }
777-
778- #[ test]
779- fn test_body_chunked_partial_chunk ( ) {
780- let input = b"HTTP/1.1 200 OK\r \n Transfer-Encoding: chunked\r \n \r \n 4\r \n ru" ;
781- let mut parser = ResponseParse :: new ( ) ;
782- let output = parser. inject_data ( input) . unwrap ( ) ;
783-
784- assert_eq ! ( output. len( ) , 1 ) ;
785- let HttpTask :: Header ( header, _eos) = & output[ 0 ] else {
786- panic ! ( "{:?}" , output) ;
787- } ;
788- assert_eq ! ( header. status, 200 ) ;
789-
790725 let output = parser. inject_data ( b"st\r \n " ) . unwrap ( ) ;
791726 assert_eq ! ( output. len( ) , 1 ) ;
792727 let HttpTask :: Body ( data, eos) = & output[ 0 ] else {
793728 panic ! ( "{:?}" , output) ;
794729 } ;
795- assert_eq ! ( data. as_ref( ) . unwrap( ) , "rust" ) ;
796- assert ! ( !eos) ;
797- }
798-
799- #[ test]
800- fn test_body_chunked_partial_chunk_head ( ) {
801- let input = b"HTTP/1.1 200 OK\r \n Transfer-Encoding: chunked\r \n \r \n 4\r " ;
802- let mut parser = ResponseParse :: new ( ) ;
803- let output = parser. inject_data ( input) . unwrap ( ) ;
804-
805- assert_eq ! ( output. len( ) , 1 ) ;
806- let HttpTask :: Header ( header, _eos) = & output[ 0 ] else {
807- panic ! ( "{:?}" , output) ;
808- } ;
809- assert_eq ! ( header. status, 200 ) ;
810-
811- let output = parser. inject_data ( b"\n rust\r \n " ) . unwrap ( ) ;
812- assert_eq ! ( output. len( ) , 1 ) ;
813- let HttpTask :: Body ( data, eos) = & output[ 0 ] else {
814- panic ! ( "{:?}" , output) ;
815- } ;
816- assert_eq ! ( data. as_ref( ) . unwrap( ) , "rust" ) ;
817- assert ! ( !eos) ;
818- }
819-
820- #[ test]
821- fn test_body_chunked_many_chunks ( ) {
822- let input =
823- b"HTTP/1.1 200 OK\r \n Transfer-Encoding: chunked\r \n \r \n 4\r \n rust\r \n 1\r \n y\r \n " ;
824- let mut parser = ResponseParse :: new ( ) ;
825- let output = parser. inject_data ( input) . unwrap ( ) ;
826-
827- assert_eq ! ( output. len( ) , 3 ) ;
828- let HttpTask :: Header ( header, _eos) = & output[ 0 ] else {
829- panic ! ( "{:?}" , output) ;
830- } ;
831- assert_eq ! ( header. status, 200 ) ;
832- let HttpTask :: Body ( data, eos) = & output[ 1 ] else {
833- panic ! ( "{:?}" , output) ;
834- } ;
835- assert ! ( !eos) ;
836- assert_eq ! ( data. as_ref( ) . unwrap( ) , "rust" ) ;
837- let HttpTask :: Body ( data, eos) = & output[ 2 ] else {
838- panic ! ( "{:?}" , output) ;
839- } ;
840- assert_eq ! ( data. as_ref( ) . unwrap( ) , "y" ) ;
730+ assert_eq ! ( data. as_ref( ) . unwrap( ) , "st\r \n " ) ;
841731 assert ! ( !eos) ;
842732 }
843733
@@ -928,25 +818,5 @@ mod parse_response {
928818 assert ! ( output. is_empty( ) ) ;
929819 parser. finish ( ) . unwrap ( ) ;
930820 }
931-
932- #[ test]
933- fn test_no_body_chunked ( ) {
934- let input = b"HTTP/1.1 200 OK\r \n Transfer-Encoding: chunked\r \n \r \n 0\r \n \r \n " ;
935- let mut parser = ResponseParse :: new ( ) ;
936- let output = parser. inject_data ( input) . unwrap ( ) ;
937-
938- assert_eq ! ( output. len( ) , 2 ) ;
939- let HttpTask :: Header ( header, _eos) = & output[ 0 ] else {
940- panic ! ( "{:?}" , output) ;
941- } ;
942- assert_eq ! ( header. status, 200 ) ;
943-
944- let HttpTask :: Body ( data, eos) = & output[ 1 ] else {
945- panic ! ( "{:?}" , output) ;
946- } ;
947- assert_eq ! ( data. as_ref( ) . unwrap( ) , "" ) ;
948- assert ! ( eos) ;
949- parser. finish ( ) . unwrap ( ) ;
950- }
951821 }
952822}
0 commit comments