use ucall::Client;use ucall::ClientCall;use ucall::ClientCallOptions;use ucall::ClientOptions;use ucall::Completed;use ucall::Response;1.0.0-rc.1 · 60202332
A Client submits calls without driving the network, and polls to drive them and collect what finished.
It holds up to connections connections, reusing them across calls, and carries up to pipelined_calls calls on each.
submit takes a ClientCall, which owns its URL, header lines, body and security until the call completes, and tags it with a u64 context.
A call admitted once completes exactly once, and a client already holding calls unretrieved calls refuses more with Status::Contended. take_completed drives every admitted call and fills a caller-provided buffer with finished ones, waiting up to its timeout for the first, and a zero timeout performs one nonblocking round. get, post, put, delete, patch and call submit one call and poll until it finishes, keeping the completions of other calls they retrieve meanwhile for the next take_completed, which hands those out first. ClientCall::options carries the call’s own ClientCallOptions: a timeout in place of the client’s, retries, redirect hops, security, and the client and server keys.
ClientOptions::max_response_bytes caps what a call buffers, failing it with Status::Overflow past the cap, and ClientOptions::log reports dials that fail every address, refused handshakes and refused redirects.
Host names resolve through the library’s own stub resolver, driven by the client’s polling, and connections race the answered addresses as Happy Eyeballs does.
Every received response is a Response, whatever its HTTP status, and only a failed exchange is an Error; Response::fields iterates its header fields as a request’s does.
A Response owns its received bytes and is Send, so it stays readable after its Client is dropped and may move to another thread.
Dropping the client cancels the calls still in flight and discards completions not yet retrieved.
API
StructClientAn HTTP client, created, submitted to, polled, and dropped on one thread.9
Allocations happen at construction, sized by the resolved call budget, and in header arrays
that grow to their largest call once; polling allocates nothing. Dropping it cancels the calls
in flight, while retrieved Responses stay readable.
use std::time::Duration;use ucall::*;let mut client = Client::new(ClientOptions { connections: 2, pipelined_calls: 4, ..Default::default() })?;for index in 0..8u64 { client.submit(ClientCall::post(format!("http://{address}/echo"), vec![index as u8]), index)?;}let mut completed: [Completed; 8] = Default::default();let mut answered = 0;while answered < 8 { for done in client.take_completed(&mut completed, Duration::from_secs(1))? { assert_eq!(done.response.as_ref().map(Response::body), Ok([done.context as u8].as_slice())); answered += 1; }}let response = client.post(format!("http://{address}/echo"), b"blocking".as_slice())?;drop(client);assert_eq!(response.body(), b"blocking");
newStarts a client; it holds no connection until the first call is polled.
take_completedDrives every admitted call on this thread and fills the front of completed with finished ones, waiting up to timeout for the first; zero performs one nonblocking round.
Answers the filled prefix, empty when nothing finished in time. Completions kept by
Client::call, Client::get or Client::post come first, without waiting.
callSubmits request and polls until it finishes, keeping other calls' completions for the next Client::take_completed.
A server whose event loop drives this client through that loop's polling, sharing its
engine; bound before the loop first polls, used only on its polling thread, and its
Client::take_completed only hands out what the loop finished.
event_loop
usize
Which of server's event loops; ignored without server.
Implements
Default
StructCompletedOne finished call: the context it was submitted with, and its response or failure.