@@ -28,17 +28,75 @@ pub struct Request {
2828 body : Vec < u8 > ,
2929}
3030
31- enum HeaderValue {
31+ /// A header value.
32+ ///
33+ /// Since header values do not have to be valid utf8, this allows for
34+ /// both utf8 strings and bags of bytes.
35+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
36+ pub struct HeaderValue {
37+ inner : HeaderValueRep ,
38+ }
39+
40+ #[ derive( Debug , PartialEq , Eq , Clone ) ]
41+ enum HeaderValueRep {
42+ /// Header value encoded as a utf8 string
3243 String ( String ) ,
44+ /// Header value as a bag of bytes
3345 Bytes ( Vec < u8 > ) ,
3446}
3547
3648impl HeaderValue {
49+ /// Construct a `HeaderValue` from a string
50+ pub fn string ( str : String ) -> HeaderValue {
51+ HeaderValue {
52+ inner : HeaderValueRep :: String ( str) ,
53+ }
54+ }
55+
56+ /// Construct a `HeaderValue` from a bag of bytes
57+ pub fn bytes ( bytes : Vec < u8 > ) -> HeaderValue {
58+ HeaderValue {
59+ inner : HeaderValueRep :: Bytes ( bytes) ,
60+ }
61+ }
62+
63+ /// Get the `HeaderValue` as a utf8 encoded string
64+ ///
65+ /// Returns `None` if the value is a non utf8 encoded header value
66+ pub fn as_str ( & self ) -> Option < & str > {
67+ match & self . inner {
68+ HeaderValueRep :: String ( s) => Some ( s) ,
69+ HeaderValueRep :: Bytes ( _) => None ,
70+ }
71+ }
72+
73+ /// Get the `HeaderValue` as bytes
74+ pub fn as_bytes ( & self ) -> & [ u8 ] {
75+ self . as_ref ( )
76+ }
77+
78+ /// Turn the `HeaderValue` into a String (in a lossy way if the `HeaderValue` is a bag of bytes)
79+ pub fn into_utf8_lossy ( self ) -> String {
80+ match self . inner {
81+ HeaderValueRep :: String ( s) => s,
82+ HeaderValueRep :: Bytes ( b) => String :: from_utf8_lossy ( & b) . into_owned ( ) ,
83+ }
84+ }
85+
3786 /// Turn the `HeaderValue` into bytes
38- fn into_bytes ( self ) -> Vec < u8 > {
39- match self {
40- HeaderValue :: String ( s) => s. into_bytes ( ) ,
41- HeaderValue :: Bytes ( b) => b,
87+ pub fn into_bytes ( self ) -> Vec < u8 > {
88+ match self . inner {
89+ HeaderValueRep :: String ( s) => s. into_bytes ( ) ,
90+ HeaderValueRep :: Bytes ( b) => b,
91+ }
92+ }
93+ }
94+
95+ impl AsRef < [ u8 ] > for HeaderValue {
96+ fn as_ref ( & self ) -> & [ u8 ] {
97+ match & self . inner {
98+ HeaderValueRep :: String ( s) => s. as_bytes ( ) ,
99+ HeaderValueRep :: Bytes ( b) => b,
42100 }
43101 }
44102}
@@ -78,33 +136,15 @@ impl Request {
78136 }
79137
80138 /// The request headers
81- ///
82- /// This only returns headers that are utf8 encoded
83- pub fn headers ( & self ) -> impl Iterator < Item = ( & str , & str ) > {
84- self . headers . iter ( ) . filter_map ( |( k, v) | match v {
85- HeaderValue :: String ( v) => Some ( ( k. as_str ( ) , v. as_str ( ) ) ) ,
86- HeaderValue :: Bytes ( _) => None ,
87- } )
139+ pub fn headers ( & self ) -> impl Iterator < Item = ( & str , & HeaderValue ) > {
140+ self . headers . iter ( ) . map ( |( k, v) | ( k. as_str ( ) , v) )
88141 }
89142
90143 /// Return a header value
91144 ///
92- /// Will return `None` if the header does not exist or if it is not utf8
93- pub fn header ( & self , name : & str ) -> Option < & str > {
94- self . headers
95- . get ( & name. to_lowercase ( ) )
96- . and_then ( |v| match v {
97- HeaderValue :: String ( s) => Some ( s. as_str ( ) ) ,
98- HeaderValue :: Bytes ( _) => None ,
99- } )
100- }
101-
102- /// The request headers as bytes
103- pub fn headers_raw ( & self ) -> impl Iterator < Item = ( & str , & [ u8 ] ) > {
104- self . headers . iter ( ) . map ( |( k, v) | match v {
105- HeaderValue :: String ( v) => ( k. as_str ( ) , v. as_bytes ( ) ) ,
106- HeaderValue :: Bytes ( v) => ( k. as_str ( ) , v. as_slice ( ) ) ,
107- } )
145+ /// Will return `None` if the header does not exist.
146+ pub fn header ( & self , name : & str ) -> Option < & HeaderValue > {
147+ self . headers . get ( & name. to_lowercase ( ) )
108148 }
109149
110150 /// The request body
@@ -172,7 +212,7 @@ impl RequestBuilder {
172212 pub fn header ( & mut self , key : impl Into < String > , value : impl Into < String > ) -> & mut Self {
173213 self . request
174214 . headers
175- . insert ( key. into ( ) . to_lowercase ( ) , HeaderValue :: String ( value. into ( ) ) ) ;
215+ . insert ( key. into ( ) . to_lowercase ( ) , HeaderValue :: string ( value. into ( ) ) ) ;
176216 self
177217 }
178218
@@ -216,32 +256,16 @@ impl Response {
216256 & self . status
217257 }
218258
219- /// The response headers
220- ///
221- /// This only returns headers that are utf8 encoded
222- pub fn headers ( & self ) -> impl Iterator < Item = ( & str , & str ) > {
223- self . headers . iter ( ) . filter_map ( |( k, v) | match v {
224- HeaderValue :: String ( v) => Some ( ( k. as_str ( ) , v. as_str ( ) ) ) ,
225- HeaderValue :: Bytes ( _) => None ,
226- } )
259+ /// The request headers
260+ pub fn headers ( & self ) -> impl Iterator < Item = ( & str , & HeaderValue ) > {
261+ self . headers . iter ( ) . map ( |( k, v) | ( k. as_str ( ) , v) )
227262 }
228263
229264 /// Return a header value
230265 ///
231- /// Will return `None` if the header does not exist or if it is not utf8
232- pub fn header ( & self , name : & str ) -> Option < & str > {
233- self . headers . get ( name) . and_then ( |v| match v {
234- HeaderValue :: String ( s) => Some ( s. as_str ( ) ) ,
235- HeaderValue :: Bytes ( _) => None ,
236- } )
237- }
238-
239- /// The request headers as bytes
240- pub fn headers_raw ( & self ) -> impl Iterator < Item = ( & str , & [ u8 ] ) > {
241- self . headers . iter ( ) . map ( |( k, v) | match v {
242- HeaderValue :: String ( v) => ( k. as_str ( ) , v. as_bytes ( ) ) ,
243- HeaderValue :: Bytes ( v) => ( k. as_str ( ) , v. as_slice ( ) ) ,
244- } )
266+ /// Will return `None` if the header does not exist.
267+ pub fn header ( & self , name : & str ) -> Option < & HeaderValue > {
268+ self . headers . get ( & name. to_lowercase ( ) )
245269 }
246270
247271 /// The response body
@@ -293,7 +317,7 @@ impl ResponseBuilder {
293317 pub fn header ( & mut self , key : impl Into < String > , value : impl Into < String > ) -> & mut Self {
294318 self . response
295319 . headers
296- . insert ( key. into ( ) . to_lowercase ( ) , HeaderValue :: String ( value. into ( ) ) ) ;
320+ . insert ( key. into ( ) . to_lowercase ( ) , HeaderValue :: string ( value. into ( ) ) ) ;
297321 self
298322 }
299323
@@ -315,9 +339,9 @@ fn into_header_rep(headers: impl conversions::IntoHeaders) -> HashMap<String, He
315339 . into_iter ( )
316340 . map ( |( k, v) | {
317341 let v = String :: from_utf8 ( v)
318- . map ( HeaderValue :: String )
319- . unwrap_or_else ( |e| HeaderValue :: Bytes ( e. into_bytes ( ) ) ) ;
320- ( k. to_lowercase ( ) , v )
342+ . map ( HeaderValueRep :: String )
343+ . unwrap_or_else ( |e| HeaderValueRep :: Bytes ( e. into_bytes ( ) ) ) ;
344+ ( k. to_lowercase ( ) , HeaderValue { inner : v } )
321345 } )
322346 . collect ( )
323347}
0 commit comments