pub struct Agent { /* private fields */ }
Expand description
Agents keep state between requests.
By default, no state, such as cookies, is kept between requests. But by creating an agent as entry point for the request, we can keep a state.
§Example
let mut agent = ureq::agent();
agent
.post("http://example.com/post/login")
.send(b"my password")?;
let secret = agent
.get("http://example.com/get/my-protected-page")
.call()?
.body_mut()
.read_to_string()?;
println!("Secret is: {}", secret);
§About threads and cloning
Agent uses inner Arc
. Cloning an Agent results in an instance
that shares the same underlying connection pool and other state.
The connection pool contains an inner Mutex
which is (briefly)
held when borrowing a pooled connection, or returning a connection to the pool.
All request functions in ureq have a signature similar to this:
fn run(request: http::Request<impl AsSendBody>) -> Result<http::Response<Body>, Error> {
// <something>
}
It follows that:
- An Agent is borrowed for the duration of:
- Sending the request header (
http::Request
) - Sending the request body (
SendBody
) - Receiving the response header (
http::Response
)
- Sending the request header (
- The
Body
of the response is not bound to the lifetime of the Agent.
A response Body
can be streamed (for instance via Body::into_reader()
). The Body
implements Send
, which means it’s possible to read the response body on another thread than
the one that run the request. Behind the scenes, the Body
retains the connection to the remote
server and it is returned to the agent’s pool, once the Body instance (or reader) is dropped.
There is an asymmetry in that sending a request body will borrow the Agent instance, while receiving
the response body does not. This inconvencience is somewhat mitigated by that Agent::run()
(or
going via the methods such as Agent::get()
), borrows &self
, i.e. not exclusive mut
borrows.
That cloning the agent shares the connection pool is considered a feature. It is often useful to
retain a single pool for the entire process, while dispatching requests from different threads.
And if we want separate pools, we can create multiple agents via one of the constructors
(such as Agent::new_with_config()
).
Note that both Config::clone()
and Agent::clone()
are “cheap” meaning they should not
incur any heap allocation.
Implementations§
Source§impl Agent
impl Agent
Sourcepub fn new_with_defaults() -> Self
pub fn new_with_defaults() -> Self
Creates an agent with defaults.
Sourcepub fn new_with_config(config: Config) -> Self
pub fn new_with_config(config: Config) -> Self
Creates an agent with config.
Sourcepub fn config_builder() -> ConfigBuilder<AgentScope>
pub fn config_builder() -> ConfigBuilder<AgentScope>
Shortcut to reach a ConfigBuilder
This is the same as doing Config::builder()
.
Sourcepub fn with_parts(
config: Config,
connector: impl Connector,
resolver: impl Resolver,
) -> Self
pub fn with_parts( config: Config, connector: impl Connector, resolver: impl Resolver, ) -> Self
Creates an agent with a bespoke transport and resolver.
This is low level API that isn’t for regular use of ureq.
Access the shared cookie jar.
Used to persist and manipulate the cookies. The jar is shared between
all clones of the same Agent
, meaning you must drop the CookieJar
before using the agent, or end up with a deadlock.
use std::io::Write;
use std::fs::File;
let agent = ureq::agent();
// Cookies set by www.google.com are stored in agent.
agent.get("https://www.google.com/").call()?;
// Saves (persistent) cookies
let mut file = File::create("cookies.json")?;
let jar = agent.cookie_jar_lock();
jar.save_json(&mut file)?;
// Release the cookie jar to use agents again.
jar.release();
Sourcepub fn run(
&self,
request: Request<impl AsSendBody>,
) -> Result<Response<Body>, Error>
pub fn run( &self, request: Request<impl AsSendBody>, ) -> Result<Response<Body>, Error>
Run a http::Request<impl AsSendBody>
.
Used to execute http crate http::Request
directly on this agent.
§Example
use ureq::{http, Agent};
let agent: Agent = Agent::new_with_defaults();
let mut request =
http::Request::get("http://httpbin.org/get")
.body(())?;
let body = agent.run(request)?
.body_mut()
.read_to_string()?;
Sourcepub fn configure_request<S: AsSendBody>(
&self,
request: Request<S>,
) -> ConfigBuilder<HttpCrateScope<S>>
pub fn configure_request<S: AsSendBody>( &self, request: Request<S>, ) -> ConfigBuilder<HttpCrateScope<S>>
Alter the configuration for an http crate request.
Notice: It’s an error to configure a http::Request
using
one instance of Agent
and run using another instance. The
library does not currently detect this situation, but it is
not considered a breaking change if this is enforced in
the future.
Sourcepub fn get<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
pub fn get<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
Make a GET request using this agent.
Sourcepub fn post<T>(&self, uri: T) -> RequestBuilder<WithBody>
pub fn post<T>(&self, uri: T) -> RequestBuilder<WithBody>
Make a POST request using this agent.
Sourcepub fn put<T>(&self, uri: T) -> RequestBuilder<WithBody>
pub fn put<T>(&self, uri: T) -> RequestBuilder<WithBody>
Make a PUT request using this agent.
Sourcepub fn delete<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
pub fn delete<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
Make a DELETE request using this agent.
Sourcepub fn head<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
pub fn head<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
Make a HEAD request using this agent.
Sourcepub fn options<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
pub fn options<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
Make an OPTIONS request using this agent.
Sourcepub fn connect<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
pub fn connect<T>(&self, uri: T) -> RequestBuilder<WithoutBody>
Make a CONNECT request using this agent.
Sourcepub fn patch<T>(&self, uri: T) -> RequestBuilder<WithBody>
pub fn patch<T>(&self, uri: T) -> RequestBuilder<WithBody>
Make a PATCH request using this agent.