Skip to main content

Client

Struct Client 

Source
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

Source

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
Hide additional 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}
Source

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
Hide additional 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}
Source

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
Hide additional 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}
Source

pub fn execute_ref(&self, request: &Request) -> Result<Response, NanoGetError>

Executes a borrowed Request by cloning it internally.

Source

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.

Source

pub fn get_bytes<U: ToUrl>(&self, url: U) -> Result<Vec<u8>, NanoGetError>

Performs a GET with the client’s default redirect policy and returns raw bytes.

Source

pub fn head<U: ToUrl>(&self, url: U) -> Result<Response, NanoGetError>

Performs a HEAD with the client’s default redirect policy.

Trait Implementations§

Source§

impl Clone for Client

Source§

fn clone(&self) -> Client

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Default for Client

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.