11use mime_plz:: ContentType ;
22
3- use super :: {
4- BodyHeader ,
5- content_encoding:: ContentEncoding ,
6- transfer_types:: { TransferType , cl_to_transfer_type, parse_and_remove_chunked} ,
7- } ;
3+ use super :: { BodyHeader , content_encoding:: ContentEncoding , transfer_types:: TransferType } ;
84use crate :: {
5+ body_headers:: encoding_info:: EncodingInfo ,
96 const_headers:: * ,
107 header_map:: { HeaderMap , header:: Header } ,
118} ;
@@ -38,12 +35,21 @@ use crate::{
3835 */
3936
4037impl From < & HeaderMap > for Option < BodyHeader > {
41- fn from ( header_map : & HeaderMap ) -> Option < BodyHeader > {
38+ fn from ( header_map : & HeaderMap ) -> Self {
39+ let bh = BodyHeader :: from ( header_map) ;
40+ bh. sanitize ( )
41+ }
42+ }
43+
44+ impl From < & HeaderMap > for BodyHeader {
45+ #[ inline( always) ]
46+ fn from ( header_map : & HeaderMap ) -> BodyHeader {
4247 let mut bh = BodyHeader :: default ( ) ;
4348 header_map
4449 . headers ( )
4550 . iter ( )
46- . for_each ( |header| parse_body_headers ( & mut bh, header) ) ;
51+ . enumerate ( )
52+ . for_each ( |( index, header) | parse_body_headers ( & mut bh, index, header) ) ;
4753
4854 // if TransferType is Unknown, and if content_encoding or transfer_encoding
4955 // or content_type is present, then set TransferType to Close
@@ -54,68 +60,50 @@ impl From<&HeaderMap> for Option<BodyHeader> {
5460 {
5561 bh. transfer_type = Some ( TransferType :: Close ) ;
5662 }
57- bh. sanitize ( )
63+ bh
5864 }
5965}
6066
61- pub fn parse_body_headers ( bh : & mut BodyHeader , header : & Header ) {
67+ pub fn parse_body_headers ( bh : & mut BodyHeader , index : usize , header : & Header ) {
6268 let key = header. key_as_str ( ) ;
6369 if ( key. eq_ignore_ascii_case ( CONTENT_LENGTH ) ) && bh. transfer_type . is_none ( ) {
64- let transfer_type = cl_to_transfer_type ( header. value_as_str ( ) ) ;
65- bh . transfer_type = Some ( transfer_type) ;
70+ let transfer_type = TransferType :: from_cl ( header. value_as_str ( ) ) ;
71+ let _ = bh . transfer_type . get_or_insert ( transfer_type) ;
6672 } else if key. eq_ignore_ascii_case ( TRANSFER_ENCODING ) {
67- bh. transfer_encoding = match_compression ( header. value_as_str ( ) ) ;
68- bh. transfer_type = parse_and_remove_chunked ( & mut bh. transfer_encoding ) ;
73+ let mut einfo_iter = EncodingInfo :: iter_from_str ( index, header. value_as_str ( ) ) ;
74+ bh. transfer_encoding
75+ . get_or_insert_with ( Vec :: new)
76+ . extend ( einfo_iter) ;
77+ if bh. is_chunked_te ( ) {
78+ bh. transfer_type = Some ( TransferType :: Chunked )
79+ }
6980 } else if key. eq_ignore_ascii_case ( CONTENT_ENCODING ) {
70- bh. content_encoding = match_compression ( header. value_as_str ( ) ) ;
81+ let einfo_iter = EncodingInfo :: iter_from_str ( index, header. value_as_str ( ) ) ;
82+ bh. content_encoding
83+ . get_or_insert_with ( Vec :: new)
84+ . extend ( einfo_iter) ;
7185 } else if key. eq_ignore_ascii_case ( CONTENT_TYPE ) {
7286 if let Some ( ( main_type, _) ) = header. value_as_str ( ) . split_once ( '/' ) {
7387 bh. content_type = Some ( ContentType :: from ( main_type) ) ;
7488 }
7589 }
7690}
7791
78- // Convert compression header values to Vec<ContentEncoding>.
79- pub fn match_compression ( value : & str ) -> Option < Vec < ContentEncoding > > {
80- let encoding: Vec < ContentEncoding > = value
81- . split ( ',' )
82- . map ( |x| x. trim ( ) )
83- . filter_map ( |x| {
84- if x. is_empty ( ) {
85- None
86- } else {
87- Some ( ContentEncoding :: from ( x) )
88- }
89- } )
90- . collect ( ) ;
91- Some ( encoding)
92- }
93-
9492#[ cfg( test) ]
9593mod tests {
96- use bytes:: BytesMut ;
97-
9894 use super :: * ;
95+ use bytes:: BytesMut ;
9996
100- #[ test]
101- fn test_match_compression ( ) {
102- let data = "gzip, deflate, br, compress," ;
103- let result = match_compression ( data) ;
104- let verify = vec ! [
105- ContentEncoding :: Gzip ,
106- ContentEncoding :: Deflate ,
107- ContentEncoding :: Brotli ,
108- ContentEncoding :: Compress ,
109- ] ;
110- assert_eq ! ( result, Some ( verify) ) ;
97+ fn build_body_header ( input : & str ) -> BodyHeader {
98+ let header_map = HeaderMap :: from ( BytesMut :: from ( input) ) ;
99+ BodyHeader :: from ( & header_map)
111100 }
112101
102+ // ---- Content Length
113103 #[ test]
114- fn test_header_map_to_body_headers_cl_only ( ) {
115- let data = "Content-Length: 10\r \n \r \n " ;
116- let buf = BytesMut :: from ( data) ;
117- let header_map = HeaderMap :: from ( buf) ;
118- let result = Option :: < BodyHeader > :: from ( & header_map) . unwrap ( ) ;
104+ fn test_body_header_from_header_map_cl ( ) {
105+ let input = "Content-Length: 10\r \n \r \n " ;
106+ let result = build_body_header ( input) ;
119107 let verify = BodyHeader {
120108 transfer_type : Some ( TransferType :: ContentLength ( 10 ) ) ,
121109 ..Default :: default ( )
@@ -124,69 +112,68 @@ mod tests {
124112 }
125113
126114 #[ test]
127- fn test_header_map_to_body_headers_cl_invalid ( ) {
128- let data = "Content-Length: invalid\r \n \r \n " ;
129- let buf = BytesMut :: from ( data) ;
130- let header_map = HeaderMap :: from ( buf) ;
115+ fn test_body_header_from_header_map_cl_invalid ( ) {
116+ let input = "Content-Length: invalid\r \n \r \n " ;
117+ let result = build_body_header ( input) ;
131118 let verify = BodyHeader {
132119 transfer_type : Some ( TransferType :: Close ) ,
133120 ..Default :: default ( )
134121 } ;
135- let result = Option :: < BodyHeader > :: from ( & header_map) . unwrap ( ) ;
136122 assert_eq ! ( result, verify) ;
137123 }
138124
125+ // ----- chunked
139126 #[ test]
140- fn test_header_map_to_body_headers_te_chunked ( ) {
141- let data = "Transfer-Encoding: chunked\r \n \r \n " ;
142- let buf = BytesMut :: from ( data ) ;
143- let header_map = HeaderMap :: from ( buf ) ;
127+ fn test_body_header_from_header_map_chunked ( ) {
128+ let input = "Transfer-Encoding: chunked\r \n \r \n " ;
129+ let result = build_body_header ( input ) ;
130+ let einfo = EncodingInfo :: new ( 0 , ContentEncoding :: Chunked ) ;
144131 let verify = BodyHeader {
132+ transfer_encoding : Some ( vec ! [ einfo] ) ,
145133 transfer_type : Some ( TransferType :: Chunked ) ,
146134 ..Default :: default ( )
147135 } ;
148- let result = Option :: < BodyHeader > :: from ( & header_map) . unwrap ( ) ;
149136 assert_eq ! ( result, verify) ;
150137 }
151138
139+ // ----- chunked + cl
152140 #[ test]
153- fn test_header_map_to_body_headers_content_length_and_chunked ( ) {
154- let data = "Content-Length: 20\r \n Transfer-Encoding: chunked\r \n \r \n " ;
155- let buf = BytesMut :: from ( data ) ;
156- let header_map = HeaderMap :: from ( buf ) ;
141+ fn test_body_header_from_header_map_cl_and_chunked ( ) {
142+ let input = "Content-Length: 20\r \n Transfer-Encoding: chunked\r \n \r \n " ;
143+ let result = build_body_header ( input ) ;
144+ let einfo = EncodingInfo :: new ( 1 , ContentEncoding :: Chunked ) ;
157145 let verify = BodyHeader {
158146 transfer_type : Some ( TransferType :: Chunked ) ,
147+ transfer_encoding : Some ( vec ! [ einfo] ) ,
159148 ..Default :: default ( )
160149 } ;
161- let result = Option :: < BodyHeader > :: from ( & header_map) . unwrap ( ) ;
162150 assert_eq ! ( result, verify) ;
163151 }
164152
153+ // ----- Content type
165154 #[ test]
166- fn test_header_map_to_body_headers_ct_only ( ) {
167- let data = "Content-Type: application/json\r \n \r \n " ;
168- let buf = BytesMut :: from ( data) ;
169- let header_map = HeaderMap :: from ( buf) ;
155+ fn test_body_header_from_header_map_ct_only ( ) {
156+ let input = "Content-Type: application/json\r \n \r \n " ;
157+ let result = build_body_header ( input) ;
170158 let verify = BodyHeader {
171159 content_type : Some ( ContentType :: Application ) ,
172160 transfer_type : Some ( TransferType :: Close ) ,
173161 ..Default :: default ( )
174162 } ;
175- let result = Option :: < BodyHeader > :: from ( & header_map) . unwrap ( ) ;
176163 assert_eq ! ( result, verify) ;
177164 }
178165
166+ // ----- Content Encoding
179167 #[ test]
180- fn test_header_map_to_body_headers_ce_only ( ) {
181- let data = "Content-Encoding: gzip\r \n \r \n " ;
182- let buf = BytesMut :: from ( data ) ;
183- let header_map = HeaderMap :: from ( buf ) ;
168+ fn test_body_headers_from_header_map_ce_only ( ) {
169+ let input = "Content-Encoding: gzip\r \n \r \n " ;
170+ let result = build_body_header ( input ) ;
171+ let einfo = EncodingInfo :: new ( 0 , ContentEncoding :: Gzip ) ;
184172 let verify = BodyHeader {
185- content_encoding : Some ( vec ! [ ContentEncoding :: Gzip ] ) ,
173+ content_encoding : Some ( vec ! [ einfo ] ) ,
186174 transfer_type : Some ( TransferType :: Close ) ,
187175 ..Default :: default ( )
188176 } ;
189- let result = Option :: < BodyHeader > :: from ( & header_map) . unwrap ( ) ;
190177 assert_eq ! ( result, verify) ;
191178 }
192179}
0 commit comments