Repository: sagebind/isahc
Pull request #281 (2020-12-22 20:18:13)

Remove structs from prelude module
Remove `Request`, `Response`, and `HttpClient` from the prelude since aren't really ubiquitous enough to deserve that position and glob-importing structs can be more confusing to beginners not sure where a type comes from.

Also clean up some doc examples to show imports to aid in understandability.

codecov[bot]: # [Codecov](https://codecov.io/gh/sagebind/isahc/pull/281?src=pr&el=h1) Report
> Merging [#281](https://codecov.io/gh/sagebind/isahc/pull/281?src=pr&el=desc) (230769d) into [master](https://codecov.io/gh/sagebind/isahc/commit/a76a873cc0fcde97593dc6267f08989689ba0319?el=desc) (a76a873) will **not change** coverage.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/sagebind/isahc/pull/281/graphs/tree.svg?width=650&height=150&src=pr&token=X5liRLDMl2)](https://codecov.io/gh/sagebind/isahc/pull/281?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master     #281   +/-   ##
=======================================
  Coverage   72.75%   72.75%           
=======================================
  Files          51       51           
  Lines        2734     2734           
=======================================
  Hits         1989     1989           
  Misses        745      745           
```


| [Impacted Files](https://codecov.io/gh/sagebind/isahc/pull/281?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [src/client.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-c3JjL2NsaWVudC5ycw==) | `66.22% <ø> (ø)` | |
| [src/config/mod.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-c3JjL2NvbmZpZy9tb2QucnM=) | `56.66% <ø> (ø)` | |
| [src/lib.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-c3JjL2xpYi5ycw==) | `73.68% <ø> (ø)` | |
| [src/request.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-c3JjL3JlcXVlc3QucnM=) | `28.00% <ø> (ø)` | |
| [tests/auth.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-dGVzdHMvYXV0aC5ycw==) | `100.00% <ø> (ø)` | |
| [tests/cookies.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-dGVzdHMvY29va2llcy5ycw==) | `100.00% <ø> (ø)` | |
| [tests/encoding.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-dGVzdHMvZW5jb2RpbmcucnM=) | `97.91% <ø> (ø)` | |
| [tests/headers.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-dGVzdHMvaGVhZGVycy5ycw==) | `100.00% <ø> (ø)` | |
| [tests/methods.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-dGVzdHMvbWV0aG9kcy5ycw==) | `100.00% <ø> (ø)` | |
| [tests/proxy.rs](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree#diff-dGVzdHMvcHJveHkucnM=) | `71.87% <ø> (ø)` | |
| ... and [5 more](https://codecov.io/gh/sagebind/isahc/pull/281/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/sagebind/isahc/pull/281?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/sagebind/isahc/pull/281?src=pr&el=footer). Last update [a76a873...230769d](https://codecov.io/gh/sagebind/isahc/pull/281?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/examples/badssl.rs b/examples/badssl.rs
index 8681691..5792344 100644
--- a/examples/badssl.rs
+++ b/examples/badssl.rs
@@ -1,7 +1,7 @@
 //! This example contains a number of manual tests against badssl.com
 //! demonstrating several dangerous SSL/TLS options.
 
-use isahc::{config::SslOption, prelude::*};
+use isahc::{config::SslOption, prelude::*, Request};
 
 fn main() {
     // accept expired cert
diff --git a/examples/client.rs b/examples/client.rs
index 2196329..f43d66d 100644
--- a/examples/client.rs
+++ b/examples/client.rs
@@ -1,7 +1,7 @@
 //! Another simple example that creates a custom HTTP client instance and sends
 //! a GET request with it instead of using the default client.
 
-use isahc::{config::RedirectPolicy, prelude::*};
+use isahc::{config::RedirectPolicy, prelude::*, HttpClient};
 use std::{
     io::{copy, stdout},
     time::Duration,
diff --git a/examples/cookies.rs b/examples/cookies.rs
index 584413c..3794851 100644
--- a/examples/cookies.rs
+++ b/examples/cookies.rs
@@ -1,7 +1,7 @@
 //! A simple example program that sends a GET request and then prints out all
 //! the cookies in the cookie jar.
 
-use isahc::{cookies::CookieJar, prelude::*};
+use isahc::{cookies::CookieJar, prelude::*, Request};
 use std::error::Error;
 
 fn main() -> Result<(), Box<dyn Error>> {
diff --git a/examples/http2.rs b/examples/http2.rs
index 39f02e4..7eb625c 100644
--- a/examples/http2.rs
+++ b/examples/http2.rs
@@ -1,7 +1,7 @@
 //! This example simply demonstrates HTTP/2 support by making a request that
 //! enforces usage of HTTP/2.
 
-use isahc::{config::VersionNegotiation, prelude::*};
+use isahc::{config::VersionNegotiation, prelude::*, Request};
 
 fn main() -> Result<(), isahc::Error> {
     let response = Request::get("https://nghttp2.org")
diff --git a/examples/parallel_requests.rs b/examples/parallel_requests.rs
index 12fa167..c3b3eed 100644
--- a/examples/parallel_requests.rs
+++ b/examples/parallel_requests.rs
@@ -6,7 +6,7 @@
 //!
 //! [rayon]: https://github.com/rayon-rs/rayon
 
-use isahc::prelude::*;
+use isahc::HttpClient;
 use rayon::prelude::*;
 use std::{env, time::Instant};
 
diff --git a/examples/progress.rs b/examples/progress.rs
index b69aac7..8b018d3 100644
--- a/examples/progress.rs
+++ b/examples/progress.rs
@@ -10,7 +10,7 @@
 //! [structopt]: https://github.com/TeXitoi/structopt
 
 use indicatif::{FormattedDuration, HumanBytes, ProgressBar, ProgressStyle};
-use isahc::prelude::*;
+use isahc::{prelude::*, Request};
 use std::io::Read;
 use structopt::StructOpt;
 
diff --git a/src/client.rs b/src/client.rs
index 55fafbe..0516dc4 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -56,8 +56,11 @@ static USER_AGENT: Lazy<String> = Lazy::new(|| {
 /// # Examples
 ///
 /// ```
-/// use isahc::config::{RedirectPolicy, VersionNegotiation};
-/// use isahc::prelude::*;
+/// use isahc::{
+///     config::{RedirectPolicy, VersionNegotiation},
+///     prelude::*,
+///     HttpClient,
+/// };
 /// use std::time::Duration;
 ///
 /// let client = HttpClient::builder()
@@ -126,8 +129,8 @@ impl HttpClientBuilder {
     /// # Examples
     ///
     /// ```no_run
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{prelude::*, HttpClient};
+    ///
     /// // Create a client with a cookie jar.
     /// let client = HttpClient::builder()
     ///     .cookies()
@@ -267,10 +270,9 @@ impl HttpClientBuilder {
     /// # Examples
     ///
     /// ```
-    /// # use isahc::config::*;
-    /// # use isahc::prelude::*;
-    /// # use std::time::Duration;
-    /// #
+    /// use isahc::{config::*, prelude::*, HttpClient};
+    /// use std::time::Duration;
+    ///
     /// let client = HttpClient::builder()
     ///     // Cache entries for 10 seconds.
     ///     .dns_cache(Duration::from_secs(10))
@@ -300,10 +302,9 @@ impl HttpClientBuilder {
     /// # Examples
     ///
     /// ```
-    /// # use isahc::config::ResolveMap;
-    /// # use isahc::prelude::*;
-    /// # use std::net::IpAddr;
-    /// #
+    /// use isahc::{config::ResolveMap, prelude::*, HttpClient};
+    /// use std::net::IpAddr;
+    ///
     /// let client = HttpClient::builder()
     ///     .dns_resolve(ResolveMap::new()
     ///         // Send requests for example.org on port 80 to 127.0.0.1.
@@ -333,8 +334,8 @@ impl HttpClientBuilder {
     /// # Examples
     ///
     /// ```
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{prelude::*, HttpClient};
+    ///
     /// let client = HttpClient::builder()
     ///     .default_header("some-header", "some-value")
     ///     .build()?;
@@ -377,8 +378,8 @@ impl HttpClientBuilder {
     /// Set default headers from a slice:
     ///
     /// ```
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{prelude::*, HttpClient};
+    ///
     /// let mut builder = HttpClient::builder()
     ///     .default_headers(&[
     ///         ("some-header", "value1"),
@@ -392,8 +393,8 @@ impl HttpClientBuilder {
     /// Using an existing header map:
     ///
     /// ```
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{prelude::*, HttpClient};
+    ///
     /// let mut headers = http::HeaderMap::new();
     /// headers.append("some-header".parse::<http::header::HeaderName>()?, "some-value".parse()?);
     ///
@@ -406,9 +407,9 @@ impl HttpClientBuilder {
     /// Using a hashmap:
     ///
     /// ```
-    /// # use isahc::prelude::*;
-    /// # use std::collections::HashMap;
-    /// #
+    /// use isahc::{prelude::*, HttpClient};
+    /// use std::collections::HashMap;
+    ///
     /// let mut headers = HashMap::new();
     /// headers.insert("some-header", "some-value");
     ///
@@ -556,7 +557,7 @@ impl<'a, K: Copy, V: Copy> HeaderPair<K, V> for &'a (K, V) {
 /// # Examples
 ///
 /// ```no_run
-/// use isahc::prelude::*;
+/// use isahc::{prelude::*, HttpClient};
 ///
 /// // Create a new client using reasonable defaults.
 /// let client = HttpClient::new()?;
@@ -575,6 +576,7 @@ impl<'a, K: Copy, V: Copy> HeaderPair<K, V> for &'a (K, V) {
 /// use isahc::{
 ///     config::{RedirectPolicy, VersionNegotiation},
 ///     prelude::*,
+///     HttpClient,
 /// };
 /// use std::time::Duration;
 ///
@@ -656,9 +658,9 @@ impl HttpClient {
     /// # Examples
     ///
     /// ```no_run
-    /// use isahc::prelude::*;
+    /// use isahc::{prelude::*, HttpClient};
     ///
-    /// # let client = HttpClient::new()?;
+    /// let client = HttpClient::new()?;
     /// let mut response = client.get("https://example.org")?;
     /// println!("{}", response.text()?);
     /// # Ok::<(), isahc::Error>(())
@@ -698,8 +700,9 @@ impl HttpClient {
     /// # Examples
     ///
     /// ```no_run
-    /// # use isahc::prelude::*;
-    /// # let client = HttpClient::new()?;
+    /// use isahc::{prelude::*, HttpClient};
+    ///
+    /// let client = HttpClient::new()?;
     /// let response = client.head("https://example.org")?;
     /// println!("Page size: {:?}", response.headers()["content-length"]);
     /// # Ok::<(), isahc::Error>(())
@@ -739,7 +742,7 @@ impl HttpClient {
     /// # Examples
     ///
     /// ```no_run
-    /// use isahc::prelude::*;
+    /// use isahc::{prelude::*, HttpClient};
     ///
     /// let client = HttpClient::new()?;
     ///
@@ -786,7 +789,7 @@ impl HttpClient {
     /// # Examples
     ///
     /// ```no_run
-    /// use isahc::prelude::*;
+    /// use isahc::{prelude::*, HttpClient};
     ///
     /// let client = HttpClient::new()?;
     ///
@@ -859,38 +862,35 @@ impl HttpClient {
 
     /// Send an HTTP request and return the HTTP response.
     ///
-    /// The response body is provided as a stream that may only be consumed
-    /// once.
-    ///
-    /// This client's configuration can be overridden for this request by
-    /// configuring the request using methods provided by the [`Configurable`]
-    /// trait.
-    ///
     /// Upon success, will return a [`Response`] containing the status code,
     /// response headers, and response body from the server. The [`Response`] is
     /// returned as soon as the HTTP response headers are received; the
     /// connection will remain open to stream the response body in real time.
-    /// Dropping the response body without fully consume it will close the
+    /// Dropping the response body without fully consuming it will close the
     /// connection early without downloading the rest of the response body.
     ///
-    /// _Note that the actual underlying socket connection isn't necessarily
-    /// closed on drop. It may remain open to be reused if pipelining is being
-    /// used, the connection is configured as `keep-alive`, and so on._
-    ///
-    /// Since the response body is streamed from the server, it may only be
-    /// consumed once. If you need to inspect the response body more than once,
-    /// you will have to either read it into memory or write it to a file.
+    /// The response body is provided as a stream that may only be consumed
+    /// once. If you need to inspect the response body more than once, you will
+    /// have to either read it into memory or write it to a file.
     ///
     /// The response body is not a direct stream from the server, but uses its
     /// own buffering mechanisms internally for performance. It is therefore
     /// undesirable to wrap the body in additional buffering readers.
     ///
-    /// To execute the request asynchronously, see [`HttpClient::send_async`].
+    /// _Note that the actual underlying socket connection isn't necessarily
+    /// closed on drop. It may remain open to be reused if pipelining is being
+    /// used, the connection is configured as `keep-alive`, and so on._
+    ///
+    /// This client's configuration can be overridden for this request by
+    /// configuring the request using methods provided by the [`Configurable`]
+    /// trait.
+    ///
+    /// To execute a request asynchronously, see [`HttpClient::send_async`].
     ///
     /// # Examples
     ///
     /// ```no_run
-    /// use isahc::prelude::*;
+    /// use isahc::{prelude::*, HttpClient, Request};
     ///
     /// let client = HttpClient::new()?;
     ///
@@ -951,13 +951,36 @@ impl HttpClient {
 
     /// Send an HTTP request and return the HTTP response asynchronously.
     ///
-    /// See [`HttpClient::send`] for further details.
+    /// Upon success, will return a [`Response`] containing the status code,
+    /// response headers, and response body from the server. The [`Response`] is
+    /// returned as soon as the HTTP response headers are received; the
+    /// connection will remain open to stream the response body in real time.
+    /// Dropping the response body without fully consuming it will close the
+    /// connection early without downloading the rest of the response body.
+    ///
+    /// The response body is provided as a stream that may only be consumed
+    /// once. If you need to inspect the response body more than once, you will
+    /// have to either read it into memory or write it to a file.
+    ///
+    /// The response body is not a direct stream from the server, but uses its
+    /// own buffering mechanisms internally for performance. It is therefore
+    /// undesirable to wrap the body in additional buffering readers.
+    ///
+    /// _Note that the actual underlying socket connection isn't necessarily
+    /// closed on drop. It may remain open to be reused if pipelining is being
+    /// used, the connection is configured as `keep-alive`, and so on._
+    ///
+    /// This client's configuration can be overridden for this request by
+    /// configuring the request using methods provided by the [`Configurable`]
+    /// trait.
+    ///
+    /// To execute a request synchronously, see [`HttpClient::send`].
     ///
     /// # Examples
     ///
     /// ```no_run
     /// # async fn run() -> Result<(), isahc::Error> {
-    /// use isahc::prelude::*;
+    /// use isahc::{prelude::*, HttpClient, Request};
     ///
     /// let client = HttpClient::new()?;
     ///
@@ -1158,10 +1181,10 @@ impl HttpClient {
 }
 
 impl crate::interceptor::Invoke for &HttpClient {
-    fn invoke<'a>(
-        &'a self,
+    fn invoke(
+        &self,
         mut request: Request<AsyncBody>,
-    ) -> crate::interceptor::InterceptorFuture<'a, Error> {
+    ) -> crate::interceptor::InterceptorFuture<'_, Error> {
         Box::pin(async move {
             // Set default user agent if not specified.
             request
diff --git a/src/config/mod.rs b/src/config/mod.rs
index cc16474..1364356 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -16,7 +16,7 @@
 use self::internal::SetOpt;
 use crate::auth::{Authentication, Credentials};
 use curl::easy::Easy2;
-use std::{iter::FromIterator, net::IpAddr, time::Duration};
+use std::{net::IpAddr, time::Duration};
 
 pub(crate) mod dial;
 pub(crate) mod dns;
@@ -62,7 +62,7 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```no_run
-    /// use isahc::prelude::*;
+    /// use isahc::{prelude::*, Request};
     /// use std::time::Duration;
     ///
     /// // This page is too slow and won't respond in time.
@@ -92,8 +92,12 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```
-    /// use isahc::config::VersionNegotiation;
-    /// use isahc::prelude::*;
+    /// use isahc::{
+    ///     config::VersionNegotiation,
+    ///     prelude::*,
+    ///     HttpClient,
+    /// };
+    ///
     /// // Never use anything newer than HTTP/1.x for this client.
     /// let http11_client = HttpClient::builder()
     ///     .version_negotiation(VersionNegotiation::http11())
@@ -116,8 +120,7 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```no_run
-    /// use isahc::config::RedirectPolicy;
-    /// use isahc::prelude::*;
+    /// use isahc::{config::RedirectPolicy, prelude::*, Request};
     ///
     /// // This URL redirects us to where we want to go.
     /// let response = Request::get("https://httpbin.org/redirect/1")
@@ -186,9 +189,12 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```
-    /// # use isahc::auth::*;
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{
+    ///     auth::{Authentication, Credentials},
+    ///     prelude::*,
+    ///     HttpClient,
+    /// };
+    ///
     /// let client = HttpClient::builder()
     ///     .authentication(Authentication::basic() | Authentication::digest())
     ///     .credentials(Credentials::new("clark", "qwerty"))
@@ -227,6 +233,8 @@ pub trait Configurable: internal::ConfigurableBase {
     /// use isahc::{
     ///     prelude::*,
     ///     config::NetworkInterface,
+    ///     HttpClient,
+    ///     Request,
     /// };
     /// use std::net::IpAddr;
     ///
@@ -274,6 +282,7 @@ pub trait Configurable: internal::ConfigurableBase {
     /// use isahc::{
     ///     config::Dialer,
     ///     prelude::*,
+    ///     Request,
     /// };
     ///
     /// # #[cfg(unix)]
@@ -289,6 +298,7 @@ pub trait Configurable: internal::ConfigurableBase {
     /// use isahc::{
     ///     config::Dialer,
     ///     prelude::*,
+    ///     Request,
     /// };
     /// use std::net::Ipv4Addr;
     ///
@@ -325,9 +335,8 @@ pub trait Configurable: internal::ConfigurableBase {
     /// Using `http://proxy:80` as a proxy:
     ///
     /// ```
-    /// # use isahc::auth::*;
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{prelude::*, HttpClient};
+    ///
     /// let client = HttpClient::builder()
     ///     .proxy(Some("http://proxy:80".parse()?))
     ///     .build()?;
@@ -337,8 +346,8 @@ pub trait Configurable: internal::ConfigurableBase {
     /// Explicitly disable the use of a proxy:
     ///
     /// ```
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{prelude::*, HttpClient};
+    ///
     /// let client = HttpClient::builder()
     ///     .proxy(None)
     ///     .build()?;
@@ -353,8 +362,8 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{prelude::*, HttpClient};
+    ///
     /// let client = HttpClient::builder()
     ///     // Disable proxy for specified hosts.
     ///     .proxy_blacklist(vec!["a.com", "b.org"])
@@ -366,7 +375,7 @@ pub trait Configurable: internal::ConfigurableBase {
         I: IntoIterator<Item = T>,
         T: Into<String>,
     {
-        self.configure(proxy::Blacklist::from_iter(hosts.into_iter().map(T::into)))
+        self.configure(hosts.into_iter().map(T::into).collect::<proxy::Blacklist>())
     }
 
     /// Set one or more HTTP authentication methods to attempt to use when
@@ -379,9 +388,12 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```
-    /// # use isahc::auth::*;
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{
+    ///     auth::{Authentication, Credentials},
+    ///     prelude::*,
+    ///     HttpClient,
+    /// };
+    ///
     /// let client = HttpClient::builder()
     ///     .proxy("http://proxy:80".parse::<http::Uri>()?)
     ///     .proxy_authentication(Authentication::basic())
@@ -427,8 +439,11 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```no_run
-    /// use isahc::config::{ClientCertificate, PrivateKey};
-    /// use isahc::prelude::*;
+    /// use isahc::{
+    ///     config::{ClientCertificate, PrivateKey},
+    ///     prelude::*,
+    ///     Request,
+    /// };
     ///
     /// let response = Request::get("localhost:3999")
     ///     .ssl_client_certificate(ClientCertificate::pem_file(
@@ -441,9 +456,12 @@ pub trait Configurable: internal::ConfigurableBase {
     /// ```
     ///
     /// ```
-    /// # use isahc::config::*;
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{
+    ///     config::{ClientCertificate, PrivateKey},
+    ///     prelude::*,
+    ///     HttpClient,
+    /// };
+    ///
     /// let client = HttpClient::builder()
     ///     .ssl_client_certificate(ClientCertificate::pem_file(
     ///         "client.pem",
@@ -470,9 +488,8 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```
-    /// # use isahc::config::*;
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{config::CaCertificate, prelude::*, HttpClient};
+    ///
     /// let client = HttpClient::builder()
     ///     .ssl_ca_certificate(CaCertificate::file("ca.pem"))
     ///     .build()?;
@@ -494,7 +511,7 @@ pub trait Configurable: internal::ConfigurableBase {
         I: IntoIterator<Item = T>,
         T: Into<String>,
     {
-        self.configure(ssl::Ciphers::from_iter(ciphers.into_iter().map(T::into)))
+        self.configure(ciphers.into_iter().map(T::into).collect::<ssl::Ciphers>())
     }
 
     /// Set various options for this request that control SSL/TLS behavior.
@@ -514,9 +531,8 @@ pub trait Configurable: internal::ConfigurableBase {
     /// # Examples
     ///
     /// ```
-    /// # use isahc::config::*;
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{config::SslOption, prelude::*, Request};
+    ///
     /// let response = Request::get("https://badssl.com")
     ///     .ssl_options(SslOption::DANGER_ACCEPT_INVALID_CERTS | SslOption::DANGER_ACCEPT_REVOKED_CERTS)
     ///     .body(())?
@@ -525,9 +541,8 @@ pub trait Configurable: internal::ConfigurableBase {
     /// ```
     ///
     /// ```
-    /// # use isahc::config::*;
-    /// # use isahc::prelude::*;
-    /// #
+    /// use isahc::{config::SslOption, prelude::*, HttpClient};
+    ///
     /// let client = HttpClient::builder()
     ///     .ssl_options(SslOption::DANGER_ACCEPT_INVALID_CERTS | SslOption::DANGER_ACCEPT_REVOKED_CERTS)
     ///     .build()?;
diff --git a/src/interceptor/context.rs b/src/interceptor/context.rs
index 44a40ca..187e6cb 100644
--- a/src/interceptor/context.rs
+++ b/src/interceptor/context.rs
@@ -33,5 +33,5 @@ impl fmt::Debug for Context<'_> {
 }
 
 pub(crate) trait Invoke {
-    fn invoke<'a>(&'a self, request: Request<AsyncBody>) -> InterceptorFuture<'a, Error>;
+    fn invoke(&self, request: Request<AsyncBody>) -> InterceptorFuture<'_, Error>;
 }
diff --git a/src/lib.rs b/src/lib.rs
index afc53b6..0126d35 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -51,7 +51,7 @@
 //! [`send`][RequestExt::send]:
 //!
 //! ```no_run
-//! use isahc::prelude::*;
+//! use isahc::{prelude::*, Request};
 //! use std::time::Duration;
 //!
 //! let response = Request::post("https://httpbin.org/post")
@@ -228,11 +228,9 @@
     unused,
     clippy::all
 )]
-
 // These lints suggest to use features not available in our MSRV.
 #![allow(clippy::manual_strip, clippy::match_like_matches_macro)]
 
-use http::{Request, Response};
 use once_cell::sync::Lazy;
 use std::convert::TryFrom;
 
@@ -270,18 +268,23 @@ pub use crate::{
     body::{AsyncBody, Body},
     client::{HttpClient, HttpClientBuilder, ResponseFuture},
     error::Error,
+    http::{request::Request, response::Response},
     metrics::Metrics,
     request::RequestExt,
     response::{AsyncReadResponseExt, ReadResponseExt, ResponseExt},
 };
 
-/// Re-export of the standard HTTP types.
+/// Re-export of HTTP types.
 pub use http;
 
-/// A "prelude" for importing common Isahc types.
+/// A "prelude" for importing commonly used Isahc types and traits.
+///
+/// The prelude re-exports most commonly used traits and macros from this crate.
 ///
 /// # Example
 ///
+/// Import the prelude with:
+///
 /// ```
 /// use isahc::prelude::*;
 /// ```
@@ -290,14 +293,10 @@ pub mod prelude {
     pub use crate::{
         config::Configurable,
         AsyncReadResponseExt,
-        HttpClient,
         ReadResponseExt,
         RequestExt,
         ResponseExt,
     };
-
-    #[doc(no_inline)]
-    pub use http::{Request, Response};
 }
 
 /// Send a GET request to the given URI.
@@ -370,26 +369,21 @@ where
 /// # Examples
 ///
 /// ```no_run
+/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
 /// use isahc::prelude::*;
 ///
-/// async fn run() {
-///     use futures_lite::AsyncReadExt;
-///     let client = HttpClient::new().unwrap();
+/// let mut response = isahc::post_async("https://httpbin.org/post", r#"{
+///     "speed": "fast",
+///     "cool_name": true
+/// }"#).await?;
 ///
-///     let mut response = client.post_async("https://httpbin.org/post", r#"{
-///         "speed": "fast",
-///         "cool_name": true
-///     }"#).await.unwrap();
+/// let mut body: Vec<u8> = vec![];
+/// response.copy_to(&mut body).await?;
 ///
-///     let mut body: Vec<u8> = vec![];
-///     let mut reader = futures_lite::io::BufReader::new(response.body_mut());
-///     reader.read_to_end(&mut body).await.unwrap();
-///
-///     let msg: serde_json::Value = serde_json::from_slice(&body).unwrap();
-///     println!("{}", msg);
-/// }
+/// let msg: serde_json::Value = serde_json::from_slice(&body)?;
+/// println!("{}", msg);
+/// # Ok(()) }
 /// ```
-///
 pub fn post_async<U, B>(uri: U, body: B) -> ResponseFuture<'static>
 where
     http::Uri: TryFrom<U>,
diff --git a/src/request.rs b/src/request.rs
index d222de9..52201d1 100644
--- a/src/request.rs
+++ b/src/request.rs
@@ -22,7 +22,7 @@ pub trait RequestExt<T> {
     /// # Examples
     ///
     /// ```no_run
-    /// use isahc::prelude::*;
+    /// use isahc::{prelude::*, Request};
     ///
     /// let response = Request::post("https://httpbin.org/post")
     ///     .header("Content-Type", "application/json")


Test patch:
diff --git a/tests/auth.rs b/tests/auth.rs
index 99373c1..8d0cd02 100644
--- a/tests/auth.rs
+++ b/tests/auth.rs
@@ -1,4 +1,4 @@
-use isahc::{auth::*, prelude::*};
+use isahc::{auth::*, prelude::*, Request};
 use testserver::mock;
 
 #[test]
diff --git a/tests/cookies.rs b/tests/cookies.rs
index 495211b..6be882d 100644
--- a/tests/cookies.rs
+++ b/tests/cookies.rs
@@ -1,6 +1,6 @@
 #![cfg(feature = "cookies")]
 
-use isahc::{cookies::CookieJar, prelude::*};
+use isahc::{cookies::CookieJar, prelude::*, HttpClient};
 use testserver::mock;
 
 #[test]
diff --git a/tests/encoding.rs b/tests/encoding.rs
index 09f7fb3..cb44ecd 100644
--- a/tests/encoding.rs
+++ b/tests/encoding.rs
@@ -2,7 +2,7 @@ use flate2::{
     read::{DeflateEncoder, GzEncoder},
     Compression,
 };
-use isahc::prelude::*;
+use isahc::{prelude::*, Request};
 use std::io::Read;
 use testserver::mock;
 
diff --git a/tests/headers.rs b/tests/headers.rs
index 4281653..0c0d85f 100644
--- a/tests/headers.rs
+++ b/tests/headers.rs
@@ -1,4 +1,4 @@
-use isahc::prelude::*;
+use isahc::{prelude::*, HttpClient, Request};
 use testserver::mock;
 
 #[test]
diff --git a/tests/methods.rs b/tests/methods.rs
index bf8a9df..c5932a7 100644
--- a/tests/methods.rs
+++ b/tests/methods.rs
@@ -1,4 +1,4 @@
-use isahc::prelude::*;
+use isahc::{prelude::*, Request};
 use testserver::mock;
 
 #[test]
diff --git a/tests/metrics.rs b/tests/metrics.rs
index f34c1c1..6fb6690 100644
--- a/tests/metrics.rs
+++ b/tests/metrics.rs
@@ -1,4 +1,4 @@
-use isahc::prelude::*;
+use isahc::{prelude::*, HttpClient, Request};
 use std::{io, time::Duration};
 use testserver::mock;
 
@@ -19,7 +19,7 @@ fn enabling_metrics_causes_metrics_to_be_collected() {
         body: "hello world",
     };
 
-    let client = isahc::HttpClient::builder().metrics(true).build().unwrap();
+    let client = HttpClient::builder().metrics(true).build().unwrap();
 
     let mut response = client
         .send(Request::post(m.url()).body("hello server").unwrap())
diff --git a/tests/proxy.rs b/tests/proxy.rs
index 5d3648c..8c4ff03 100644
--- a/tests/proxy.rs
+++ b/tests/proxy.rs
@@ -1,4 +1,4 @@
-use isahc::prelude::*;
+use isahc::{prelude::*, Request};
 use testserver::{mock, socks4::Socks4Server};
 
 #[test]
diff --git a/tests/redirects.rs b/tests/redirects.rs
index 2760d35..7866069 100644
--- a/tests/redirects.rs
+++ b/tests/redirects.rs
@@ -1,4 +1,4 @@
-use isahc::{config::RedirectPolicy, prelude::*, Body};
+use isahc::{config::RedirectPolicy, prelude::*, Body, HttpClient, Request};
 use test_case::test_case;
 use testserver::mock;
 
diff --git a/tests/request_body.rs b/tests/request_body.rs
index 34b147b..3159c76 100644
--- a/tests/request_body.rs
+++ b/tests/request_body.rs
@@ -1,5 +1,5 @@
 use futures_lite::{future::block_on, AsyncRead};
-use isahc::{prelude::*, AsyncBody, Body};
+use isahc::{prelude::*, AsyncBody, Body, Request};
 use std::{
     error::Error,
     io::{self, Read},
diff --git a/tests/timeouts.rs b/tests/timeouts.rs
index 08d59b1..1e79c32 100644
--- a/tests/timeouts.rs
+++ b/tests/timeouts.rs
@@ -1,4 +1,4 @@
-use isahc::prelude::*;
+use isahc::{prelude::*, Request};
 use std::{
     io::{self, Cursor, Read},
     thread,
diff --git a/tests/unix.rs b/tests/unix.rs
index 2af6c45..8f65f77 100644
--- a/tests/unix.rs
+++ b/tests/unix.rs
@@ -1,6 +1,6 @@
 #![cfg(unix)]
 
-use isahc::{config::Dialer, prelude::*};
+use isahc::{config::Dialer, prelude::*, Request};
 use std::{
     io::{self, Write},
     os::unix::net::UnixListener,