reqwest/lib.rs
1#![deny(missing_docs)]
2#![deny(missing_debug_implementations)]
3#![cfg_attr(docsrs, feature(doc_cfg))]
4#![cfg_attr(not(test), warn(unused_crate_dependencies))]
5#![cfg_attr(test, deny(warnings))]
6
7//! # reqwest-boring
8//!
9//! `reqwest-boring` is a fork of the original
10//! [reqwest](https://github.com/seanmonstar/reqwest) HTTP client by Sean McArthur
11//! and contributors. It uses [boring](https://crates.io/crates/boring), the Rust
12//! bindings to BoringSSL, as its default TLS layer, and
13//! [Quiche](https://github.com/cloudflare/quiche) for HTTP/3.
14//!
15//! The package is named `reqwest-boring`, while the Rust library remains
16//! `reqwest`, preserving the familiar [`Client`][client], request, response,
17//! and builder APIs. See [TLS](#tls) for backend-specific configuration.
18//!
19//! ```toml
20//! [dependencies]
21//! reqwest = { package = "reqwest-boring", version = "0.13.5", features = ["json"] }
22//! ```
23//!
24//! It handles many of the things that most people just expect an HTTP client
25//! to do for them.
26//!
27//! - Async and [blocking] Clients
28//! - Plain bodies, [JSON](#json), [urlencoded](#forms), [multipart]
29//! - Customizable [redirect policy](#redirect-policies)
30//! - HTTP [Proxies](#proxies)
31//! - Uses BoringSSL for [TLS](#tls) by default
32//! - Experimental HTTP/3 through Quiche
33//! - Cookies
34//!
35//! The [`reqwest::Client`][client] is asynchronous (requiring Tokio). For
36//! applications wishing to only make a few HTTP requests, the
37//! [`reqwest::blocking`](blocking) API may be more convenient.
38//!
39//! Additional learning resources include:
40//!
41//! - [The Rust Cookbook](https://rust-lang-nursery.github.io/rust-cookbook/web/clients.html)
42//! - [reqwest-boring Repository Examples](https://github.com/madeye/reqwest-boring/tree/master/examples)
43//!
44//! ## Making a GET request
45//!
46//! For a single request, you can use the [`get`][get] shortcut method.
47//!
48//! ```rust
49//! # async fn run() -> Result<(), reqwest::Error> {
50//! let body = reqwest::get("https://www.rust-lang.org")
51//! .await?
52//! .text()
53//! .await?;
54//!
55//! println!("body = {body:?}");
56//! # Ok(())
57//! # }
58//! ```
59//!
60//! **NOTE**: If you plan to perform multiple requests, it is best to create a
61//! [`Client`][client] and reuse it, taking advantage of keep-alive connection
62//! pooling.
63//!
64//! ## Making POST requests (or setting request bodies)
65//!
66//! There are several ways you can set the body of a request. The basic one is
67//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
68//! exact raw bytes of what the body should be. It accepts various types,
69//! including `String` and `Vec<u8>`. If you wish to pass a custom
70//! type, you can use the `reqwest::Body` constructors.
71//!
72//! ```rust
73//! # use reqwest::Error;
74//! #
75//! # async fn run() -> Result<(), Error> {
76//! let client = reqwest::Client::new();
77//! let res = client.post("http://httpbin.org/post")
78//! .body("the exact body that is sent")
79//! .send()
80//! .await?;
81//! # Ok(())
82//! # }
83//! ```
84//!
85//! ### Forms
86//!
87//! It's very common to want to send form data in a request body. This can be
88//! done with any type that can be serialized into form data.
89//!
90//! This can be an array of tuples, or a `HashMap`, or a custom type that
91//! implements [`Serialize`][serde].
92//!
93//! The feature `form` is required.
94//!
95//! ```rust
96//! # use reqwest::Error;
97//! #
98//! # #[cfg(feature = "form")]
99//! # async fn run() -> Result<(), Error> {
100//! // This will POST a body of `foo=bar&baz=quux`
101//! let params = [("foo", "bar"), ("baz", "quux")];
102//! let client = reqwest::Client::new();
103//! let res = client.post("http://httpbin.org/post")
104//! .form(¶ms)
105//! .send()
106//! .await?;
107//! # Ok(())
108//! # }
109//! ```
110//!
111//! ### JSON
112//!
113//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
114//! a similar fashion the `form` method. It can take any value that can be
115//! serialized into JSON.
116//!
117//! The feature `json` is required.
118//!
119//! ```rust
120//! # use reqwest::Error;
121//! # use std::collections::HashMap;
122//! #
123//! # #[cfg(feature = "json")]
124//! # async fn run() -> Result<(), Error> {
125//! // This will POST a body of `{"lang":"rust","body":"json"}`
126//! let mut map = HashMap::new();
127//! map.insert("lang", "rust");
128//! map.insert("body", "json");
129//!
130//! let client = reqwest::Client::new();
131//! let res = client.post("http://httpbin.org/post")
132//! .json(&map)
133//! .send()
134//! .await?;
135//! # Ok(())
136//! # }
137//! ```
138//!
139//! ## Redirect Policies
140//!
141//! By default, a `Client` will automatically handle HTTP redirects, having a
142//! maximum redirect chain of 10 hops. To customize this behavior, a
143//! [`redirect::Policy`][redirect] can be used with a `ClientBuilder`.
144//!
145//! ## Cookies
146//!
147//! The automatic storing and sending of session cookies can be enabled with
148//! the [`cookie_store`][ClientBuilder::cookie_store] method on `ClientBuilder`.
149//!
150//! ## Proxies
151//!
152//! **NOTE**: System proxies are enabled by default.
153//!
154//! System proxies look in environment variables to set HTTP or HTTPS proxies.
155//!
156//! `HTTP_PROXY` or `http_proxy` provide HTTP proxies for HTTP connections while
157//! `HTTPS_PROXY` or `https_proxy` provide HTTPS proxies for HTTPS connections.
158//! `ALL_PROXY` or `all_proxy` provide proxies for both HTTP and HTTPS connections.
159//! If both the all proxy and HTTP or HTTPS proxy variables are set the more specific
160//! HTTP or HTTPS proxies take precedence.
161//!
162//! These can be overwritten by adding a [`Proxy`] to `ClientBuilder`
163//! i.e. `let proxy = reqwest::Proxy::http("https://secure.example")?;`
164//! or disabled by calling `ClientBuilder::no_proxy()`.
165//!
166//! `socks` feature is required if you have configured socks proxy like this:
167//!
168//! ```bash
169//! export https_proxy=socks5://127.0.0.1:1086
170//! ```
171//!
172//! ## TLS
173//!
174//! On native targets, a `Client` uses BoringSSL through the `boring` and
175//! `tokio-boring` crates by default to connect to HTTPS destinations. The
176//! optional `native-tls` backend remains available. Browser WASM targets use
177//! the browser's TLS implementation.
178//!
179//! The `rustls` and `rustls-no-provider` features and the
180//! `tls_backend_rustls()` / `use_rustls_tls()` builder methods are compatibility
181//! aliases for BoringSSL. Preconfigured TLS methods retain their signatures but
182//! now accept `boring::ssl::SslConnector` instead of Rustls configuration
183//! objects. Configure HTTP/3 through the standard builder methods.
184//!
185//! Building BoringSSL requires a C/C++ compiler, CMake, Perl, and libclang.
186//! Windows builds additionally require LLVM and NASM.
187//!
188//! - Additional server certificates can be configured on a `ClientBuilder`
189//! with the [`Certificate`] type.
190//! - Client certificates can be added to a `ClientBuilder` with the
191//! [`Identity`] type.
192//! - Various parts of TLS can also be configured or even disabled on the
193//! `ClientBuilder`.
194//!
195//! See more details in the [`tls`] module.
196//!
197//! ## WASM
198//!
199//! The Client implementation automatically switches to the WASM one when the target_arch is wasm32,
200//! the usage is basically the same as the async api. Some of the features are disabled in wasm
201//! : [`tls`], [`cookie`], [`blocking`], as well as various `ClientBuilder` methods such as `timeout()` and `connector_layer()`.
202//!
203//! TLS and cookies are provided through the browser environment, so reqwest can issue TLS requests with cookies,
204//! but has limited configuration.
205//!
206//! ## Optional Features
207//!
208//! The following are a list of [Cargo features][cargo-features] that can be
209//! enabled or disabled:
210//!
211//! - **http2** *(enabled by default)*: Enables HTTP/2 support.
212//! - **default-tls** *(enabled by default)*: Provides HTTPS support through BoringSSL.
213//! - **boring**: Enables TLS functionality provided by BoringSSL.
214//! - **rustls**: Compatibility alias for `boring`.
215//! - **rustls-no-provider**: Compatibility alias for `boring`; no provider installation is needed.
216//! - **native-tls**: Enables TLS functionality provided by `native-tls`.
217//! - **native-tls-vendored**: Enables the `vendored` feature of `native-tls`.
218//! - **native-tls-no-alpn**: Enables `native-tls` without its `alpn` feature.
219//! - **native-tls-vendored-no-alpn**: Enables `native-tls-vendored` without its `alpn` feature.
220//! - **blocking**: Provides the [blocking][] client API.
221//! - **charset** *(enabled by default)*: Improved support for decoding text.
222//! - **cookies**: Provides cookie session support.
223//! - **gzip**: Provides response body gzip decompression.
224//! - **brotli**: Provides response body brotli decompression.
225//! - **zstd**: Provides response body zstd decompression.
226//! - **deflate**: Provides response body deflate decompression.
227//! - **query**: Provides query parameter serialization.
228//! - **form**: Provides form data serialization.
229//! - **json**: Provides serialization and deserialization for JSON bodies.
230//! - **multipart**: Provides functionality for multipart forms.
231//! - **stream**: Adds support for `futures::Stream`.
232//! - **socks**: Provides SOCKS5 proxy support.
233//! - **hickory-dns**: Enables a hickory-dns async resolver instead of default
234//! threadpool using `getaddrinfo`.
235//! - **system-proxy** *(enabled by default)*: Use Windows and macOS system
236//! proxy settings automatically.
237//!
238//! ## Unstable Features
239//!
240//! Some feature flags require additional opt-in by the application, by setting
241//! a `reqwest_unstable` flag.
242//!
243//! - **http3** *(unstable)*: Enables HTTP/3 through Quiche, sharing the same
244//! BoringSSL build as the default TLS backend.
245//!
246//! These features are unstable, and experimental. Details about them may be
247//! changed in patch releases.
248//!
249//! You can pass such a flag to the compiler via `.cargo/config`, or
250//! environment variables, such as:
251//!
252//! ```notrust
253//! RUSTFLAGS="--cfg reqwest_unstable" cargo build
254//! ```
255//!
256//! ## Attribution
257//!
258//! This fork retains the original reqwest project's MIT and Apache-2.0 licenses
259//! and copyright notices. Report fork-specific issues at
260//! [madeye/reqwest-boring](https://github.com/madeye/reqwest-boring/issues).
261//!
262//! [hyper]: https://hyper.rs
263//! [blocking]: ./blocking/index.html
264//! [client]: ./struct.Client.html
265//! [response]: ./struct.Response.html
266//! [get]: ./fn.get.html
267//! [builder]: ./struct.RequestBuilder.html
268//! [serde]: http://serde.rs
269//! [redirect]: crate::redirect
270//! [Proxy]: ./struct.Proxy.html
271//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section
272
273#[cfg(all(feature = "http3", not(reqwest_unstable)))]
274compile_error!(
275 "\
276 The `http3` feature is unstable, and requires the \
277 `RUSTFLAGS='--cfg reqwest_unstable'` environment variable to be set.\
278"
279);
280
281// Ignore `unused_crate_dependencies` warnings.
282// Used in many features that they're not worth making it optional.
283use futures_core as _;
284use sync_wrapper as _;
285
286macro_rules! if_wasm {
287 ($($item:item)*) => {$(
288 #[cfg(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none")))]
289 $item
290 )*}
291}
292
293macro_rules! if_hyper {
294 ($($item:item)*) => {$(
295 #[cfg(not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "none"))))]
296 $item
297 )*}
298}
299
300pub use http::header;
301pub use http::Method;
302pub use http::{StatusCode, Version};
303pub use url::Url;
304
305// universal mods
306#[macro_use]
307mod error;
308// TODO: remove `if_hyper` if wasm has been migrated to new config system.
309if_hyper! {
310 mod config;
311}
312mod into_url;
313mod response;
314
315pub use self::error::{Error, Result};
316pub use self::into_url::IntoUrl;
317pub use self::response::ResponseBuilderExt;
318
319/// Shortcut method to quickly make a `GET` request.
320///
321/// See also the methods on the [`reqwest::Response`](./struct.Response.html)
322/// type.
323///
324/// **NOTE**: This function creates a new internal `Client` on each call,
325/// and so should not be used if making many requests. Create a
326/// [`Client`](./struct.Client.html) instead.
327///
328/// # Examples
329///
330/// ```rust
331/// # async fn run() -> Result<(), reqwest::Error> {
332/// let body = reqwest::get("https://www.rust-lang.org").await?
333/// .text().await?;
334/// # Ok(())
335/// # }
336/// ```
337///
338/// # Errors
339///
340/// This function fails if:
341///
342/// - native TLS backend cannot be initialized
343/// - supplied `Url` cannot be parsed
344/// - there was an error while sending request
345/// - redirect limit was exhausted
346pub async fn get<T: IntoUrl>(url: T) -> crate::Result<Response> {
347 Client::builder().build()?.get(url).send().await
348}
349
350fn _assert_impls() {
351 fn assert_send<T: Send>() {}
352 fn assert_sync<T: Sync>() {}
353 fn assert_clone<T: Clone>() {}
354
355 assert_send::<Client>();
356 assert_sync::<Client>();
357 assert_clone::<Client>();
358
359 assert_send::<Request>();
360 assert_send::<RequestBuilder>();
361
362 #[cfg(not(target_arch = "wasm32"))]
363 {
364 assert_send::<Response>();
365 }
366
367 assert_send::<Error>();
368 assert_sync::<Error>();
369
370 assert_send::<Body>();
371 assert_sync::<Body>();
372}
373
374if_hyper! {
375 #[cfg(test)]
376 #[macro_use]
377 extern crate doc_comment;
378
379 #[cfg(test)]
380 doctest!("../README.md");
381
382 pub use self::async_impl::{
383 Body, Client, ClientBuilder, Request, RequestBuilder, Response, Upgraded,
384 };
385 pub use self::proxy::{Proxy,NoProxy};
386 #[cfg(feature = "__tls")]
387 // Re-exports, to be removed in a future release
388 pub use tls::{Certificate, Identity};
389 #[cfg(feature = "multipart")]
390 pub use self::async_impl::multipart;
391
392
393 mod async_impl;
394 #[cfg(feature = "blocking")]
395 pub mod blocking;
396 #[cfg(feature = "__rustls")]
397 mod boring_tls;
398 #[cfg(feature = "__rustls")]
399 mod boring_connector;
400 mod connect;
401 #[cfg(feature = "cookies")]
402 pub mod cookie;
403 pub mod dns;
404 mod proxy;
405 pub mod redirect;
406 pub mod retry;
407 #[cfg(feature = "__tls")]
408 pub mod tls;
409 mod util;
410
411 #[cfg(docsrs)]
412 pub use connect::uds::UnixSocketProvider;
413}
414
415if_wasm! {
416 mod wasm;
417 mod util;
418
419 pub use self::wasm::{Body, Client, ClientBuilder, Request, RequestBuilder, Response};
420 #[cfg(feature = "multipart")]
421 pub use self::wasm::multipart;
422}