wreq-rb 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Cargo.lock +2688 -0
- data/Cargo.toml +6 -0
- data/README.md +179 -0
- data/ext/wreq_rb/Cargo.toml +39 -0
- data/ext/wreq_rb/extconf.rb +22 -0
- data/ext/wreq_rb/src/client.rs +565 -0
- data/ext/wreq_rb/src/error.rs +25 -0
- data/ext/wreq_rb/src/lib.rs +20 -0
- data/ext/wreq_rb/src/response.rs +132 -0
- data/lib/wreq-rb/version.rb +5 -0
- data/lib/wreq-rb.rb +17 -0
- data/patches/0001-add-transfer-size-tracking.patch +292 -0
- data/vendor/wreq/Cargo.toml +306 -0
- data/vendor/wreq/LICENSE +202 -0
- data/vendor/wreq/README.md +122 -0
- data/vendor/wreq/examples/cert_store.rs +77 -0
- data/vendor/wreq/examples/connect_via_lower_priority_tokio_runtime.rs +258 -0
- data/vendor/wreq/examples/emulation.rs +118 -0
- data/vendor/wreq/examples/form.rs +14 -0
- data/vendor/wreq/examples/http1_websocket.rs +37 -0
- data/vendor/wreq/examples/http2_websocket.rs +45 -0
- data/vendor/wreq/examples/json_dynamic.rs +41 -0
- data/vendor/wreq/examples/json_typed.rs +47 -0
- data/vendor/wreq/examples/keylog.rs +16 -0
- data/vendor/wreq/examples/request_with_emulation.rs +115 -0
- data/vendor/wreq/examples/request_with_interface.rs +37 -0
- data/vendor/wreq/examples/request_with_local_address.rs +16 -0
- data/vendor/wreq/examples/request_with_proxy.rs +13 -0
- data/vendor/wreq/examples/request_with_redirect.rs +22 -0
- data/vendor/wreq/examples/request_with_version.rs +15 -0
- data/vendor/wreq/examples/tor_socks.rs +24 -0
- data/vendor/wreq/examples/unix_socket.rs +33 -0
- data/vendor/wreq/src/client/body.rs +304 -0
- data/vendor/wreq/src/client/conn/conn.rs +231 -0
- data/vendor/wreq/src/client/conn/connector.rs +549 -0
- data/vendor/wreq/src/client/conn/http.rs +1023 -0
- data/vendor/wreq/src/client/conn/proxy/socks.rs +233 -0
- data/vendor/wreq/src/client/conn/proxy/tunnel.rs +260 -0
- data/vendor/wreq/src/client/conn/proxy.rs +39 -0
- data/vendor/wreq/src/client/conn/tls_info.rs +98 -0
- data/vendor/wreq/src/client/conn/uds.rs +44 -0
- data/vendor/wreq/src/client/conn/verbose.rs +149 -0
- data/vendor/wreq/src/client/conn.rs +323 -0
- data/vendor/wreq/src/client/core/body/incoming.rs +485 -0
- data/vendor/wreq/src/client/core/body/length.rs +118 -0
- data/vendor/wreq/src/client/core/body.rs +34 -0
- data/vendor/wreq/src/client/core/common/buf.rs +149 -0
- data/vendor/wreq/src/client/core/common/rewind.rs +141 -0
- data/vendor/wreq/src/client/core/common/watch.rs +76 -0
- data/vendor/wreq/src/client/core/common.rs +3 -0
- data/vendor/wreq/src/client/core/conn/http1.rs +342 -0
- data/vendor/wreq/src/client/core/conn/http2.rs +307 -0
- data/vendor/wreq/src/client/core/conn.rs +11 -0
- data/vendor/wreq/src/client/core/dispatch.rs +299 -0
- data/vendor/wreq/src/client/core/error.rs +435 -0
- data/vendor/wreq/src/client/core/ext.rs +201 -0
- data/vendor/wreq/src/client/core/http1.rs +178 -0
- data/vendor/wreq/src/client/core/http2.rs +483 -0
- data/vendor/wreq/src/client/core/proto/h1/conn.rs +988 -0
- data/vendor/wreq/src/client/core/proto/h1/decode.rs +1170 -0
- data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +684 -0
- data/vendor/wreq/src/client/core/proto/h1/encode.rs +580 -0
- data/vendor/wreq/src/client/core/proto/h1/io.rs +879 -0
- data/vendor/wreq/src/client/core/proto/h1/role.rs +694 -0
- data/vendor/wreq/src/client/core/proto/h1.rs +104 -0
- data/vendor/wreq/src/client/core/proto/h2/client.rs +650 -0
- data/vendor/wreq/src/client/core/proto/h2/ping.rs +539 -0
- data/vendor/wreq/src/client/core/proto/h2.rs +379 -0
- data/vendor/wreq/src/client/core/proto/headers.rs +138 -0
- data/vendor/wreq/src/client/core/proto.rs +58 -0
- data/vendor/wreq/src/client/core/rt/bounds.rs +57 -0
- data/vendor/wreq/src/client/core/rt/timer.rs +150 -0
- data/vendor/wreq/src/client/core/rt/tokio.rs +99 -0
- data/vendor/wreq/src/client/core/rt.rs +25 -0
- data/vendor/wreq/src/client/core/upgrade.rs +267 -0
- data/vendor/wreq/src/client/core.rs +16 -0
- data/vendor/wreq/src/client/emulation.rs +161 -0
- data/vendor/wreq/src/client/http/client/error.rs +142 -0
- data/vendor/wreq/src/client/http/client/exec.rs +29 -0
- data/vendor/wreq/src/client/http/client/extra.rs +77 -0
- data/vendor/wreq/src/client/http/client/lazy.rs +79 -0
- data/vendor/wreq/src/client/http/client/pool.rs +1105 -0
- data/vendor/wreq/src/client/http/client/util.rs +104 -0
- data/vendor/wreq/src/client/http/client.rs +1003 -0
- data/vendor/wreq/src/client/http/future.rs +99 -0
- data/vendor/wreq/src/client/http.rs +1629 -0
- data/vendor/wreq/src/client/layer/config/options.rs +156 -0
- data/vendor/wreq/src/client/layer/config.rs +116 -0
- data/vendor/wreq/src/client/layer/cookie.rs +161 -0
- data/vendor/wreq/src/client/layer/decoder.rs +139 -0
- data/vendor/wreq/src/client/layer/redirect/future.rs +270 -0
- data/vendor/wreq/src/client/layer/redirect/policy.rs +63 -0
- data/vendor/wreq/src/client/layer/redirect.rs +145 -0
- data/vendor/wreq/src/client/layer/retry/classify.rs +105 -0
- data/vendor/wreq/src/client/layer/retry/scope.rs +51 -0
- data/vendor/wreq/src/client/layer/retry.rs +151 -0
- data/vendor/wreq/src/client/layer/timeout/body.rs +233 -0
- data/vendor/wreq/src/client/layer/timeout/future.rs +90 -0
- data/vendor/wreq/src/client/layer/timeout.rs +177 -0
- data/vendor/wreq/src/client/layer.rs +15 -0
- data/vendor/wreq/src/client/multipart.rs +717 -0
- data/vendor/wreq/src/client/request.rs +818 -0
- data/vendor/wreq/src/client/response.rs +534 -0
- data/vendor/wreq/src/client/ws/json.rs +99 -0
- data/vendor/wreq/src/client/ws/message.rs +453 -0
- data/vendor/wreq/src/client/ws.rs +714 -0
- data/vendor/wreq/src/client.rs +27 -0
- data/vendor/wreq/src/config.rs +140 -0
- data/vendor/wreq/src/cookie.rs +579 -0
- data/vendor/wreq/src/dns/gai.rs +249 -0
- data/vendor/wreq/src/dns/hickory.rs +78 -0
- data/vendor/wreq/src/dns/resolve.rs +180 -0
- data/vendor/wreq/src/dns.rs +69 -0
- data/vendor/wreq/src/error.rs +502 -0
- data/vendor/wreq/src/ext.rs +398 -0
- data/vendor/wreq/src/hash.rs +143 -0
- data/vendor/wreq/src/header.rs +506 -0
- data/vendor/wreq/src/into_uri.rs +187 -0
- data/vendor/wreq/src/lib.rs +586 -0
- data/vendor/wreq/src/proxy/mac.rs +82 -0
- data/vendor/wreq/src/proxy/matcher.rs +806 -0
- data/vendor/wreq/src/proxy/uds.rs +66 -0
- data/vendor/wreq/src/proxy/win.rs +31 -0
- data/vendor/wreq/src/proxy.rs +569 -0
- data/vendor/wreq/src/redirect.rs +575 -0
- data/vendor/wreq/src/retry.rs +198 -0
- data/vendor/wreq/src/sync.rs +129 -0
- data/vendor/wreq/src/tls/conn/cache.rs +123 -0
- data/vendor/wreq/src/tls/conn/cert_compression.rs +125 -0
- data/vendor/wreq/src/tls/conn/ext.rs +82 -0
- data/vendor/wreq/src/tls/conn/macros.rs +34 -0
- data/vendor/wreq/src/tls/conn/service.rs +138 -0
- data/vendor/wreq/src/tls/conn.rs +681 -0
- data/vendor/wreq/src/tls/keylog/handle.rs +64 -0
- data/vendor/wreq/src/tls/keylog.rs +99 -0
- data/vendor/wreq/src/tls/options.rs +464 -0
- data/vendor/wreq/src/tls/x509/identity.rs +122 -0
- data/vendor/wreq/src/tls/x509/parser.rs +71 -0
- data/vendor/wreq/src/tls/x509/store.rs +228 -0
- data/vendor/wreq/src/tls/x509.rs +68 -0
- data/vendor/wreq/src/tls.rs +154 -0
- data/vendor/wreq/src/trace.rs +55 -0
- data/vendor/wreq/src/util.rs +122 -0
- data/vendor/wreq/tests/badssl.rs +228 -0
- data/vendor/wreq/tests/brotli.rs +350 -0
- data/vendor/wreq/tests/client.rs +1098 -0
- data/vendor/wreq/tests/connector_layers.rs +227 -0
- data/vendor/wreq/tests/cookie.rs +306 -0
- data/vendor/wreq/tests/deflate.rs +347 -0
- data/vendor/wreq/tests/emulation.rs +260 -0
- data/vendor/wreq/tests/gzip.rs +347 -0
- data/vendor/wreq/tests/layers.rs +261 -0
- data/vendor/wreq/tests/multipart.rs +165 -0
- data/vendor/wreq/tests/proxy.rs +438 -0
- data/vendor/wreq/tests/redirect.rs +629 -0
- data/vendor/wreq/tests/retry.rs +135 -0
- data/vendor/wreq/tests/support/delay_server.rs +117 -0
- data/vendor/wreq/tests/support/error.rs +16 -0
- data/vendor/wreq/tests/support/layer.rs +183 -0
- data/vendor/wreq/tests/support/mod.rs +9 -0
- data/vendor/wreq/tests/support/server.rs +232 -0
- data/vendor/wreq/tests/timeouts.rs +281 -0
- data/vendor/wreq/tests/unix_socket.rs +135 -0
- data/vendor/wreq/tests/upgrade.rs +98 -0
- data/vendor/wreq/tests/zstd.rs +559 -0
- metadata +225 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
#![deny(unused)]
|
|
2
|
+
#![deny(unsafe_code)]
|
|
3
|
+
#![deny(missing_docs)]
|
|
4
|
+
#![cfg_attr(docsrs, feature(doc_cfg))]
|
|
5
|
+
#![cfg_attr(test, deny(warnings))]
|
|
6
|
+
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
|
7
|
+
|
|
8
|
+
//! # wreq
|
|
9
|
+
//!
|
|
10
|
+
//! An ergonomic all-in-one HTTP client for browser emulation with TLS, JA3/JA4, and HTTP/2
|
|
11
|
+
//! fingerprints.
|
|
12
|
+
//!
|
|
13
|
+
//! - Plain bodies, [JSON](#json), [urlencoded](#forms), [multipart]
|
|
14
|
+
//! - Cookies Store
|
|
15
|
+
//! - [Redirect Policy](#redirect-policies)
|
|
16
|
+
//! - Original Header
|
|
17
|
+
//! - Rotating [Proxies](#proxies)
|
|
18
|
+
//! - [Certificate Store](#certificate-store)
|
|
19
|
+
//! - [Tower](https://docs.rs/tower/latest/tower) Middleware
|
|
20
|
+
//! - [WebSocket](#websocket) Upgrade
|
|
21
|
+
//! - HTTPS via [BoringSSL](#tls)
|
|
22
|
+
//! - HTTP/2 over TLS [Emulation](#emulation)
|
|
23
|
+
//!
|
|
24
|
+
//! Additional learning resources include:
|
|
25
|
+
//!
|
|
26
|
+
//! - [The Rust Cookbook](https://doc.rust-lang.org/stable/book/ch00-00-introduction.html)
|
|
27
|
+
//! - [Repository Examples](https://github.com/0x676e67/wreq/tree/main/examples)
|
|
28
|
+
//!
|
|
29
|
+
//! ## Emulation
|
|
30
|
+
//!
|
|
31
|
+
//! The `emulation` module provides a way to simulate various browser TLS/HTTP2 fingerprints.
|
|
32
|
+
//!
|
|
33
|
+
//! ```rust,no_run
|
|
34
|
+
//! use wreq_util::Emulation;
|
|
35
|
+
//!
|
|
36
|
+
//! #[tokio::main]
|
|
37
|
+
//! async fn main() -> wreq::Result<()> {
|
|
38
|
+
//! // Use the API you're already familiar with
|
|
39
|
+
//! let resp = wreq::get("https://tls.peet.ws/api/all")
|
|
40
|
+
//! .emulation(Emulation::Firefox136)
|
|
41
|
+
//! .send().await?;
|
|
42
|
+
//! println!("{}", resp.text().await?);
|
|
43
|
+
//!
|
|
44
|
+
//! Ok(())
|
|
45
|
+
//! }
|
|
46
|
+
//! ```
|
|
47
|
+
//!
|
|
48
|
+
//! ## Websocket
|
|
49
|
+
//!
|
|
50
|
+
//! The `websocket` module provides a way to upgrade a connection to a websocket.
|
|
51
|
+
//!
|
|
52
|
+
//! ```rust,no_run
|
|
53
|
+
//! use futures_util::{SinkExt, StreamExt, TryStreamExt};
|
|
54
|
+
//! use wreq::{header, ws::message::Message};
|
|
55
|
+
//!
|
|
56
|
+
//! #[tokio::main]
|
|
57
|
+
//! async fn main() -> wreq::Result<()> {
|
|
58
|
+
//! // Use the API you're already familiar with
|
|
59
|
+
//! let websocket = wreq::websocket("wss://echo.websocket.org")
|
|
60
|
+
//! .header(header::USER_AGENT, env!("CARGO_PKG_NAME"))
|
|
61
|
+
//! .send()
|
|
62
|
+
//! .await?;
|
|
63
|
+
//!
|
|
64
|
+
//! assert_eq!(websocket.version(), http::Version::HTTP_11);
|
|
65
|
+
//!
|
|
66
|
+
//! let (mut tx, mut rx) = websocket.into_websocket().await?.split();
|
|
67
|
+
//!
|
|
68
|
+
//! tokio::spawn(async move {
|
|
69
|
+
//! for i in 1..11 {
|
|
70
|
+
//! if let Err(err) = tx.send(Message::text(format!("Hello, World! {i}"))).await {
|
|
71
|
+
//! eprintln!("failed to send message: {err}");
|
|
72
|
+
//! }
|
|
73
|
+
//! }
|
|
74
|
+
//! });
|
|
75
|
+
//!
|
|
76
|
+
//! while let Some(message) = rx.try_next().await? {
|
|
77
|
+
//! if let Message::Text(text) = message {
|
|
78
|
+
//! println!("received: {text}");
|
|
79
|
+
//! }
|
|
80
|
+
//! }
|
|
81
|
+
//!
|
|
82
|
+
//! Ok(())
|
|
83
|
+
//! }
|
|
84
|
+
//! ```
|
|
85
|
+
//!
|
|
86
|
+
//! ## Making a GET request
|
|
87
|
+
//!
|
|
88
|
+
//! Making a GET request is simple.
|
|
89
|
+
//!
|
|
90
|
+
//! ```rust
|
|
91
|
+
//! # async fn run() -> wreq::Result<()> {
|
|
92
|
+
//! let body = wreq::get("https://www.rust-lang.org")
|
|
93
|
+
//! .send()
|
|
94
|
+
//! .await?
|
|
95
|
+
//! .text()
|
|
96
|
+
//! .await?;
|
|
97
|
+
//!
|
|
98
|
+
//! println!("body = {:?}", body);
|
|
99
|
+
//! # Ok(())
|
|
100
|
+
//! # }
|
|
101
|
+
//! ```
|
|
102
|
+
//!
|
|
103
|
+
//! **NOTE**: If you plan to perform multiple requests, it is best to create a
|
|
104
|
+
//! [`Client`][client] and reuse it, taking advantage of keep-alive connection
|
|
105
|
+
//! pooling.
|
|
106
|
+
//!
|
|
107
|
+
//! ## Making POST requests (or setting request bodies)
|
|
108
|
+
//!
|
|
109
|
+
//! There are several ways you can set the body of a request. The basic one is
|
|
110
|
+
//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
|
|
111
|
+
//! exact raw bytes of what the body should be. It accepts various types,
|
|
112
|
+
//! including `String` and `Vec<u8>`. If you wish to pass a custom
|
|
113
|
+
//! type, you can use the `wreq::Body` constructors.
|
|
114
|
+
//!
|
|
115
|
+
//! ```rust
|
|
116
|
+
//! # use wreq::Error;
|
|
117
|
+
//! #
|
|
118
|
+
//! # async fn run() -> Result<(), Error> {
|
|
119
|
+
//! let client = wreq::Client::new();
|
|
120
|
+
//! let res = client
|
|
121
|
+
//! .post("http://httpbin.org/post")
|
|
122
|
+
//! .body("the exact body that is sent")
|
|
123
|
+
//! .send()
|
|
124
|
+
//! .await?;
|
|
125
|
+
//! # Ok(())
|
|
126
|
+
//! # }
|
|
127
|
+
//! ```
|
|
128
|
+
//!
|
|
129
|
+
//! ### Forms
|
|
130
|
+
//!
|
|
131
|
+
//! It's very common to want to send form data in a request body. This can be
|
|
132
|
+
//! done with any type that can be serialized into form data.
|
|
133
|
+
//!
|
|
134
|
+
//! This can be an array of tuples, or a `HashMap`, or a custom type that
|
|
135
|
+
//! implements [`Serialize`][serde].
|
|
136
|
+
//!
|
|
137
|
+
//! The feature `form` is required.
|
|
138
|
+
//!
|
|
139
|
+
//! ```rust
|
|
140
|
+
//! # use wreq::Error;
|
|
141
|
+
//! # #[cfg(feature = "form")]
|
|
142
|
+
//! # async fn run() -> Result<(), Error> {
|
|
143
|
+
//! // This will POST a body of `foo=bar&baz=quux`
|
|
144
|
+
//! let params = [("foo", "bar"), ("baz", "quux")];
|
|
145
|
+
//! let client = wreq::Client::new();
|
|
146
|
+
//! let res = client
|
|
147
|
+
//! .post("http://httpbin.org/post")
|
|
148
|
+
//! .form(¶ms)
|
|
149
|
+
//! .send()
|
|
150
|
+
//! .await?;
|
|
151
|
+
//! # Ok(())
|
|
152
|
+
//! # }
|
|
153
|
+
//! ```
|
|
154
|
+
//!
|
|
155
|
+
//! ### JSON
|
|
156
|
+
//!
|
|
157
|
+
//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
|
|
158
|
+
//! a similar fashion the `form` method. It can take any value that can be
|
|
159
|
+
//! serialized into JSON. The feature `json` is required.
|
|
160
|
+
//!
|
|
161
|
+
//! ```rust
|
|
162
|
+
//! # use wreq::Error;
|
|
163
|
+
//! # use std::collections::HashMap;
|
|
164
|
+
//! #
|
|
165
|
+
//! # #[cfg(feature = "json")]
|
|
166
|
+
//! # async fn run() -> Result<(), Error> {
|
|
167
|
+
//! // This will POST a body of `{"lang":"rust","body":"json"}`
|
|
168
|
+
//! let mut map = HashMap::new();
|
|
169
|
+
//! map.insert("lang", "rust");
|
|
170
|
+
//! map.insert("body", "json");
|
|
171
|
+
//!
|
|
172
|
+
//! let client = wreq::Client::new();
|
|
173
|
+
//! let res = client
|
|
174
|
+
//! .post("http://httpbin.org/post")
|
|
175
|
+
//! .json(&map)
|
|
176
|
+
//! .send()
|
|
177
|
+
//! .await?;
|
|
178
|
+
//! # Ok(())
|
|
179
|
+
//! # }
|
|
180
|
+
//! ```
|
|
181
|
+
//!
|
|
182
|
+
//! ## Redirect Policies
|
|
183
|
+
//!
|
|
184
|
+
//! By default, the client does not handle HTTP redirects.
|
|
185
|
+
//! To customize this behavior, you can use [`redirect::Policy`][redirect] with ClientBuilder.
|
|
186
|
+
//!
|
|
187
|
+
//! ## Cookies
|
|
188
|
+
//!
|
|
189
|
+
//! The automatic storing and sending of session cookies can be enabled with
|
|
190
|
+
//! the [`cookie_store`][ClientBuilder::cookie_store] method on `ClientBuilder`.
|
|
191
|
+
//!
|
|
192
|
+
//! ## Proxies
|
|
193
|
+
//!
|
|
194
|
+
//! **NOTE**: System proxies are enabled by default.
|
|
195
|
+
//!
|
|
196
|
+
//! System proxies look in environment variables to set HTTP or HTTPS proxies.
|
|
197
|
+
//!
|
|
198
|
+
//! `HTTP_PROXY` or `http_proxy` provide HTTP proxies for HTTP connections while
|
|
199
|
+
//! `HTTPS_PROXY` or `https_proxy` provide HTTPS proxies for HTTPS connections.
|
|
200
|
+
//! `ALL_PROXY` or `all_proxy` provide proxies for both HTTP and HTTPS connections.
|
|
201
|
+
//! If both the all proxy and HTTP or HTTPS proxy variables are set the more specific
|
|
202
|
+
//! HTTP or HTTPS proxies take precedence.
|
|
203
|
+
//!
|
|
204
|
+
//! These can be overwritten by adding a [`Proxy`] to `ClientBuilder`
|
|
205
|
+
//! i.e. `let proxy = wreq::Proxy::http("https://secure.example")?;`
|
|
206
|
+
//! or disabled by calling `ClientBuilder::no_proxy()`.
|
|
207
|
+
//!
|
|
208
|
+
//! `socks` feature is required if you have configured socks proxy like this:
|
|
209
|
+
//!
|
|
210
|
+
//! ```bash
|
|
211
|
+
//! export https_proxy=socks5://127.0.0.1:1086
|
|
212
|
+
//! ```
|
|
213
|
+
//!
|
|
214
|
+
//! * `http://` is the scheme for http proxy
|
|
215
|
+
//! * `https://` is the scheme for https proxy
|
|
216
|
+
//! * `socks4://` is the scheme for socks4 proxy
|
|
217
|
+
//! * `socks4a://` is the scheme for socks4a proxy
|
|
218
|
+
//! * `socks5://` is the scheme for socks5 proxy
|
|
219
|
+
//! * `socks5h://` is the scheme for socks5h proxy
|
|
220
|
+
//!
|
|
221
|
+
//! ## TLS
|
|
222
|
+
//!
|
|
223
|
+
//! By default, clients will utilize BoringSSL transport layer security to connect to HTTPS targets.
|
|
224
|
+
//!
|
|
225
|
+
//! - Various parts of TLS can also be configured or even disabled on the `ClientBuilder`.
|
|
226
|
+
//!
|
|
227
|
+
//! ## Certificate Store
|
|
228
|
+
//!
|
|
229
|
+
//! By default, wreq uses Mozilla's root certificates through the webpki-roots crate.
|
|
230
|
+
//! This static root certificate bundle is not automatically updated and ignores any root
|
|
231
|
+
//! certificates installed on the host. You can disable default-features to use the system's default
|
|
232
|
+
//! certificate path. Additionally, wreq provides a certificate store for users to customize and
|
|
233
|
+
//! update certificates.
|
|
234
|
+
//!
|
|
235
|
+
//! Custom Certificate Store verification supports Root CA certificates, peer certificates, and
|
|
236
|
+
//! self-signed certificate SSL pinning.
|
|
237
|
+
//!
|
|
238
|
+
//! ## Optional Features
|
|
239
|
+
//!
|
|
240
|
+
//! The following are a list of [Cargo features][cargo-features] that can be
|
|
241
|
+
//! enabled or disabled:
|
|
242
|
+
//!
|
|
243
|
+
//! - **cookies**: Provides cookie session support.
|
|
244
|
+
//! - **gzip**: Provides response body gzip decompression.
|
|
245
|
+
//! - **brotli**: Provides response body brotli decompression.
|
|
246
|
+
//! - **zstd**: Provides response body zstd decompression.
|
|
247
|
+
//! - **deflate**: Provides response body deflate decompression.
|
|
248
|
+
//! - **query**: Provides query parameter serialization.
|
|
249
|
+
//! - **form**: Provides form data serialization.
|
|
250
|
+
//! - **json**: Provides serialization and deserialization for JSON bodies.
|
|
251
|
+
//! - **multipart**: Provides functionality for multipart forms.
|
|
252
|
+
//! - **charset**: Improved support for decoding text.
|
|
253
|
+
//! - **stream**: Adds support for `futures::Stream`.
|
|
254
|
+
//! - **socks**: Provides SOCKS5 and SOCKS4 proxy support.
|
|
255
|
+
//! - **ws**: Provides websocket support.
|
|
256
|
+
//! - **hickory-dns**: Enables a hickory-dns async resolver instead of default threadpool using
|
|
257
|
+
//! `getaddrinfo`.
|
|
258
|
+
//! - **webpki-roots** *(enabled by default)*: Use the webpki-roots crate for root certificates.
|
|
259
|
+
//! - **system-proxy**: Enable system proxy support.
|
|
260
|
+
//! - **tracing**: Enable tracing logging support.
|
|
261
|
+
//! - **prefix-symbols**: Prefix BoringSSL symbols to avoid linker conflicts.
|
|
262
|
+
//!
|
|
263
|
+
//! [client]: ./struct.Client.html
|
|
264
|
+
//! [response]: ./struct.Response.html
|
|
265
|
+
//! [get]: ./fn.get.html
|
|
266
|
+
//! [builder]: ./struct.RequestBuilder.html
|
|
267
|
+
//! [serde]: http://serde.rs
|
|
268
|
+
//! [redirect]: crate::redirect
|
|
269
|
+
//! [Proxy]: ./struct.Proxy.html
|
|
270
|
+
//! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section
|
|
271
|
+
|
|
272
|
+
#[macro_use]
|
|
273
|
+
mod trace;
|
|
274
|
+
#[macro_use]
|
|
275
|
+
mod config;
|
|
276
|
+
mod client;
|
|
277
|
+
mod error;
|
|
278
|
+
mod ext;
|
|
279
|
+
mod hash;
|
|
280
|
+
mod into_uri;
|
|
281
|
+
mod proxy;
|
|
282
|
+
mod sync;
|
|
283
|
+
mod util;
|
|
284
|
+
|
|
285
|
+
#[cfg(feature = "cookies")]
|
|
286
|
+
pub mod cookie;
|
|
287
|
+
pub mod dns;
|
|
288
|
+
pub mod header;
|
|
289
|
+
pub mod redirect;
|
|
290
|
+
pub mod retry;
|
|
291
|
+
pub mod tls;
|
|
292
|
+
|
|
293
|
+
pub use http::{Method, StatusCode, Uri, Version};
|
|
294
|
+
#[cfg(unix)]
|
|
295
|
+
use libc as _;
|
|
296
|
+
|
|
297
|
+
#[cfg(feature = "multipart")]
|
|
298
|
+
pub use self::client::multipart;
|
|
299
|
+
#[cfg(feature = "ws")]
|
|
300
|
+
pub use self::client::ws;
|
|
301
|
+
pub use self::{
|
|
302
|
+
client::{
|
|
303
|
+
Body, Client, ClientBuilder, Emulation, EmulationBuilder, EmulationFactory, Request,
|
|
304
|
+
RequestBuilder, Response, Upgraded, http1, http2,
|
|
305
|
+
},
|
|
306
|
+
error::{Error, Result},
|
|
307
|
+
ext::{ResponseBuilderExt, ResponseExt},
|
|
308
|
+
into_uri::IntoUri,
|
|
309
|
+
proxy::{NoProxy, Proxy},
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
fn _assert_impls() {
|
|
313
|
+
fn assert_send<T: Send>() {}
|
|
314
|
+
fn assert_sync<T: Sync>() {}
|
|
315
|
+
fn assert_clone<T: Clone>() {}
|
|
316
|
+
|
|
317
|
+
assert_send::<Client>();
|
|
318
|
+
assert_sync::<Client>();
|
|
319
|
+
assert_clone::<Client>();
|
|
320
|
+
|
|
321
|
+
assert_send::<Request>();
|
|
322
|
+
assert_send::<RequestBuilder>();
|
|
323
|
+
#[cfg(feature = "ws")]
|
|
324
|
+
assert_send::<ws::WebSocketRequestBuilder>();
|
|
325
|
+
|
|
326
|
+
assert_send::<Response>();
|
|
327
|
+
#[cfg(feature = "ws")]
|
|
328
|
+
assert_send::<ws::WebSocketResponse>();
|
|
329
|
+
#[cfg(feature = "ws")]
|
|
330
|
+
assert_send::<ws::WebSocket>();
|
|
331
|
+
|
|
332
|
+
assert_send::<Error>();
|
|
333
|
+
assert_sync::<Error>();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/// Shortcut method to quickly make a `GET` request.
|
|
337
|
+
///
|
|
338
|
+
/// See also the methods on the [`wreq::RequestBuilder`](./struct.RequestBuilder.html)
|
|
339
|
+
/// type.
|
|
340
|
+
///
|
|
341
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
342
|
+
/// and so should not be used if making many requests. Create a
|
|
343
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
344
|
+
///
|
|
345
|
+
/// # Examples
|
|
346
|
+
///
|
|
347
|
+
/// ```rust
|
|
348
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
349
|
+
/// let body = wreq::get("https://www.rust-lang.org")
|
|
350
|
+
/// .send()
|
|
351
|
+
/// .await?
|
|
352
|
+
/// .text()
|
|
353
|
+
/// .await?;
|
|
354
|
+
/// # Ok(())
|
|
355
|
+
/// # }
|
|
356
|
+
/// ```
|
|
357
|
+
#[inline]
|
|
358
|
+
pub fn get<T: IntoUri>(uri: T) -> RequestBuilder {
|
|
359
|
+
Client::new().get(uri)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/// Shortcut method to quickly make a `POST` request.
|
|
363
|
+
///
|
|
364
|
+
/// See also the methods on the [`wreq::RequestBuilder`](./struct.RequestBuilder.html)
|
|
365
|
+
/// type.
|
|
366
|
+
///
|
|
367
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
368
|
+
/// and so should not be used if making many requests. Create a
|
|
369
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
370
|
+
///
|
|
371
|
+
/// # Examples
|
|
372
|
+
///
|
|
373
|
+
/// ```rust
|
|
374
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
375
|
+
/// let res = wreq::post("https://httpbin.org/post")
|
|
376
|
+
/// .body("example body")
|
|
377
|
+
/// .send()
|
|
378
|
+
/// .await?;
|
|
379
|
+
/// # Ok(())
|
|
380
|
+
/// # }
|
|
381
|
+
/// ```
|
|
382
|
+
#[inline]
|
|
383
|
+
pub fn post<T: IntoUri>(uri: T) -> RequestBuilder {
|
|
384
|
+
Client::new().post(uri)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/// Shortcut method to quickly make a `PUT` request.
|
|
388
|
+
///
|
|
389
|
+
/// See also the methods on the [`wreq::RequestBuilder`](./struct.RequestBuilder.html)
|
|
390
|
+
/// type.
|
|
391
|
+
///
|
|
392
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
393
|
+
/// and so should not be used if making many requests. Create a
|
|
394
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
395
|
+
///
|
|
396
|
+
/// # Examples
|
|
397
|
+
///
|
|
398
|
+
/// ```rust
|
|
399
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
400
|
+
/// let res = wreq::put("https://httpbin.org/put")
|
|
401
|
+
/// .body("update content")
|
|
402
|
+
/// .send()
|
|
403
|
+
/// .await?;
|
|
404
|
+
/// # Ok(())
|
|
405
|
+
/// # }
|
|
406
|
+
/// ```
|
|
407
|
+
#[inline]
|
|
408
|
+
pub fn put<T: IntoUri>(uri: T) -> RequestBuilder {
|
|
409
|
+
Client::new().put(uri)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/// Shortcut method to quickly make a `DELETE` request.
|
|
413
|
+
///
|
|
414
|
+
/// See also the methods on the [`wreq::RequestBuilder`](./struct.RequestBuilder.html)
|
|
415
|
+
/// type.
|
|
416
|
+
///
|
|
417
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
418
|
+
/// and so should not be used if making many requests. Create a
|
|
419
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
420
|
+
///
|
|
421
|
+
/// # Examples
|
|
422
|
+
///
|
|
423
|
+
/// ```rust
|
|
424
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
425
|
+
/// let res = wreq::delete("https://httpbin.org/delete")
|
|
426
|
+
/// .send()
|
|
427
|
+
/// .await?;
|
|
428
|
+
/// # Ok(())
|
|
429
|
+
/// # }
|
|
430
|
+
/// ```
|
|
431
|
+
#[inline]
|
|
432
|
+
pub fn delete<T: IntoUri>(uri: T) -> RequestBuilder {
|
|
433
|
+
Client::new().delete(uri)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/// Shortcut method to quickly make a `HEAD` request.
|
|
437
|
+
///
|
|
438
|
+
/// See also the methods on the [`wreq::RequestBuilder`](./struct.RequestBuilder.html)
|
|
439
|
+
/// type.
|
|
440
|
+
///
|
|
441
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
442
|
+
/// and so should not be used if making many requests. Create a
|
|
443
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
444
|
+
///
|
|
445
|
+
/// # Examples
|
|
446
|
+
///
|
|
447
|
+
/// ```rust
|
|
448
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
449
|
+
/// let res = wreq::head("https://httpbin.org/get")
|
|
450
|
+
/// .send()
|
|
451
|
+
/// .await?;
|
|
452
|
+
/// # Ok(())
|
|
453
|
+
/// # }
|
|
454
|
+
/// ```
|
|
455
|
+
#[inline]
|
|
456
|
+
pub fn head<T: IntoUri>(uri: T) -> RequestBuilder {
|
|
457
|
+
Client::new().head(uri)
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/// Shortcut method to quickly make a `PATCH` request.
|
|
461
|
+
///
|
|
462
|
+
/// See also the methods on the [`wreq::RequestBuilder`](./struct.RequestBuilder.html)
|
|
463
|
+
/// type.
|
|
464
|
+
///
|
|
465
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
466
|
+
/// and so should not be used if making many requests. Create a
|
|
467
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
468
|
+
///
|
|
469
|
+
/// # Examples
|
|
470
|
+
///
|
|
471
|
+
/// ```rust
|
|
472
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
473
|
+
/// let res = wreq::patch("https://httpbin.org/patch")
|
|
474
|
+
/// .body("patch content")
|
|
475
|
+
/// .send()
|
|
476
|
+
/// .await?;
|
|
477
|
+
/// # Ok(())
|
|
478
|
+
/// # }
|
|
479
|
+
/// ```
|
|
480
|
+
#[inline]
|
|
481
|
+
pub fn patch<T: IntoUri>(uri: T) -> RequestBuilder {
|
|
482
|
+
Client::new().patch(uri)
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/// Shortcut method to quickly make an `OPTIONS` request.
|
|
486
|
+
///
|
|
487
|
+
/// See also the methods on the [`wreq::RequestBuilder`](./struct.RequestBuilder.html)
|
|
488
|
+
/// type.
|
|
489
|
+
///
|
|
490
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
491
|
+
/// and so should not be used if making many requests. Create a
|
|
492
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
493
|
+
///
|
|
494
|
+
/// # Examples
|
|
495
|
+
///
|
|
496
|
+
/// ```rust
|
|
497
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
498
|
+
/// let res = wreq::options("https://httpbin.org/get")
|
|
499
|
+
/// .send()
|
|
500
|
+
/// .await?;
|
|
501
|
+
/// # Ok(())
|
|
502
|
+
/// # }
|
|
503
|
+
/// ```
|
|
504
|
+
#[inline]
|
|
505
|
+
pub fn options<T: IntoUri>(uri: T) -> RequestBuilder {
|
|
506
|
+
Client::new().options(uri)
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/// Shortcut method to quickly make a request with a custom HTTP method.
|
|
510
|
+
///
|
|
511
|
+
/// See also the methods on the [`wreq::RequestBuilder`](./struct.RequestBuilder.html)
|
|
512
|
+
/// type.
|
|
513
|
+
///
|
|
514
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
515
|
+
/// and so should not be used if making many requests. Create a
|
|
516
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
517
|
+
///
|
|
518
|
+
/// # Examples
|
|
519
|
+
///
|
|
520
|
+
/// ```rust
|
|
521
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
522
|
+
/// use http::Method;
|
|
523
|
+
/// let res = wreq::request(Method::TRACE, "https://httpbin.org/trace")
|
|
524
|
+
/// .send()
|
|
525
|
+
/// .await?;
|
|
526
|
+
/// # Ok(())
|
|
527
|
+
/// # }
|
|
528
|
+
/// ```
|
|
529
|
+
#[inline]
|
|
530
|
+
pub fn request<T: IntoUri>(method: Method, uri: T) -> RequestBuilder {
|
|
531
|
+
Client::new().request(method, uri)
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/// Shortcut method to quickly make a WebSocket request.
|
|
535
|
+
///
|
|
536
|
+
/// See also the methods on the
|
|
537
|
+
/// [`wreq::ws::WebSocketRequestBuilder`](./ws/struct.WebSocketRequestBuilder.html) type.
|
|
538
|
+
///
|
|
539
|
+
/// **NOTE**: This function creates a new internal `Client` on each call,
|
|
540
|
+
/// and so should not be used if making many requests. Create a
|
|
541
|
+
/// [`Client`](./struct.Client.html) instead.
|
|
542
|
+
///
|
|
543
|
+
/// # Examples
|
|
544
|
+
///
|
|
545
|
+
/// ```rust
|
|
546
|
+
/// # async fn run() -> wreq::Result<()> {
|
|
547
|
+
/// use futures_util::{SinkExt, StreamExt, TryStreamExt};
|
|
548
|
+
/// use wreq::{header, ws::message::Message};
|
|
549
|
+
///
|
|
550
|
+
/// let resp = wreq::websocket("wss://echo.websocket.org")
|
|
551
|
+
/// .header(header::USER_AGENT, env!("CARGO_PKG_NAME"))
|
|
552
|
+
/// .read_buffer_size(1024 * 1024)
|
|
553
|
+
/// .send()
|
|
554
|
+
/// .await?;
|
|
555
|
+
///
|
|
556
|
+
/// assert_eq!(resp.version(), http::Version::HTTP_11);
|
|
557
|
+
///
|
|
558
|
+
/// let websocket = resp.into_websocket().await?;
|
|
559
|
+
/// if let Some(protocol) = websocket.protocol() {
|
|
560
|
+
/// println!("WebSocket subprotocol: {:?}", protocol);
|
|
561
|
+
/// }
|
|
562
|
+
///
|
|
563
|
+
/// let (mut tx, mut rx) = websocket.split();
|
|
564
|
+
///
|
|
565
|
+
/// tokio::spawn(async move {
|
|
566
|
+
/// for i in 1..11 {
|
|
567
|
+
/// if let Err(err) = tx.send(Message::text(format!("Hello, World! {i}"))).await {
|
|
568
|
+
/// eprintln!("failed to send message: {err}");
|
|
569
|
+
/// }
|
|
570
|
+
/// }
|
|
571
|
+
/// });
|
|
572
|
+
///
|
|
573
|
+
/// while let Some(message) = rx.try_next().await? {
|
|
574
|
+
/// if let Message::Text(text) = message {
|
|
575
|
+
/// println!("received: {text}");
|
|
576
|
+
/// }
|
|
577
|
+
/// }
|
|
578
|
+
/// # Ok(())
|
|
579
|
+
/// # }
|
|
580
|
+
/// ```
|
|
581
|
+
#[inline]
|
|
582
|
+
#[cfg(feature = "ws")]
|
|
583
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "ws")))]
|
|
584
|
+
pub fn websocket<T: IntoUri>(uri: T) -> ws::WebSocketRequestBuilder {
|
|
585
|
+
Client::new().websocket(uri)
|
|
586
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
use system_configuration::{
|
|
2
|
+
core_foundation::{
|
|
3
|
+
base::CFType,
|
|
4
|
+
dictionary::CFDictionary,
|
|
5
|
+
number::CFNumber,
|
|
6
|
+
string::{CFString, CFStringRef},
|
|
7
|
+
},
|
|
8
|
+
dynamic_store::SCDynamicStoreBuilder,
|
|
9
|
+
sys::schema_definitions::{
|
|
10
|
+
kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPPort, kSCPropNetProxiesHTTPProxy,
|
|
11
|
+
kSCPropNetProxiesHTTPSEnable, kSCPropNetProxiesHTTPSPort, kSCPropNetProxiesHTTPSProxy,
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
#[allow(unsafe_code)]
|
|
16
|
+
pub(super) fn with_system(builder: &mut super::matcher::Builder) {
|
|
17
|
+
let Some(proxies_map) = SCDynamicStoreBuilder::new("")
|
|
18
|
+
.build()
|
|
19
|
+
.and_then(|store| store.get_proxies())
|
|
20
|
+
else {
|
|
21
|
+
return;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
if builder.http.is_empty() {
|
|
25
|
+
let http_proxy_config = parse_setting_from_dynamic_store(
|
|
26
|
+
&proxies_map,
|
|
27
|
+
unsafe { kSCPropNetProxiesHTTPEnable },
|
|
28
|
+
unsafe { kSCPropNetProxiesHTTPProxy },
|
|
29
|
+
unsafe { kSCPropNetProxiesHTTPPort },
|
|
30
|
+
);
|
|
31
|
+
if let Some(http) = http_proxy_config {
|
|
32
|
+
builder.http = http;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if builder.https.is_empty() {
|
|
37
|
+
let https_proxy_config = parse_setting_from_dynamic_store(
|
|
38
|
+
&proxies_map,
|
|
39
|
+
unsafe { kSCPropNetProxiesHTTPSEnable },
|
|
40
|
+
unsafe { kSCPropNetProxiesHTTPSProxy },
|
|
41
|
+
unsafe { kSCPropNetProxiesHTTPSPort },
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if let Some(https) = https_proxy_config {
|
|
45
|
+
builder.https = https;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
fn parse_setting_from_dynamic_store(
|
|
51
|
+
proxies_map: &CFDictionary<CFString, CFType>,
|
|
52
|
+
enabled_key: CFStringRef,
|
|
53
|
+
host_key: CFStringRef,
|
|
54
|
+
port_key: CFStringRef,
|
|
55
|
+
) -> Option<String> {
|
|
56
|
+
let proxy_enabled = proxies_map
|
|
57
|
+
.find(enabled_key)
|
|
58
|
+
.and_then(|flag| flag.downcast::<CFNumber>())
|
|
59
|
+
.and_then(|flag| flag.to_i32())
|
|
60
|
+
.unwrap_or(0)
|
|
61
|
+
== 1;
|
|
62
|
+
|
|
63
|
+
if proxy_enabled {
|
|
64
|
+
let proxy_host = proxies_map
|
|
65
|
+
.find(host_key)
|
|
66
|
+
.and_then(|host| host.downcast::<CFString>())
|
|
67
|
+
.map(|host| host.to_string());
|
|
68
|
+
let proxy_port = proxies_map
|
|
69
|
+
.find(port_key)
|
|
70
|
+
.and_then(|port| port.downcast::<CFNumber>())
|
|
71
|
+
.and_then(|port| port.to_i32());
|
|
72
|
+
|
|
73
|
+
return match (proxy_host, proxy_port) {
|
|
74
|
+
(Some(proxy_host), Some(proxy_port)) => Some(format!("{proxy_host}:{proxy_port}")),
|
|
75
|
+
(Some(proxy_host), None) => Some(proxy_host),
|
|
76
|
+
(None, Some(_)) => None,
|
|
77
|
+
(None, None) => None,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
None
|
|
82
|
+
}
|