22// SPDX-License-Identifier: Apache-2.0
33// SPDX-License-Identifier: MIT
44
5- use std:: { collections :: HashMap , future:: Future , pin:: Pin , sync:: Arc , time:: Duration } ;
5+ use std:: { future:: Future , pin:: Pin , str :: FromStr , sync:: Arc , time:: Duration } ;
66
7- use http:: { header, HeaderName , Method , StatusCode } ;
7+ use http:: { header, HeaderMap , HeaderName , HeaderValue , Method , StatusCode } ;
88use reqwest:: { redirect:: Policy , NoProxy } ;
99use serde:: { Deserialize , Serialize } ;
1010use tauri:: {
@@ -176,7 +176,7 @@ pub async fn fetch<R: Runtime>(
176176 let ClientConfig {
177177 method,
178178 url,
179- headers,
179+ headers : headers_raw ,
180180 data,
181181 connect_timeout,
182182 max_redirections,
@@ -185,7 +185,17 @@ pub async fn fetch<R: Runtime>(
185185
186186 let scheme = url. scheme ( ) ;
187187 let method = Method :: from_bytes ( method. as_bytes ( ) ) ?;
188- let headers: HashMap < String , String > = HashMap :: from_iter ( headers) ;
188+
189+ let mut headers = HeaderMap :: new ( ) ;
190+ for ( h, v) in headers_raw {
191+ let name = HeaderName :: from_str ( & h) ?;
192+ #[ cfg( not( feature = "unsafe-headers" ) ) ]
193+ if is_unsafe_header ( & name) {
194+ continue ;
195+ }
196+
197+ headers. append ( name, HeaderValue :: from_str ( & v) ?) ;
198+ }
189199
190200 match scheme {
191201 "http" | "https" => {
@@ -228,45 +238,38 @@ pub async fn fetch<R: Runtime>(
228238
229239 let mut request = builder. build ( ) ?. request ( method. clone ( ) , url) ;
230240
231- for ( name, value) in & headers {
232- let name = HeaderName :: from_bytes ( name. as_bytes ( ) ) ?;
233- #[ cfg( not( feature = "unsafe-headers" ) ) ]
234- if is_unsafe_header ( & name) {
235- continue ;
236- }
237-
238- request = request. header ( name, value) ;
239- }
240-
241241 // POST and PUT requests should always have a 0 length content-length,
242242 // if there is no body. https://fetch.spec.whatwg.org/#http-network-or-cache-fetch
243243 if data. is_none ( ) && matches ! ( method, Method :: POST | Method :: PUT ) {
244- request = request . header ( header:: CONTENT_LENGTH , 0 ) ;
244+ headers . append ( header:: CONTENT_LENGTH , HeaderValue :: from_str ( "0" ) ? ) ;
245245 }
246246
247- if headers. contains_key ( header:: RANGE . as_str ( ) ) {
247+ if headers. contains_key ( header:: RANGE ) {
248248 // https://fetch.spec.whatwg.org/#http-network-or-cache-fetch step 18
249249 // If httpRequest’s header list contains `Range`, then append (`Accept-Encoding`, `identity`)
250- request = request . header ( header:: ACCEPT_ENCODING , "identity" ) ;
250+ headers . append ( header:: ACCEPT_ENCODING , HeaderValue :: from_str ( "identity" ) ? ) ;
251251 }
252252
253- if !headers. contains_key ( header:: USER_AGENT . as_str ( ) ) {
254- request = request . header ( header:: USER_AGENT , HTTP_USER_AGENT ) ;
253+ if !headers. contains_key ( header:: USER_AGENT ) {
254+ headers . append ( header:: USER_AGENT , HeaderValue :: from_str ( HTTP_USER_AGENT ) ? ) ;
255255 }
256256
257- if cfg ! ( feature = "unsafe-headers" )
258- && !headers. contains_key ( header:: ORIGIN . as_str ( ) )
259- {
257+ // ensure we have an Origin header set
258+ if cfg ! ( not( feature = "unsafe-headers" ) ) || !headers. contains_key ( header:: ORIGIN ) {
260259 if let Ok ( url) = webview. url ( ) {
261- request =
262- request. header ( header:: ORIGIN , url. origin ( ) . ascii_serialization ( ) ) ;
260+ headers. append (
261+ header:: ORIGIN ,
262+ HeaderValue :: from_str ( & url. origin ( ) . ascii_serialization ( ) ) ?,
263+ ) ;
263264 }
264265 }
265266
266267 if let Some ( data) = data {
267268 request = request. body ( data) ;
268269 }
269270
271+ request = request. headers ( headers) ;
272+
270273 let fut = async move { request. send ( ) . await . map_err ( Into :: into) } ;
271274 let mut resources_table = webview. resources_table ( ) ;
272275 let rid = resources_table. add_request ( Box :: pin ( fut) ) ;
0 commit comments