minreq/lib.rs
1//! # Minreq
2//!
3//! Simple, minimal-dependency HTTP client. The library has a very
4//! minimal API, so you'll probably know everything you need to after
5//! reading a few examples.
6//!
7//! Note: as a minimal library, minreq has been written with the
8//! assumption that servers are well-behaved. This means that there is
9//! little error-correction for incoming data, which may cause some
10//! requests to fail unexpectedly. If you're writing an application or
11//! library that connects to servers you can't test beforehand,
12//! consider using a more robust library, such as
13//! [curl](https://crates.io/crates/curl).
14//!
15//! # Additional features
16//!
17//! Since the crate is supposed to be minimal in terms of
18//! dependencies, there are no default features, and optional
19//! functionality can be enabled by specifying features for `minreq`
20//! dependency in `Cargo.toml`:
21//!
22//! ```toml
23//! [dependencies]
24//! minreq = { version = "2.14.1", features = ["punycode"] }
25//! ```
26//!
27//! Below is the list of all available features.
28//!
29//! ## `https` or `https-rustls`
30//!
31//! This feature uses the (very good)
32//! [`rustls`](https://crates.io/crates/rustls) crate to secure the
33//! connection when needed. Note that if this feature is not enabled
34//! (and it is not by default), requests to urls that start with
35//! `https://` will fail and return a
36//! [`HttpsFeatureNotEnabled`](enum.Error.html#variant.HttpsFeatureNotEnabled)
37//! error. `https` was the name of this feature until the other https
38//! feature variants were added, and is now an alias for
39//! `https-rustls`.
40//!
41//! ## `https-rustls-probe`
42//!
43//! Like `https-rustls`, but also includes the
44//! [`rustls-native-certs`](https://crates.io/crates/rustls-native-certs)
45//! crate to auto-detect root certificates installed in common
46//! locations.
47//!
48//! ## `https-native`
49//!
50//! Like `https`, but uses
51//! [`tls-native`](https://crates.io/crates/native-tls) instead of
52//! `rustls`.
53//!
54//! ## `https-bundled`
55//!
56//! Like `https`, but uses a statically linked copy of the OpenSSL
57//! library (provided by
58//! [`openssl-sys`](https://crates.io/crates/openssl-sys) with
59//! features = "vendored"). This feature on its own doesn't provide
60//! any detection of where your root certificates are installed. They
61//! can be specified via the environment variables `SSL_CERT_FILE` or
62//! `SSL_CERT_DIR`.
63//!
64//! ## `https-bundled-probe`
65//!
66//! Like `https-bundled`, but also includes the
67//! [`openssl-probe`](https://crates.io/crates/openssl-probe) crate to
68//! auto-detect root certificates installed in common locations.
69//!
70//! ## `json-using-serde`
71//!
72//! This feature allows both serialize and deserialize JSON payload
73//! using the [`serde_json`](https://crates.io/crates/serde_json)
74//! crate.
75//!
76//! [`Request`](struct.Request.html) and
77//! [`Response`](struct.Response.html) expose
78//! [`with_json()`](struct.Request.html#method.with_json) and
79//! [`json()`](struct.Response.html#method.json) for constructing the
80//! struct from JSON and extracting the JSON body out, respectively.
81//!
82//! ## `punycode`
83//!
84//! This feature enables requests to non-ascii domains: the
85//! [`punycode`](https://crates.io/crates/punycode) crate is used to
86//! convert the non-ascii parts into their punycode representations
87//! before making the request. If you try to make a request to 㯙㯜㯙
88//! 㯟.net or i❤.ws for example, with this feature disabled (as it is
89//! by default), your request will fail with a
90//! [`PunycodeFeatureNotEnabled`](enum.Error.html#variant.PunycodeFeatureNotEnabled)
91//! error.
92//!
93//! ## `proxy`
94//!
95//! This feature enables HTTP proxy support. See [Proxy].
96//!
97//! ## `urlencoding`
98//!
99//! This feature enables percent-encoding for the URL resource when
100//! creating a request and any subsequently added parameters from
101//! [`Request::with_param`].
102//!
103//! # Examples
104//!
105//! ## Get
106//!
107//! This is a simple example of sending a GET request and printing out
108//! the response's body, status code, and reason phrase. The `?` are
109//! needed because the server could return invalid UTF-8 in the body,
110//! or something could go wrong during the download.
111//!
112//! ```
113//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
114//! let response = minreq::get("http://example.com").send()?;
115//! assert!(response.as_str()?.contains("</html>"));
116//! assert_eq!(200, response.status_code);
117//! assert_eq!("OK", response.reason_phrase);
118//! # Ok(()) }
119//! ```
120//!
121//! Note: you could change the `get` function to `head` or `put` or
122//! any other HTTP request method: the api is the same for all of
123//! them, it just changes what is sent to the server.
124//!
125//! ## Body (sending)
126//!
127//! To include a body, add `with_body("<body contents>")` before
128//! `send()`.
129//!
130//! ```
131//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
132//! let response = minreq::post("http://example.com")
133//! .with_body("Foobar")
134//! .send()?;
135//! # Ok(()) }
136//! ```
137//!
138//! ## Headers (sending)
139//!
140//! To add a header, add `with_header("Key", "Value")` before
141//! `send()`.
142//!
143//! ```
144//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
145//! let response = minreq::get("http://example.com")
146//! .with_header("Accept", "text/html")
147//! .send()?;
148//! # Ok(()) }
149//! ```
150//!
151//! ## Headers (receiving)
152//!
153//! Reading the headers sent by the servers is done via the
154//! [`headers`](struct.Response.html#structfield.headers) field of the
155//! [`Response`](struct.Response.html). Note: the header field names
156//! (that is, the *keys* of the `HashMap`) are all lowercase: this is
157//! because the names are case-insensitive according to the spec, and
158//! this unifies the casings for easier `get()`ing.
159//!
160//! ```
161//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
162//! let response = minreq::get("http://example.com").send()?;
163//! assert!(response.headers.get("content-type").unwrap().starts_with("text/html"));
164//! # Ok(()) }
165//! ```
166//!
167//! ## Timeouts
168//!
169//! To avoid timing out, or limit the request's response time, use
170//! `with_timeout(n)` before `send()`. The given value is in seconds.
171//!
172//! NOTE: There is no timeout by default.
173//!
174//! ```no_run
175//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
176//! let response = minreq::post("http://example.com")
177//! .with_timeout(10)
178//! .send()?;
179//! # Ok(()) }
180//! ```
181//!
182//! ## Proxy
183//!
184//! To use a proxy server, simply create a `Proxy` instance and use
185//! `.with_proxy()` on your request.
186//!
187//! Supported proxy formats are `host:port` and
188//! `user:password@proxy:host`. Only HTTP CONNECT proxies are
189//! supported at this time.
190//!
191//! ```no_run
192//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
193//! #[cfg(feature = "proxy")]
194//! {
195//! let proxy = minreq::Proxy::new("localhost:8080")?;
196//! let response = minreq::post("http://example.com")
197//! .with_proxy(proxy)
198//! .send()?;
199//! println!("{}", response.as_str()?);
200//! }
201//! # Ok(()) }
202//! ```
203//!
204//! # Timeouts
205//!
206//! By default, a request has no timeout. You can change this in two
207//! ways:
208//!
209//! - Use [`with_timeout`](struct.Request.html#method.with_timeout) on
210//! your request to set the timeout per-request like so:
211//! ```
212//! minreq::get("/").with_timeout(8).send();
213//! ```
214//! - Set the environment variable `MINREQ_TIMEOUT` to the desired
215//! amount of seconds until timeout. Ie. if you have a program called
216//! `foo` that uses minreq, and you want all the requests made by that
217//! program to timeout in 8 seconds, you launch the program like so:
218//! ```text,ignore
219//! $ MINREQ_TIMEOUT=8 ./foo
220//! ```
221//! Or add the following somewhere before the requests in the code.
222//! ```
223//! std::env::set_var("MINREQ_TIMEOUT", "8");
224//! ```
225//! If the timeout is set with `with_timeout`, the environment
226//! variable will be ignored.
227
228#![deny(missing_docs)]
229// Can't fix before an MSRV bump: std::io::Error::other was added in 1.74.
230#![allow(clippy::io_other_error)]
231// Can't fix before an MSRV bump: inlined format args were added after 1.48.0.
232#![allow(clippy::uninlined_format_args)]
233
234#[cfg(feature = "json-using-serde")]
235extern crate serde;
236#[cfg(feature = "json-using-serde")]
237extern crate serde_json;
238
239mod connection;
240mod error;
241mod http_url;
242#[cfg(feature = "proxy")]
243mod proxy;
244mod request;
245mod response;
246
247pub use error::*;
248#[cfg(feature = "proxy")]
249pub use proxy::*;
250pub use request::*;
251pub use response::*;