pub struct Client { /* private fields */ }Expand description
Reusable synchronous HTTP client.
Use this when you want to configure redirects, connection reuse, caching, proxy behavior, and authentication once, then execute many requests.
Implementations§
Source§impl Client
impl Client
Sourcepub fn builder() -> ClientBuilder
pub fn builder() -> ClientBuilder
Creates a new ClientBuilder.
Examples found in repository?
examples/custom-auth-handler/main.rs (line 47)
41fn main() -> Result<(), Box<dyn Error>> {
42 let Some(url) = env::var("NANO_GET_CUSTOM_AUTH_URL").ok() else {
43 print_setup();
44 return Ok(());
45 };
46
47 let client = Client::builder()
48 .auth_handler(Arc::new(DemoTokenAuth))
49 .build();
50 let response = client.execute(Request::get(&url)?)?;
51
52 println!("custom-auth-handler example");
53 println!(
54 "status: {} {}",
55 response.status_code, response.reason_phrase
56 );
57 println!(
58 "parsed WWW-Authenticate challenges: {}",
59 response.www_authenticate_challenges()?.len()
60 );
61
62 Ok(())
63}More examples
examples/nano-get-bench.rs (line 46)
42fn bench_get(iterations: usize) -> Duration {
43 let response = b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello".to_vec();
44 let (base_url, handle) = spawn_persistent_server(iterations, response);
45
46 let client = Client::builder()
47 .connection_policy(ConnectionPolicy::Reuse)
48 .build();
49 let mut session = client.session();
50
51 let start = Instant::now();
52 for i in 0..iterations {
53 let req = Request::get(format!("{}/g{}", base_url, i)).expect("request");
54 let resp = session.execute(req).expect("execute");
55 assert_eq!(resp.body, b"hello");
56 }
57 let elapsed = start.elapsed();
58 handle.join().expect("join server");
59 elapsed
60}
61
62fn bench_head(iterations: usize) -> Duration {
63 let response = b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\nX-Bench: 1\r\n\r\n".to_vec();
64 let (base_url, handle) = spawn_persistent_server(iterations, response);
65
66 let client = Client::builder()
67 .connection_policy(ConnectionPolicy::Reuse)
68 .build();
69 let mut session = client.session();
70
71 let start = Instant::now();
72 for i in 0..iterations {
73 let req = Request::head(format!("{}/h{}", base_url, i)).expect("request");
74 let resp = session.execute(req).expect("execute");
75 assert!(resp.body.is_empty());
76 }
77 let elapsed = start.elapsed();
78 handle.join().expect("join server");
79 elapsed
80}
81
82fn bench_pipeline(total_requests: usize, pipeline_depth: usize) -> Duration {
83 let response = b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello".to_vec();
84 let (base_url, handle) = spawn_persistent_server(total_requests, response);
85
86 let client = Client::builder()
87 .connection_policy(ConnectionPolicy::Reuse)
88 .build();
89 let mut session = client.session();
90
91 let start = Instant::now();
92 let mut sent = 0usize;
93 while sent < total_requests {
94 let batch_size = (total_requests - sent).min(pipeline_depth);
95 let mut batch = Vec::with_capacity(batch_size);
96 for index in 0..batch_size {
97 batch.push(Request::get(format!("{}/p{}", base_url, sent + index)).expect("request"));
98 }
99 let responses = session.execute_pipelined(&batch).expect("execute");
100 assert_eq!(responses.len(), batch_size);
101 for response in responses {
102 assert_eq!(response.body, b"hello");
103 }
104 sent += batch_size;
105 }
106 let elapsed = start.elapsed();
107 handle.join().expect("join server");
108 elapsed
109}examples/session-reuse-and-pipelining/main.rs (line 15)
14fn main() -> Result<(), Box<dyn Error>> {
15 let client = Client::builder()
16 .connection_policy(ConnectionPolicy::Reuse)
17 .build();
18 let mut session = client.session();
19
20 let first = session.execute(Request::get("http://example.com/")?)?;
21 let second = session.execute(Request::get("http://example.com/index.html")?)?;
22 let pipelined = session.execute_pipelined(&[
23 Request::get("http://example.com/")?,
24 Request::get("http://example.com/index.html")?,
25 ])?;
26
27 println!("This example demonstrates the Session API shape for reuse and pipelining.");
28 summarize("sequential #1", &first);
29 summarize("sequential #2", &second);
30 summarize("pipeline #1", &pipelined[0]);
31 summarize("pipeline #2", &pipelined[1]);
32
33 Ok(())
34}examples/memory-cache/main.rs (line 6)
5fn main() -> Result<(), Box<dyn Error>> {
6 let client = Client::builder().cache_mode(CacheMode::Memory).build();
7
8 let first = Request::get("http://example.com")?;
9 let mut second = Request::get("http://example.com")?;
10 second.add_header("Cache-Control", "max-age=0, min-fresh=1")?;
11
12 let first_response = client.execute(first)?;
13 let second_response = client.execute(second)?;
14
15 println!("memory cache example");
16 println!(
17 "first response: {} {}",
18 first_response.status_code, first_response.reason_phrase
19 );
20 println!(
21 "second response with request directives: {} {}",
22 second_response.status_code, second_response.reason_phrase
23 );
24 println!("This example demonstrates cache configuration and cache-control request headers.");
25
26 Ok(())
27}examples/basic-auth/main.rs (line 27)
18fn main() -> Result<(), Box<dyn Error>> {
19 let Some(url) = env::var("NANO_GET_BASIC_AUTH_URL").ok() else {
20 print_setup();
21 return Ok(());
22 };
23
24 let user = env_or_default("NANO_GET_BASIC_AUTH_USER", "demo-user");
25 let pass = env_or_default("NANO_GET_BASIC_AUTH_PASS", "demo-pass");
26
27 let challenge_driven = Client::builder()
28 .basic_auth(user.clone(), pass.clone())
29 .build()
30 .execute(Request::get(&url)?)?;
31
32 let preemptive = Client::builder()
33 .preemptive_basic_auth(user.clone(), pass.clone())
34 .build()
35 .execute(Request::get(&url)?)?;
36
37 let mut request = Request::get(&url)?;
38 request.basic_auth(user, pass)?;
39 let manual = request.execute()?;
40
41 println!("basic-auth example");
42 println!("challenge-driven status: {}", challenge_driven.status_code);
43 println!("preemptive status: {}", preemptive.status_code);
44 println!("request-level override status: {}", manual.status_code);
45
46 Ok(())
47}examples/proxy-and-proxy-auth/main.rs (line 32)
19fn main() -> Result<(), Box<dyn Error>> {
20 let Some(proxy_url) = env::var("NANO_GET_PROXY_URL").ok() else {
21 print_setup();
22 return Ok(());
23 };
24
25 let target_url = env_or_default("NANO_GET_PROXY_TARGET_URL", "http://example.com");
26 let proxy_user = env_or_default("NANO_GET_PROXY_AUTH_USER", "proxy-user");
27 let proxy_pass = env_or_default("NANO_GET_PROXY_AUTH_PASS", "proxy-pass");
28
29 let mut proxy = ProxyConfig::new(proxy_url)?;
30 proxy.add_header("X-Example-Proxy", "nano-get-demo")?;
31
32 let challenge_driven = Client::builder()
33 .proxy(proxy.clone())
34 .basic_proxy_auth(proxy_user.clone(), proxy_pass.clone())
35 .build()
36 .execute(Request::get(&target_url)?)?;
37
38 let preemptive = Client::builder()
39 .proxy(proxy.clone())
40 .preemptive_basic_proxy_auth(proxy_user.clone(), proxy_pass.clone())
41 .build()
42 .execute(Request::get(&target_url)?)?;
43
44 let mut manual = Request::get(&target_url)?;
45 manual.proxy_basic_auth(proxy_user, proxy_pass)?;
46 let manual_response = Client::builder().proxy(proxy).build().execute(manual)?;
47
48 println!("proxy-and-proxy-auth example");
49 println!("challenge-driven status: {}", challenge_driven.status_code);
50 println!("preemptive status: {}", preemptive.status_code);
51 println!(
52 "request-level override status: {}",
53 manual_response.status_code
54 );
55
56 Ok(())
57}Sourcepub fn session(&self) -> Session
pub fn session(&self) -> Session
Creates a Session that can reuse a live connection for sequential requests.
Examples found in repository?
examples/nano-get-bench.rs (line 49)
42fn bench_get(iterations: usize) -> Duration {
43 let response = b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello".to_vec();
44 let (base_url, handle) = spawn_persistent_server(iterations, response);
45
46 let client = Client::builder()
47 .connection_policy(ConnectionPolicy::Reuse)
48 .build();
49 let mut session = client.session();
50
51 let start = Instant::now();
52 for i in 0..iterations {
53 let req = Request::get(format!("{}/g{}", base_url, i)).expect("request");
54 let resp = session.execute(req).expect("execute");
55 assert_eq!(resp.body, b"hello");
56 }
57 let elapsed = start.elapsed();
58 handle.join().expect("join server");
59 elapsed
60}
61
62fn bench_head(iterations: usize) -> Duration {
63 let response = b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\nX-Bench: 1\r\n\r\n".to_vec();
64 let (base_url, handle) = spawn_persistent_server(iterations, response);
65
66 let client = Client::builder()
67 .connection_policy(ConnectionPolicy::Reuse)
68 .build();
69 let mut session = client.session();
70
71 let start = Instant::now();
72 for i in 0..iterations {
73 let req = Request::head(format!("{}/h{}", base_url, i)).expect("request");
74 let resp = session.execute(req).expect("execute");
75 assert!(resp.body.is_empty());
76 }
77 let elapsed = start.elapsed();
78 handle.join().expect("join server");
79 elapsed
80}
81
82fn bench_pipeline(total_requests: usize, pipeline_depth: usize) -> Duration {
83 let response = b"HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nhello".to_vec();
84 let (base_url, handle) = spawn_persistent_server(total_requests, response);
85
86 let client = Client::builder()
87 .connection_policy(ConnectionPolicy::Reuse)
88 .build();
89 let mut session = client.session();
90
91 let start = Instant::now();
92 let mut sent = 0usize;
93 while sent < total_requests {
94 let batch_size = (total_requests - sent).min(pipeline_depth);
95 let mut batch = Vec::with_capacity(batch_size);
96 for index in 0..batch_size {
97 batch.push(Request::get(format!("{}/p{}", base_url, sent + index)).expect("request"));
98 }
99 let responses = session.execute_pipelined(&batch).expect("execute");
100 assert_eq!(responses.len(), batch_size);
101 for response in responses {
102 assert_eq!(response.body, b"hello");
103 }
104 sent += batch_size;
105 }
106 let elapsed = start.elapsed();
107 handle.join().expect("join server");
108 elapsed
109}More examples
examples/session-reuse-and-pipelining/main.rs (line 18)
14fn main() -> Result<(), Box<dyn Error>> {
15 let client = Client::builder()
16 .connection_policy(ConnectionPolicy::Reuse)
17 .build();
18 let mut session = client.session();
19
20 let first = session.execute(Request::get("http://example.com/")?)?;
21 let second = session.execute(Request::get("http://example.com/index.html")?)?;
22 let pipelined = session.execute_pipelined(&[
23 Request::get("http://example.com/")?,
24 Request::get("http://example.com/index.html")?,
25 ])?;
26
27 println!("This example demonstrates the Session API shape for reuse and pipelining.");
28 summarize("sequential #1", &first);
29 summarize("sequential #2", &second);
30 summarize("pipeline #1", &pipelined[0]);
31 summarize("pipeline #2", &pipelined[1]);
32
33 Ok(())
34}Sourcepub fn execute(&self, request: Request) -> Result<Response, NanoGetError>
pub fn execute(&self, request: Request) -> Result<Response, NanoGetError>
Executes a fully configured Request.
Examples found in repository?
examples/custom-auth-handler/main.rs (line 50)
41fn main() -> Result<(), Box<dyn Error>> {
42 let Some(url) = env::var("NANO_GET_CUSTOM_AUTH_URL").ok() else {
43 print_setup();
44 return Ok(());
45 };
46
47 let client = Client::builder()
48 .auth_handler(Arc::new(DemoTokenAuth))
49 .build();
50 let response = client.execute(Request::get(&url)?)?;
51
52 println!("custom-auth-handler example");
53 println!(
54 "status: {} {}",
55 response.status_code, response.reason_phrase
56 );
57 println!(
58 "parsed WWW-Authenticate challenges: {}",
59 response.www_authenticate_challenges()?.len()
60 );
61
62 Ok(())
63}More examples
examples/memory-cache/main.rs (line 12)
5fn main() -> Result<(), Box<dyn Error>> {
6 let client = Client::builder().cache_mode(CacheMode::Memory).build();
7
8 let first = Request::get("http://example.com")?;
9 let mut second = Request::get("http://example.com")?;
10 second.add_header("Cache-Control", "max-age=0, min-fresh=1")?;
11
12 let first_response = client.execute(first)?;
13 let second_response = client.execute(second)?;
14
15 println!("memory cache example");
16 println!(
17 "first response: {} {}",
18 first_response.status_code, first_response.reason_phrase
19 );
20 println!(
21 "second response with request directives: {} {}",
22 second_response.status_code, second_response.reason_phrase
23 );
24 println!("This example demonstrates cache configuration and cache-control request headers.");
25
26 Ok(())
27}examples/basic-auth/main.rs (line 30)
18fn main() -> Result<(), Box<dyn Error>> {
19 let Some(url) = env::var("NANO_GET_BASIC_AUTH_URL").ok() else {
20 print_setup();
21 return Ok(());
22 };
23
24 let user = env_or_default("NANO_GET_BASIC_AUTH_USER", "demo-user");
25 let pass = env_or_default("NANO_GET_BASIC_AUTH_PASS", "demo-pass");
26
27 let challenge_driven = Client::builder()
28 .basic_auth(user.clone(), pass.clone())
29 .build()
30 .execute(Request::get(&url)?)?;
31
32 let preemptive = Client::builder()
33 .preemptive_basic_auth(user.clone(), pass.clone())
34 .build()
35 .execute(Request::get(&url)?)?;
36
37 let mut request = Request::get(&url)?;
38 request.basic_auth(user, pass)?;
39 let manual = request.execute()?;
40
41 println!("basic-auth example");
42 println!("challenge-driven status: {}", challenge_driven.status_code);
43 println!("preemptive status: {}", preemptive.status_code);
44 println!("request-level override status: {}", manual.status_code);
45
46 Ok(())
47}examples/proxy-and-proxy-auth/main.rs (line 36)
19fn main() -> Result<(), Box<dyn Error>> {
20 let Some(proxy_url) = env::var("NANO_GET_PROXY_URL").ok() else {
21 print_setup();
22 return Ok(());
23 };
24
25 let target_url = env_or_default("NANO_GET_PROXY_TARGET_URL", "http://example.com");
26 let proxy_user = env_or_default("NANO_GET_PROXY_AUTH_USER", "proxy-user");
27 let proxy_pass = env_or_default("NANO_GET_PROXY_AUTH_PASS", "proxy-pass");
28
29 let mut proxy = ProxyConfig::new(proxy_url)?;
30 proxy.add_header("X-Example-Proxy", "nano-get-demo")?;
31
32 let challenge_driven = Client::builder()
33 .proxy(proxy.clone())
34 .basic_proxy_auth(proxy_user.clone(), proxy_pass.clone())
35 .build()
36 .execute(Request::get(&target_url)?)?;
37
38 let preemptive = Client::builder()
39 .proxy(proxy.clone())
40 .preemptive_basic_proxy_auth(proxy_user.clone(), proxy_pass.clone())
41 .build()
42 .execute(Request::get(&target_url)?)?;
43
44 let mut manual = Request::get(&target_url)?;
45 manual.proxy_basic_auth(proxy_user, proxy_pass)?;
46 let manual_response = Client::builder().proxy(proxy).build().execute(manual)?;
47
48 println!("proxy-and-proxy-auth example");
49 println!("challenge-driven status: {}", challenge_driven.status_code);
50 println!("preemptive status: {}", preemptive.status_code);
51 println!(
52 "request-level override status: {}",
53 manual_response.status_code
54 );
55
56 Ok(())
57}Sourcepub fn execute_ref(&self, request: &Request) -> Result<Response, NanoGetError>
pub fn execute_ref(&self, request: &Request) -> Result<Response, NanoGetError>
Executes a borrowed Request by cloning it internally.
Sourcepub fn get<U: ToUrl>(&self, url: U) -> Result<String, NanoGetError>
pub fn get<U: ToUrl>(&self, url: U) -> Result<String, NanoGetError>
Performs a GET with the client’s default redirect policy and returns UTF-8 text.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for Client
impl !RefUnwindSafe for Client
impl Send for Client
impl Sync for Client
impl Unpin for Client
impl UnsafeUnpin for Client
impl !UnwindSafe for Client
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more