@@ -6,6 +6,7 @@ use hyper::{Method, Request, http};
66use hyper_util:: rt:: { TokioExecutor , TokioIo } ;
77use rand:: prelude:: * ;
88use std:: {
9+ borrow:: Cow ,
910 io:: Write ,
1011 sync:: {
1112 Arc ,
@@ -207,8 +208,6 @@ pub enum ClientError {
207208
208209pub struct Client {
209210 pub request_generator : RequestGenerator ,
210- pub url : Url ,
211- pub http_version : http:: Version ,
212211 pub proxy_http_version : http:: Version ,
213212 pub proxy_headers : http:: header:: HeaderMap ,
214213 pub dns : Dns ,
@@ -246,15 +245,14 @@ impl Default for Client {
246245 url_generator : crate :: url_generator:: UrlGenerator :: new_static (
247246 "http://example.com" . parse ( ) . unwrap ( ) ,
248247 ) ,
248+ https : false ,
249249 http_proxy : None ,
250250 method : http:: Method :: GET ,
251251 version : http:: Version :: HTTP_11 ,
252252 headers : http:: header:: HeaderMap :: new ( ) ,
253253 body_generator : BodyGenerator :: Static ( Bytes :: new ( ) ) ,
254254 aws_config : None ,
255255 } ,
256- url : "http://example.com" . parse ( ) . unwrap ( ) ,
257- http_version : http:: Version :: HTTP_11 ,
258256 proxy_http_version : http:: Version :: HTTP_11 ,
259257 proxy_headers : http:: header:: HeaderMap :: new ( ) ,
260258 dns : Dns {
@@ -411,7 +409,7 @@ impl Stream {
411409impl Client {
412410 #[ inline]
413411 fn is_http2 ( & self ) -> bool {
414- self . http_version == http:: Version :: HTTP_2
412+ self . request_generator . version == http:: Version :: HTTP_2
415413 }
416414
417415 #[ inline]
@@ -421,7 +419,7 @@ impl Client {
421419
422420 fn is_work_http2 ( & self ) -> bool {
423421 if self . proxy_url . is_some ( ) {
424- if self . url . scheme ( ) == " https" {
422+ if self . request_generator . https {
425423 self . is_http2 ( )
426424 } else {
427425 self . is_proxy_http2 ( )
@@ -433,7 +431,7 @@ impl Client {
433431
434432 fn work_type ( & self ) -> HttpWorkType {
435433 #[ cfg( feature = "http3" ) ]
436- if self . http_version == http:: Version :: HTTP_3 {
434+ if self . request_generator . version == http:: Version :: HTTP_3 {
437435 return HttpWorkType :: H3 ;
438436 }
439437 if self . is_work_http2 ( ) {
@@ -458,17 +456,19 @@ impl Client {
458456 }
459457
460458 let mut rng = StdRng :: from_os_rng ( ) ;
459+ let url = self . request_generator . url_generator . generate ( & mut rng) ?;
461460 // It automatically caches the result
462- self . dns . lookup ( & self . url , & mut rng) . await ?;
461+ self . dns . lookup ( & url, & mut rng) . await ?;
463462 Ok ( ( ) )
464463 }
465464
465+ #[ allow( clippy:: type_complexity) ]
466466 pub fn generate_request < R : Rng + Copy > (
467467 & self ,
468468 rng : & mut R ,
469- ) -> Result < ( Request < Full < Bytes > > , R ) , ClientError > {
469+ ) -> Result < ( Cow < ' _ , Url > , Request < Full < Bytes > > , R ) , ClientError > {
470470 let snapshot = * rng;
471- let mut req = self . request_generator . generate ( rng) ?;
471+ let ( url , mut req) = self . request_generator . generate ( rng) ?;
472472 if self . proxy_url . is_some ( ) && req. uri ( ) . scheme_str ( ) == Some ( "http" ) {
473473 if let Some ( authority) = req. uri ( ) . authority ( ) {
474474 let requested_host = authority. host ( ) ;
@@ -486,7 +486,7 @@ impl Client {
486486 }
487487 }
488488 }
489- Ok ( ( req, snapshot) )
489+ Ok ( ( url , req, snapshot) )
490490 }
491491
492492 /**
@@ -665,7 +665,7 @@ impl Client {
665665 } ;
666666 let stream = hyper:: upgrade:: on ( res) . await ?;
667667 let stream = self
668- . connect_tls ( TokioIo :: new ( stream) , url, self . http_version )
668+ . connect_tls ( TokioIo :: new ( stream) , url, self . request_generator . version )
669669 . await ?;
670670 let ( send_request, conn) =
671671 hyper:: client:: conn:: http1:: handshake ( TokioIo :: new ( stream) ) . await ?;
@@ -686,7 +686,7 @@ impl Client {
686686 client_state : & mut ClientStateHttp1 ,
687687 ) -> Result < RequestResult , ClientError > {
688688 let do_req = async {
689- let ( request, rng) = self . generate_request ( & mut client_state. rng ) ?;
689+ let ( url , request, rng) = self . generate_request ( & mut client_state. rng ) ?;
690690 let mut start = std:: time:: Instant :: now ( ) ;
691691 let mut first_byte: Option < std:: time:: Instant > = None ;
692692 let mut connection_time: Option < ConnectionTime > = None ;
@@ -695,7 +695,7 @@ impl Client {
695695 send_request
696696 } else {
697697 let ( dns_lookup, send_request) =
698- self . client_http1 ( & self . url , & mut client_state. rng ) . await ?;
698+ self . client_http1 ( & url, & mut client_state. rng ) . await ?;
699699 let dialup = std:: time:: Instant :: now ( ) ;
700700
701701 connection_time = Some ( ConnectionTime {
@@ -709,7 +709,7 @@ impl Client {
709709 // This re-connects
710710 start = std:: time:: Instant :: now ( ) ;
711711 let ( dns_lookup, send_request_) =
712- self . client_http1 ( & self . url , & mut client_state. rng ) . await ?;
712+ self . client_http1 ( & url, & mut client_state. rng ) . await ?;
713713 send_request = send_request_;
714714 let dialup = std:: time:: Instant :: now ( ) ;
715715 connection_time = Some ( ConnectionTime {
@@ -734,6 +734,7 @@ impl Client {
734734 if let Some ( location) = parts. headers . get ( "Location" ) {
735735 let ( send_request_redirect, new_status, len) = self
736736 . redirect (
737+ url,
737738 rng,
738739 send_request,
739740 location,
@@ -864,7 +865,9 @@ impl Client {
864865 ) )
865866 }
866867 } else {
867- let ( dns_lookup, stream) = self . client ( url, rng, self . http_version ) . await ?;
868+ let ( dns_lookup, stream) = self
869+ . client ( url, rng, self . request_generator . version )
870+ . await ?;
868871 let send_request = stream. handshake_http2 ( ) . await ?;
869872 let dialup = std:: time:: Instant :: now ( ) ;
870873 Ok ( (
@@ -882,7 +885,7 @@ impl Client {
882885 client_state : & mut ClientStateHttp2 ,
883886 ) -> Result < RequestResult , ClientError > {
884887 let do_req = async {
885- let ( request, rng) = self . generate_request ( & mut client_state. rng ) ?;
888+ let ( _url , request, rng) = self . generate_request ( & mut client_state. rng ) ?;
886889 let start = std:: time:: Instant :: now ( ) ;
887890 let mut first_byte: Option < std:: time:: Instant > = None ;
888891 let connection_time: Option < ConnectionTime > = None ;
@@ -936,6 +939,7 @@ impl Client {
936939 #[ allow( clippy:: type_complexity) ]
937940 async fn redirect < R : Rng + Send + Copy > (
938941 & self ,
942+ base_url : Cow < ' _ , Url > ,
939943 seed : R ,
940944 send_request : SendRequestHttp1 ,
941945 location : & http:: header:: HeaderValue ,
@@ -948,13 +952,13 @@ impl Client {
948952 let url = match Url :: parse ( location. to_str ( ) ?) {
949953 Ok ( url) => url,
950954 Err ( ParseError :: RelativeUrlWithoutBase ) => Url :: options ( )
951- . base_url ( Some ( & self . url ) )
955+ . base_url ( Some ( & base_url ) )
952956 . parse ( location. to_str ( ) ?) ?,
953957 Err ( err) => Err ( err) ?,
954958 } ;
955959
956960 let ( mut send_request, send_request_base) =
957- if self . url . authority ( ) == url. authority ( ) && !self . disable_keepalive {
961+ if base_url . authority ( ) == url. authority ( ) && !self . disable_keepalive {
958962 // reuse connection
959963 ( send_request, None )
960964 } else {
@@ -967,8 +971,8 @@ impl Client {
967971 send_request = stream;
968972 }
969973
970- let mut request = self . generate_request ( & mut seed. clone ( ) ) ?. 0 ;
971- if url. authority ( ) != self . url . authority ( ) {
974+ let mut request = self . generate_request ( & mut seed. clone ( ) ) ?. 1 ;
975+ if url. authority ( ) != base_url . authority ( ) {
972976 request. headers_mut ( ) . insert (
973977 http:: header:: HOST ,
974978 http:: HeaderValue :: from_str ( url. authority ( ) ) ?,
@@ -1008,7 +1012,8 @@ impl Client {
10081012
10091013 if let Some ( location) = parts. headers . get ( "Location" ) {
10101014 let ( send_request_redirect, new_status, len) =
1011- Box :: pin ( self . redirect ( seed, send_request, location, limit - 1 , rng) ) . await ?;
1015+ Box :: pin ( self . redirect ( base_url, seed, send_request, location, limit - 1 , rng) )
1016+ . await ?;
10121017 send_request = send_request_redirect;
10131018 status = new_status;
10141019 len_bytes = len;
@@ -1056,7 +1061,8 @@ async fn setup_http2<R: Rng>(
10561061 client : & Client ,
10571062 rng : & mut R ,
10581063) -> Result < ( ConnectionTime , SendRequestHttp2 ) , ClientError > {
1059- let ( connection_time, send_request) = client. connect_http2 ( & client. url , rng) . await ?;
1064+ let url = client. request_generator . url_generator . generate ( rng) ?;
1065+ let ( connection_time, send_request) = client. connect_http2 ( & url, rng) . await ?;
10601066
10611067 Ok ( ( connection_time, send_request) )
10621068}
@@ -1099,29 +1105,27 @@ pub(crate) fn set_start_latency_correction<E>(
10991105
11001106pub async fn work_debug < W : Write > ( w : & mut W , client : Arc < Client > ) -> Result < ( ) , ClientError > {
11011107 let mut rng = Pcg64Si :: from_os_rng ( ) ;
1102- let ( request, _) = client. generate_request ( & mut rng) ?;
1108+ let ( url , request, _) = client. generate_request ( & mut rng) ?;
11031109
11041110 writeln ! ( w, "{request:#?}" ) ?;
11051111
11061112 let response = match client. work_type ( ) {
11071113 #[ cfg( feature = "http3" ) ]
11081114 HttpWorkType :: H3 => {
1109- let ( _, ( h3_connection, client_state) ) =
1110- client. connect_http3 ( & client. url , & mut rng) . await ?;
1115+ let ( _, ( h3_connection, client_state) ) = client. connect_http3 ( & url, & mut rng) . await ?;
11111116
11121117 send_debug_request_http3 ( h3_connection, client_state, request) . await ?
11131118 }
11141119 HttpWorkType :: H2 => {
1115- let ( _, mut client_state) = client. connect_http2 ( & client . url , & mut rng) . await ?;
1120+ let ( _, mut client_state) = client. connect_http2 ( & url, & mut rng) . await ?;
11161121 let response = client_state. send_request ( request) . await ?;
11171122 let ( parts, body) = response. into_parts ( ) ;
11181123 let body = body. collect ( ) . await . unwrap ( ) . to_bytes ( ) ;
11191124
11201125 http:: Response :: from_parts ( parts, body)
11211126 }
11221127 HttpWorkType :: H1 => {
1123- let ( _dns_lookup, mut send_request) =
1124- client. client_http1 ( & client. url , & mut rng) . await ?;
1128+ let ( _dns_lookup, mut send_request) = client. client_http1 ( & url, & mut rng) . await ?;
11251129
11261130 let response = send_request. send_request ( request) . await ?;
11271131 let ( parts, body) = response. into_parts ( ) ;
0 commit comments