API changes for 2.0

* Remove Request::build
* All mutations on Request follow builder pattern

The previous `build()` on request was necessary because mutating
functions did not follow a proper builder pattern (taking `&mut self`
instead of `mut self`). With a proper builder pattern, the need for
`.build()` goes away.

* All Request body and call methods consume self

Anything which "executes" the request will now consume the `Request`
to produce a `Result<Response>`.

* Move all config from request to agent builder

Timeouts, redirect config, proxy settings and TLS config are now on
`AgentBuilder`.

* Rename max_pool_connections -> max_idle_connections
* Rename max_pool_connections_per_host ->  max_idle_connections_per_host

Consistent internal and external naming.

* Introduce new AgentConfig for static config created by builder.

`Agent` can be seen as having two parts. Static config and a mutable
shared state between all states. The static config goes into
`AgentConfig` and the mutable shared state into `AgentState`.

* Replace all use of `Default` for `new`.

Deriving or implementing `Default` makes for a secondary instantiation
API.  It is useful in some cases, but gets very confusing when there
is both `new` _and_ a `Default`. It's especially devious for derived
values where a reasonable default is not `0`, `false` or `None`.

* Remove feature native_tls, we want only native rustls.

This feature made for very clunky handling throughout the code. From a
security point of view, it's better to stick with one single TLS API.
Rustls recently got an official audit (very positive).

https://github.com/ctz/rustls/tree/master/audit

Rustls deliberately omits support for older, insecure TLS such as TLS
1.1 or RC4. This might be a problem for a user of ureq, but on balance
not considered important enough to keep native_tls.

* Remove auth and support for basic auth.

The API just wasn't enough. A future reintroduction should at least
also provide a `Bearer` mechanism and possibly more.

* Rename jar -> cookie_store
* Rename jar -> cookie_tin

Just make some field names sync up with the type.

* Drop "cookies" as default feature

The need for handling cookies is probably rare, let's not enable it by
default.

* Change all feature checks for "cookie" to "cookies"

The outward facing feature is "cookies" and I think it's better form
that the code uses the official feature name instead of the optional
library "cookies".

* Keep `set` on Agent level as well as AgentBuilder.

The idea is that an auth exchange might result in a header that need
to be set _after_ the agent has been built.
This commit is contained in:
Martin Algesten
2020-10-25 11:08:50 +01:00
parent 703ca41960
commit 1369c32351
24 changed files with 398 additions and 647 deletions

View File

@@ -130,15 +130,20 @@ pub use crate::resolve::Resolver;
pub use crate::response::Response;
// re-export
#[cfg(feature = "cookie")]
#[cfg(feature = "cookies")]
pub use cookie::Cookie;
#[cfg(feature = "json")]
pub use serde_json::{to_value as serde_to_value, Map as SerdeMap, Value as SerdeValue};
/// Creates an agent builder.
pub fn builder() -> AgentBuilder {
AgentBuilder::new()
}
/// Agents are used to keep state between requests.
pub fn agent() -> Agent {
#[cfg(not(test))]
return Agent::default();
return AgentBuilder::new().build();
#[cfg(test)]
return test::test_agent();
}
@@ -198,7 +203,9 @@ mod tests {
#[test]
fn connect_http_google() {
let resp = get("http://www.google.com/").call().unwrap();
let agent = Agent::new();
let resp = agent.get("http://www.google.com/").call().unwrap();
assert_eq!(
"text/html; charset=ISO-8859-1",
resp.header("content-type").unwrap()
@@ -207,9 +214,11 @@ mod tests {
}
#[test]
#[cfg(any(feature = "tls", feature = "native-tls"))]
#[cfg(feature = "tls")]
fn connect_https_google() {
let resp = get("https://www.google.com/").call().unwrap();
let agent = Agent::new();
let resp = agent.get("https://www.google.com/").call().unwrap();
assert_eq!(
"text/html; charset=ISO-8859-1",
resp.header("content-type").unwrap()
@@ -218,7 +227,7 @@ mod tests {
}
#[test]
#[cfg(any(feature = "tls", feature = "native-tls"))]
#[cfg(feature = "tls")]
fn connect_https_invalid_name() {
let result = get("https://example.com{REQUEST_URI}/").call();
assert!(matches!(result.unwrap_err(), Error::DnsFailed(_)));