@@ -2,6 +2,7 @@ use std::borrow::Borrow;
22use std:: convert:: { From , TryInto } ;
33use std:: fs;
44use std:: str;
5+ use std:: sync:: Arc ;
56use std:: time:: Duration ;
67
78use base64:: Engine ;
@@ -38,7 +39,10 @@ pub struct RequestBuilder<B = body::Empty> {
3839 url : Url ,
3940 method : Method ,
4041 body : B ,
41- base_settings : BaseSettings ,
42+ // Headers are always modified by [Self::try_prepare], it's cheaper to keep them
43+ // separate than to clone all of BaseSettings through [Arc::make_mut].
44+ headers : HeaderMap ,
45+ base_settings : Arc < BaseSettings > ,
4246}
4347
4448impl RequestBuilder {
@@ -61,17 +65,17 @@ impl RequestBuilder {
6165 where
6266 U : AsRef < str > ,
6367 {
64- Self :: try_with_settings ( method, base_url, BaseSettings :: default ( ) )
68+ Self :: try_with_settings ( method, base_url, Arc :: new ( BaseSettings :: default ( ) ) )
6569 }
6670
67- pub ( crate ) fn with_settings < U > ( method : Method , base_url : U , base_settings : BaseSettings ) -> Self
71+ pub ( crate ) fn with_settings < U > ( method : Method , base_url : U , base_settings : Arc < BaseSettings > ) -> Self
6872 where
6973 U : AsRef < str > ,
7074 {
7175 Self :: try_with_settings ( method, base_url, base_settings) . expect ( "invalid url or method" )
7276 }
7377
74- pub ( crate ) fn try_with_settings < U > ( method : Method , base_url : U , base_settings : BaseSettings ) -> Result < Self >
78+ pub ( crate ) fn try_with_settings < U > ( method : Method , base_url : U , base_settings : Arc < BaseSettings > ) -> Result < Self >
7579 where
7680 U : AsRef < str > ,
7781 {
@@ -85,6 +89,7 @@ impl RequestBuilder {
8589 url,
8690 method,
8791 body : body:: Empty ,
92+ headers : base_settings. headers . clone ( ) ,
8893 base_settings,
8994 } )
9095 }
@@ -161,6 +166,7 @@ impl<B> RequestBuilder<B> {
161166 url : self . url ,
162167 method : self . method ,
163168 body,
169+ headers : self . headers ,
164170 base_settings : self . base_settings ,
165171 }
166172 }
@@ -169,8 +175,7 @@ impl<B> RequestBuilder<B> {
169175 ///
170176 /// If the `Content-Type` header is unset, it will be set to `text/plain` and the charset to UTF-8.
171177 pub fn text < B1 : AsRef < str > > ( mut self , body : B1 ) -> RequestBuilder < body:: Text < B1 > > {
172- self . base_settings
173- . headers
178+ self . headers
174179 . entry ( http:: header:: CONTENT_TYPE )
175180 . or_insert ( HeaderValue :: from_static ( "text/plain; charset=utf-8" ) ) ;
176181 self . body ( body:: Text ( body) )
@@ -180,8 +185,7 @@ impl<B> RequestBuilder<B> {
180185 ///
181186 /// If the `Content-Type` header is unset, it will be set to `application/octet-stream`.
182187 pub fn bytes < B1 : AsRef < [ u8 ] > > ( mut self , body : B1 ) -> RequestBuilder < body:: Bytes < B1 > > {
183- self . base_settings
184- . headers
188+ self . headers
185189 . entry ( http:: header:: CONTENT_TYPE )
186190 . or_insert ( HeaderValue :: from_static ( "application/octet-stream" ) ) ;
187191 self . body ( body:: Bytes ( body) )
@@ -191,8 +195,7 @@ impl<B> RequestBuilder<B> {
191195 ///
192196 /// If the `Content-Type` header is unset, it will be set to `application/octet-stream`.
193197 pub fn file ( mut self , body : fs:: File ) -> RequestBuilder < body:: File > {
194- self . base_settings
195- . headers
198+ self . headers
196199 . entry ( http:: header:: CONTENT_TYPE )
197200 . or_insert ( HeaderValue :: from_static ( "application/octet-stream" ) ) ;
198201 self . body ( body:: File ( body) )
@@ -204,8 +207,7 @@ impl<B> RequestBuilder<B> {
204207 #[ cfg( feature = "json" ) ]
205208 pub fn json < T : serde:: Serialize > ( mut self , value : & T ) -> Result < RequestBuilder < body:: Bytes < Vec < u8 > > > > {
206209 let body = serde_json:: to_vec ( value) ?;
207- self . base_settings
208- . headers
210+ self . headers
209211 . entry ( http:: header:: CONTENT_TYPE )
210212 . or_insert ( HeaderValue :: from_static ( "application/json; charset=utf-8" ) ) ;
211213 Ok ( self . body ( body:: Bytes ( body) ) )
@@ -216,8 +218,7 @@ impl<B> RequestBuilder<B> {
216218 /// If the `Content-Type` header is unset, it will be set to `application/json` and the charset to UTF-8.
217219 #[ cfg( feature = "json" ) ]
218220 pub fn json_streaming < T : serde:: Serialize > ( mut self , value : T ) -> RequestBuilder < body:: Json < T > > {
219- self . base_settings
220- . headers
221+ self . headers
221222 . entry ( http:: header:: CONTENT_TYPE )
222223 . or_insert ( HeaderValue :: from_static ( "application/json; charset=utf-8" ) ) ;
223224 self . body ( body:: Json ( value) )
@@ -229,13 +230,22 @@ impl<B> RequestBuilder<B> {
229230 #[ cfg( feature = "form" ) ]
230231 pub fn form < T : serde:: Serialize > ( mut self , value : & T ) -> Result < RequestBuilder < body:: Bytes < Vec < u8 > > > > {
231232 let body = serde_urlencoded:: to_string ( value) ?. into_bytes ( ) ;
232- self . base_settings
233- . headers
233+ self . headers
234234 . entry ( http:: header:: CONTENT_TYPE )
235235 . or_insert ( HeaderValue :: from_static ( "application/x-www-form-urlencoded" ) ) ;
236236 Ok ( self . body ( body:: Bytes ( body) ) )
237237 }
238238
239+ /// Get a mutable reference to headers.
240+ pub fn headers ( & self ) -> & HeaderMap {
241+ & self . headers
242+ }
243+
244+ /// Get a mutable reference to headers.
245+ pub fn headers_mut ( & mut self ) -> & mut HeaderMap {
246+ & mut self . headers
247+ }
248+
239249 //
240250 // Settings
241251 //
@@ -281,7 +291,7 @@ impl<B> RequestBuilder<B> {
281291 V : TryInto < HeaderValue > ,
282292 Error : From < V :: Error > ,
283293 {
284- header_insert ( & mut self . base_settings . headers , header, value) ?;
294+ header_insert ( & mut self . headers , header, value) ?;
285295 Ok ( self )
286296 }
287297
@@ -294,68 +304,63 @@ impl<B> RequestBuilder<B> {
294304 V : TryInto < HeaderValue > ,
295305 Error : From < V :: Error > ,
296306 {
297- header_append ( & mut self . base_settings . headers , header, value) ?;
307+ header_append ( & mut self . headers , header, value) ?;
298308 Ok ( self )
299309 }
300310
301311 /// Set the maximum number of headers accepted in responses to this request.
302312 ///
303313 /// The default is 100.
304314 pub fn max_headers ( mut self , max_headers : usize ) -> Self {
305- self . base_settings . max_headers = max_headers ;
315+ self . base_settings . set_max_headers ( max_headers) ;
306316 self
307317 }
308318
309- /// Get a mutable reference to headers.
310- pub fn headers_mut ( & mut self ) -> & mut HeaderMap {
311- & mut self . base_settings . headers
312- }
313-
314319 /// Set the maximum number of redirections this request can perform.
315320 ///
316321 /// The default is 5.
317322 pub fn max_redirections ( mut self , max_redirections : u32 ) -> Self {
318- self . base_settings . max_redirections = max_redirections ;
323+ self . base_settings . set_max_redirections ( max_redirections) ;
319324 self
320325 }
321326
322327 /// Sets if this request should follow redirects, 3xx codes.
323328 ///
324329 /// This value defaults to true.
325330 pub fn follow_redirects ( mut self , follow_redirects : bool ) -> Self {
326- self . base_settings . follow_redirects = follow_redirects ;
331+ self . base_settings . set_follow_redirects ( follow_redirects) ;
327332 self
328333 }
329334
330335 /// Sets a connect timeout for this request.
331336 ///
332337 /// The default is 30 seconds.
333- pub fn connect_timeout ( mut self , duration : Duration ) -> Self {
334- self . base_settings . connect_timeout = duration ;
338+ pub fn connect_timeout ( mut self , connect_timeout : Duration ) -> Self {
339+ self . base_settings . set_connect_timeout ( connect_timeout) ;
335340 self
336341 }
337342
338343 /// Sets a read timeout for this request.
339344 ///
340345 /// The default is 30 seconds.
341- pub fn read_timeout ( mut self , duration : Duration ) -> Self {
342- self . base_settings . read_timeout = duration ;
346+ pub fn read_timeout ( mut self , read_timeout : Duration ) -> Self {
347+ self . base_settings . set_read_tmeout ( read_timeout) ;
343348 self
344349 }
345350
346351 /// Sets a timeout for the whole request.
347352 ///
348353 /// Applies after a TCP connection is established. Defaults to no timeout.
349- pub fn timeout ( mut self , duration : Duration ) -> Self {
350- self . base_settings . timeout = Some ( duration ) ;
354+ pub fn timeout ( mut self , timeout : Duration ) -> Self {
355+ self . base_settings . set_timeout ( Some ( timeout ) ) ;
351356 self
352357 }
353358
354359 /// Sets the proxy settigns for this request.
355360 ///
356361 /// If left untouched, the defaults are to use system proxy settings found in environment variables.
357- pub fn proxy_settings ( mut self , settings : ProxySettings ) -> Self {
358- self . base_settings . proxy_settings = settings ;
362+ pub fn proxy_settings ( mut self , proxy_settings : ProxySettings ) -> Self {
363+ self . base_settings . set_proxy_settings ( proxy_settings) ;
359364 self
360365 }
361366
@@ -365,7 +370,7 @@ impl<B> RequestBuilder<B> {
365370 /// This value defaults to `None`, in which case ISO-8859-1 is used.
366371 #[ cfg( feature = "charsets" ) ]
367372 pub fn default_charset ( mut self , default_charset : Option < Charset > ) -> Self {
368- self . base_settings . default_charset = default_charset ;
373+ self . base_settings . set_default_charset ( default_charset) ;
369374 self
370375 }
371376
@@ -375,7 +380,7 @@ impl<B> RequestBuilder<B> {
375380 /// compression, the server might choose not to compress the content.
376381 #[ cfg( feature = "flate2" ) ]
377382 pub fn allow_compression ( mut self , allow_compression : bool ) -> Self {
378- self . base_settings . allow_compression = allow_compression ;
383+ self . base_settings . set_allow_compression ( allow_compression) ;
379384 self
380385 }
381386
@@ -391,7 +396,7 @@ impl<B> RequestBuilder<B> {
391396 /// If you are using self signed certificates, it is much safer to add their root CA
392397 /// to the list of trusted root CAs by your system.
393398 pub fn danger_accept_invalid_certs ( mut self , accept_invalid_certs : bool ) -> Self {
394- self . base_settings . accept_invalid_certs = accept_invalid_certs ;
399+ self . base_settings . set_accept_invalid_certs ( accept_invalid_certs) ;
395400 self
396401 }
397402
@@ -403,13 +408,14 @@ impl<B> RequestBuilder<B> {
403408 /// Use this setting with care. This will accept TLS certificates that do not match
404409 /// the hostname.
405410 pub fn danger_accept_invalid_hostnames ( mut self , accept_invalid_hostnames : bool ) -> Self {
406- self . base_settings . accept_invalid_hostnames = accept_invalid_hostnames;
411+ self . base_settings
412+ . set_accept_invalid_hostnames ( accept_invalid_hostnames) ;
407413 self
408414 }
409415
410416 /// Adds a root certificate that will be trusted.
411417 pub fn add_root_certificate ( mut self , cert : Certificate ) -> Self {
412- self . base_settings . root_certificates . 0 . push ( cert) ;
418+ self . base_settings . add_root_certificate ( cert) ;
413419 self
414420 }
415421}
@@ -429,27 +435,29 @@ impl<B: Body> RequestBuilder<B> {
429435 url : self . url ,
430436 method : self . method ,
431437 body : self . body ,
438+ headers : self . headers ,
432439 base_settings : self . base_settings ,
433440 } ;
434-
435- header_insert ( & mut prepped. base_settings . headers , CONNECTION , "close" ) ?;
436441 prepped. set_compression ( ) ?;
442+ let headers = & mut prepped. headers ;
443+
444+ header_insert ( headers, CONNECTION , "close" ) ?;
437445 match prepped. body . kind ( ) ? {
438446 BodyKind :: Empty => ( ) ,
439447 BodyKind :: KnownLength ( len) => {
440- header_insert ( & mut prepped . base_settings . headers , CONTENT_LENGTH , len) ?;
448+ header_insert ( headers, CONTENT_LENGTH , len) ?;
441449 }
442450 BodyKind :: Chunked => {
443- header_insert ( & mut prepped . base_settings . headers , TRANSFER_ENCODING , "chunked" ) ?;
451+ header_insert ( headers, TRANSFER_ENCODING , "chunked" ) ?;
444452 }
445453 }
446454
447455 if let Some ( typ) = prepped. body . content_type ( ) ? {
448- header_insert ( & mut prepped . base_settings . headers , CONTENT_TYPE , typ) ?;
456+ header_insert ( headers, CONTENT_TYPE , typ) ?;
449457 }
450458
451- header_insert_if_missing ( & mut prepped . base_settings . headers , ACCEPT , "*/*" ) ?;
452- header_insert_if_missing ( & mut prepped . base_settings . headers , USER_AGENT , DEFAULT_USER_AGENT ) ?;
459+ header_insert_if_missing ( headers, ACCEPT , "*/*" ) ?;
460+ header_insert_if_missing ( headers, USER_AGENT , DEFAULT_USER_AGENT ) ?;
453461
454462 Ok ( prepped)
455463 }
@@ -489,7 +497,7 @@ impl<B> RequestInspector<'_, B> {
489497
490498 /// Acess the current headers
491499 pub fn headers ( & self ) -> & HeaderMap {
492- & self . 0 . base_settings . headers
500+ & self . 0 . headers
493501 }
494502}
495503
0 commit comments