@@ -18,6 +18,7 @@ use headers::{
1818 HeaderName ,
1919} ;
2020use http:: {
21+ HeaderValue ,
2122 Method ,
2223 StatusCode ,
2324} ;
@@ -50,7 +51,7 @@ impl HttpRequestV8 {
5051 ) -> anyhow:: Result < HttpRequestStream > {
5152 let mut header_map = HeaderMap :: new ( ) ;
5253 for ( name, value) in & self . header_pairs {
53- header_map. append ( HeaderName :: from_str ( name. as_str ( ) ) ?, value . parse ( ) ?) ;
54+ header_map. append ( HeaderName :: from_str ( name) ?, byte_string_to_header ( value ) ?) ;
5455 }
5556 let ( body_sender, body_receiver) = spsc:: unbounded_channel ( ) ;
5657 match self . stream_id {
@@ -86,9 +87,9 @@ impl HttpRequestV8 {
8687 // None as the HeaderName for headers with multiple values
8788 // (https://docs.rs/http/latest/http/header/struct.HeaderMap.html#method.into_iter)
8889 for ( name, value) in & request. headers {
89- let value_str = value . to_str ( ) ? ;
90+ let value_str = header_to_byte_string ( value ) ;
9091 let header_name_str = name. as_str ( ) ;
91- header_pairs. push ( ( header_name_str. to_string ( ) , value_str. to_string ( ) ) ) ;
92+ header_pairs. push ( ( header_name_str. to_string ( ) , value_str) ) ;
9293 }
9394
9495 Ok ( Self {
@@ -117,7 +118,10 @@ impl HttpResponseV8 {
117118
118119 let mut header_map = HeaderMap :: new ( ) ;
119120 for ( name, value) in & self . header_pairs {
120- header_map. append ( HeaderName :: from_str ( name. as_str ( ) ) ?, value. parse ( ) ?) ;
121+ header_map. append (
122+ HeaderName :: from_str ( name. as_str ( ) ) ?,
123+ byte_string_to_header ( value) ?,
124+ ) ;
121125 }
122126
123127 Ok ( (
@@ -144,9 +148,7 @@ impl HttpResponseV8 {
144148 // None as the HeaderName for headers with multiple values
145149 // (https://docs.rs/http/latest/http/header/struct.HeaderMap.html#method.into_iter)
146150 for ( name, value) in & response. headers {
147- // Don't use `value.to_str()` since that does not support non-ASCII headers
148- let value_bytes = value. as_bytes ( ) ;
149- let value_str: String = value_bytes. iter ( ) . map ( |& c| c as char ) . collect ( ) ;
151+ let value_str = header_to_byte_string ( value) ;
150152 let header_name_str = name. as_str ( ) ;
151153 header_pairs. push ( ( header_name_str. to_string ( ) , value_str) ) ;
152154 }
@@ -168,3 +170,18 @@ impl HttpResponseV8 {
168170 ) )
169171 }
170172}
173+
174+ // WebIDL ByteStrings use "isomorphic encoding" to convert to/from JS strings,
175+ // i.e. latin-1
176+ fn header_to_byte_string ( header : & HeaderValue ) -> String {
177+ header. as_bytes ( ) . iter ( ) . map ( |& b| char:: from ( b) ) . collect ( )
178+ }
179+
180+ fn byte_string_to_header ( header : & str ) -> anyhow:: Result < HeaderValue > {
181+ // TODO: turn these into TypeErrors
182+ let bytes = header
183+ . chars ( )
184+ . map ( |c| u8:: try_from ( c) . map_err ( |_| anyhow:: anyhow!( "invalid char for header: `{c}`" ) ) )
185+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
186+ Ok ( HeaderValue :: from_bytes ( & bytes) ?)
187+ }
0 commit comments