1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
//! A truly platform-native Rust HTTP client library.
//!
//! ## Overview
//!
//! Nyquest aims to fully utilize the functionality provided by existing HTTP libraries or built-in
//! HTTP stacks on various platforms, while providing a consistent and idiomatic API for Rust
//! developers. Based on the backend implementation, your application automatically benefits[^1] from
//!
//! - Core HTTP stack features
//! - Transparent response caching and session cookies
//! - Global proxy settings
//! - Hassle-free TLS
//! - Fewer Rust crate dependencies
//! - Smaller binary size
//! - System-managed security updates
//! - Better power management
//!
//! At the cost of
//!
//! - Abstraction and interop overhead
//! - Limited control over the underlying HTTP requests
//! - Potential inconsistencies in the behavior of different backends
//! - Link-time and runtime dependency to some native libraries (e.g. `libcurl` on Linux)
//!
//! ## The `nyquest` crate
//!
//! The `nyquest` crate is the main user interface of Nyquest HTTP clients for both library authors
//! and end users. It serves as a facade without actual implementations, and calls into the
//! preregistered backends via [`nyquest-interface`].
//!
//! ### Backends
//!
//! Before using `nyquest`, you need to register a backend. The simplest way is to use
//! [`nyquest-preset`] by adding it to your dependencies and calling the `register` function at
//! the beginning of your program. This will automatically select the appropriate backend based on
//! the target platform. Once registered, any transitive dependencies that use `nyquest` will also
//! pick up the registered backend given the version constraints of [`nyquest-interface`] are
//! compatible.
//!
//! You may want to handle the backends individually for more control. Currently, the
//! following backends are available:
//!
//! - [`nyquest-backend-winrt`](https://docs.rs/nyquest-backend-winrt)
//! - [`nyquest-backend-nsurlsession`](https://docs.rs/nyquest-backend-nsurlsession)
//! - [`nyquest-backend-curl`](https://docs.rs/nyquest-backend-curl)
//!
//! Refer to our [repository](https://github.com/bdbai/nyquest) for up-to-date
//! information on the backends.
//!
//! ### Threading and `async` Support
//!
//! Nyquest requires backends to be thread-safe in general. The "blocking" clients enabled by the
//! `blocking` feature can be used in any thread safely. The "async" clients enabled by the `async`
//! feature are thread-safe as well, and additionally the `Future`s they return are `Send`.
//!
//! An "async" client should not require an event loop or an async runtime available in the current
//! thread, allowing you to mix and match with any async runtimes. Under the hood, there may be
//! some threads managed by the backend crates or the HTTP stacks running in the background. With
//! that said, a backend implementation that would normally spin up its own event loop may decide
//! to reuse the one in the current thread if it is available, which may require certain features
//! of the runtime to be enabled.
//!
//! ## Usage
//!
//! Assume a backend with `async` feature has been registered. For a simple GET request, you can
//! use the shortcut `get` function:
//!
//! ```no_run
//! # async fn run() -> Result<(), nyquest::Error> {
//! let body = nyquest::r#async::get("https://example.com").await?.text().await?;
//! println!("{body}");
//! # Ok(())
//! # }
//! ``````
//!
//! **Note**: If you plan to perform multiple requests, it is best to create a Client and reuse
//! it, taking advantage of thread reuse and potential keep-alive connection pooling.
//!
//! To send a POST request with urlencoded form data, use the `body_form!` macro to build the body:
//!
//! ```no_run
//! use nyquest::{body_form, ClientBuilder};
//! use nyquest::r#async::Request;
//! # async fn run() -> Result<(), nyquest::Error> {
//! let client = ClientBuilder::default().build_async().await?;
//! let body = Request::post("http://httpbin.org/post").with_body(body_form! {
//! "key1" => "value1",
//! "key2" => "value2",
//! });
//! let resp = client.request(body).await?;
//! # Ok(())
//! # }
//! ```
//!
//! For blocking requests, simply change `r#async` to `blocking` and remove `.await`s in the above
//! examples.
//!
//! ## Features
//!
//! - `async`: Enable async support. The registered backend must implement the async interface
//! to compile.
//! - `async-stream`: Enable async support and streaming upload/download. The registered backend
//! must implement the async-stream interface to compile.
//! - `blocking`: Enable blocking support. The registered backend must implement the blocking
//! interface to compile.
//! - `blocking-stream`: Enable blocking support and streaming upload/download. The registered
//! backend must implement the blocking-stream interface to compile.
//! - `multipart`: Enable multipart form support. The registered backend must implement the
//! multipart interface to compile.
//! - `json`: Enable JSON request/response shorthand methods.
//!
//! [^1]: Subject to the backend's capability.
//!
//! [`nyquest-interface`]: https://docs.rs/nyquest-interface
//! [`nyquest-preset`]: https://docs.rs/nyquest-preset
//!
pub use BlockingClient;
pub use Body;
pub use ;
pub use ClientBuilder;
pub use ;
pub use r#AsyncClient;
pub use ;
pub use StatusCode;