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,818 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
convert::TryFrom,
|
|
3
|
+
fmt,
|
|
4
|
+
future::Future,
|
|
5
|
+
net::{IpAddr, Ipv4Addr, Ipv6Addr},
|
|
6
|
+
time::Duration,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
use http::{Extensions, Request as HttpRequest, Uri, Version};
|
|
10
|
+
#[cfg(any(feature = "query", feature = "form", feature = "json"))]
|
|
11
|
+
use serde::Serialize;
|
|
12
|
+
#[cfg(feature = "multipart")]
|
|
13
|
+
use {super::multipart, bytes::Bytes, http::header::CONTENT_LENGTH};
|
|
14
|
+
#[cfg(feature = "cookies")]
|
|
15
|
+
use {
|
|
16
|
+
crate::cookie::{CookieStore, IntoCookieStore},
|
|
17
|
+
std::sync::Arc,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
#[cfg(any(
|
|
21
|
+
feature = "gzip",
|
|
22
|
+
feature = "zstd",
|
|
23
|
+
feature = "brotli",
|
|
24
|
+
feature = "deflate",
|
|
25
|
+
))]
|
|
26
|
+
use super::layer::decoder::AcceptEncoding;
|
|
27
|
+
use super::{
|
|
28
|
+
Body, EmulationFactory, Response,
|
|
29
|
+
http::{Client, future::Pending},
|
|
30
|
+
layer::{
|
|
31
|
+
config::{DefaultHeaders, RequestOptions},
|
|
32
|
+
timeout::TimeoutOptions,
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
#[cfg(any(feature = "multipart", feature = "form", feature = "json"))]
|
|
36
|
+
use crate::header::CONTENT_TYPE;
|
|
37
|
+
use crate::{
|
|
38
|
+
Error, Method, Proxy,
|
|
39
|
+
config::{RequestConfig, RequestConfigValue},
|
|
40
|
+
ext::UriExt,
|
|
41
|
+
header::{AUTHORIZATION, HeaderMap, HeaderName, HeaderValue, OrigHeaderMap},
|
|
42
|
+
redirect,
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/// A request which can be executed with [`Client::execute()`].
|
|
46
|
+
#[derive(Debug)]
|
|
47
|
+
pub struct Request(http::Request<Option<Body>>);
|
|
48
|
+
|
|
49
|
+
/// A builder to construct the properties of a [`Request`].
|
|
50
|
+
///
|
|
51
|
+
/// To construct a [`RequestBuilder`], refer to the [`Client`] documentation.
|
|
52
|
+
#[must_use = "RequestBuilder does nothing until you 'send' it"]
|
|
53
|
+
pub struct RequestBuilder {
|
|
54
|
+
client: Client,
|
|
55
|
+
request: crate::Result<Request>,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
impl Request {
|
|
59
|
+
/// Constructs a new [`Request`].
|
|
60
|
+
pub fn new(method: Method, uri: Uri) -> Self {
|
|
61
|
+
let mut request = http::Request::new(None);
|
|
62
|
+
*request.method_mut() = method;
|
|
63
|
+
*request.uri_mut() = uri;
|
|
64
|
+
Request(request)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// Get the method.
|
|
68
|
+
#[inline]
|
|
69
|
+
pub fn method(&self) -> &Method {
|
|
70
|
+
self.0.method()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// Get a mutable reference to the method.
|
|
74
|
+
#[inline]
|
|
75
|
+
pub fn method_mut(&mut self) -> &mut Method {
|
|
76
|
+
self.0.method_mut()
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// Get the uri.
|
|
80
|
+
#[inline]
|
|
81
|
+
pub fn uri(&self) -> &Uri {
|
|
82
|
+
self.0.uri()
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Get a mutable reference to the uri.
|
|
86
|
+
#[inline]
|
|
87
|
+
pub fn uri_mut(&mut self) -> &mut Uri {
|
|
88
|
+
self.0.uri_mut()
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// Get the headers.
|
|
92
|
+
#[inline]
|
|
93
|
+
pub fn headers(&self) -> &HeaderMap {
|
|
94
|
+
self.0.headers()
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// Get a mutable reference to the headers.
|
|
98
|
+
#[inline]
|
|
99
|
+
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
|
100
|
+
self.0.headers_mut()
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/// Get the body.
|
|
104
|
+
#[inline]
|
|
105
|
+
pub fn body(&self) -> Option<&Body> {
|
|
106
|
+
self.0.body().as_ref()
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// Get a mutable reference to the body.
|
|
110
|
+
#[inline]
|
|
111
|
+
pub fn body_mut(&mut self) -> &mut Option<Body> {
|
|
112
|
+
self.0.body_mut()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// Get the http version.
|
|
116
|
+
#[inline]
|
|
117
|
+
pub fn version(&self) -> Option<Version> {
|
|
118
|
+
self.config::<RequestOptions>()
|
|
119
|
+
.and_then(RequestOptions::enforced_version)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// Get a mutable reference to the http version.
|
|
123
|
+
#[inline]
|
|
124
|
+
pub fn version_mut(&mut self) -> &mut Option<Version> {
|
|
125
|
+
self.config_mut::<RequestOptions>()
|
|
126
|
+
.get_or_insert_default()
|
|
127
|
+
.enforced_version_mut()
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// Attempt to clone the request.
|
|
131
|
+
///
|
|
132
|
+
/// `None` is returned if the request can not be cloned, i.e. if the body is a stream.
|
|
133
|
+
pub fn try_clone(&self) -> Option<Request> {
|
|
134
|
+
let body = match self.body() {
|
|
135
|
+
Some(body) => Some(body.try_clone()?),
|
|
136
|
+
None => None,
|
|
137
|
+
};
|
|
138
|
+
let mut req = Request::new(self.method().clone(), self.uri().clone());
|
|
139
|
+
*req.headers_mut() = self.headers().clone();
|
|
140
|
+
*req.version_mut() = self.version();
|
|
141
|
+
*req.extensions_mut() = self.extensions().clone();
|
|
142
|
+
*req.body_mut() = body;
|
|
143
|
+
Some(req)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
#[inline]
|
|
147
|
+
pub(crate) fn extensions(&self) -> &Extensions {
|
|
148
|
+
self.0.extensions()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#[inline]
|
|
152
|
+
pub(crate) fn extensions_mut(&mut self) -> &mut Extensions {
|
|
153
|
+
self.0.extensions_mut()
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
#[inline]
|
|
157
|
+
pub(crate) fn config<T>(&self) -> Option<&T::Value>
|
|
158
|
+
where
|
|
159
|
+
T: RequestConfigValue,
|
|
160
|
+
{
|
|
161
|
+
RequestConfig::<T>::get(self.extensions())
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
#[inline]
|
|
165
|
+
pub(crate) fn config_mut<T>(&mut self) -> &mut Option<T::Value>
|
|
166
|
+
where
|
|
167
|
+
T: RequestConfigValue,
|
|
168
|
+
{
|
|
169
|
+
RequestConfig::<T>::get_mut(self.extensions_mut())
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
impl RequestBuilder {
|
|
174
|
+
pub(super) fn new(client: Client, request: crate::Result<Request>) -> RequestBuilder {
|
|
175
|
+
let mut builder = RequestBuilder { client, request };
|
|
176
|
+
|
|
177
|
+
let auth = builder
|
|
178
|
+
.request
|
|
179
|
+
.as_mut()
|
|
180
|
+
.ok()
|
|
181
|
+
.and_then(|req| extract_authority(req.uri_mut()));
|
|
182
|
+
|
|
183
|
+
if let Some((username, password)) = auth {
|
|
184
|
+
builder.basic_auth(username, password)
|
|
185
|
+
} else {
|
|
186
|
+
builder
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// Assemble a builder starting from an existing `Client` and a `Request`.
|
|
191
|
+
pub fn from_parts(client: Client, request: Request) -> RequestBuilder {
|
|
192
|
+
RequestBuilder {
|
|
193
|
+
client,
|
|
194
|
+
request: crate::Result::Ok(request),
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/// Add a `Header` to this Request with ability to define if `header_value` is sensitive.
|
|
199
|
+
fn header_sensitive<K, V>(mut self, key: K, value: V, sensitive: bool) -> RequestBuilder
|
|
200
|
+
where
|
|
201
|
+
HeaderName: TryFrom<K>,
|
|
202
|
+
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
|
|
203
|
+
HeaderValue: TryFrom<V>,
|
|
204
|
+
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
|
|
205
|
+
{
|
|
206
|
+
let mut error = None;
|
|
207
|
+
if let Ok(ref mut req) = self.request {
|
|
208
|
+
match <HeaderName as TryFrom<K>>::try_from(key) {
|
|
209
|
+
Ok(key) => match <HeaderValue as TryFrom<V>>::try_from(value) {
|
|
210
|
+
Ok(mut value) => {
|
|
211
|
+
// We want to potentially make an non-sensitive header
|
|
212
|
+
// to be sensitive, not the reverse. So, don't turn off
|
|
213
|
+
// a previously sensitive header.
|
|
214
|
+
if sensitive {
|
|
215
|
+
value.set_sensitive(true);
|
|
216
|
+
}
|
|
217
|
+
req.headers_mut().append(key, value);
|
|
218
|
+
}
|
|
219
|
+
Err(e) => error = Some(Error::builder(e.into())),
|
|
220
|
+
},
|
|
221
|
+
Err(e) => error = Some(Error::builder(e.into())),
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
if let Some(err) = error {
|
|
225
|
+
self.request = Err(err);
|
|
226
|
+
}
|
|
227
|
+
self
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/// Add a `Header` to this Request.
|
|
231
|
+
///
|
|
232
|
+
/// If the header is already present, the value will be replaced.
|
|
233
|
+
#[inline]
|
|
234
|
+
pub fn header<K, V>(self, key: K, value: V) -> RequestBuilder
|
|
235
|
+
where
|
|
236
|
+
HeaderName: TryFrom<K>,
|
|
237
|
+
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
|
|
238
|
+
HeaderValue: TryFrom<V>,
|
|
239
|
+
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
|
|
240
|
+
{
|
|
241
|
+
self.header_sensitive(key, value, false)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/// Add a set of Headers to the existing ones on this Request.
|
|
245
|
+
///
|
|
246
|
+
/// The headers will be merged in to any already set.
|
|
247
|
+
pub fn headers(mut self, headers: HeaderMap) -> RequestBuilder {
|
|
248
|
+
if let Ok(ref mut req) = self.request {
|
|
249
|
+
crate::util::replace_headers(req.headers_mut(), headers);
|
|
250
|
+
}
|
|
251
|
+
self
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/// Set the original headers for this request.
|
|
255
|
+
pub fn orig_headers(mut self, orig_headers: OrigHeaderMap) -> RequestBuilder {
|
|
256
|
+
if let Ok(ref mut req) = self.request {
|
|
257
|
+
req.config_mut::<OrigHeaderMap>().replace(orig_headers);
|
|
258
|
+
}
|
|
259
|
+
self
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/// Enable or disable client default headers for this request.
|
|
263
|
+
///
|
|
264
|
+
/// By default, client default headers are included. Set to `false` to skip them.
|
|
265
|
+
pub fn default_headers(mut self, enable: bool) -> RequestBuilder {
|
|
266
|
+
if let Ok(ref mut req) = self.request {
|
|
267
|
+
req.config_mut::<DefaultHeaders>().replace(enable);
|
|
268
|
+
}
|
|
269
|
+
self
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/// Enable HTTP authentication.
|
|
273
|
+
///
|
|
274
|
+
/// ```rust
|
|
275
|
+
/// # use wreq::Error;
|
|
276
|
+
/// #
|
|
277
|
+
/// # async fn run() -> Result<(), Error> {
|
|
278
|
+
/// let client = wreq::Client::new();
|
|
279
|
+
/// let resp = client
|
|
280
|
+
/// .get("http://httpbin.org/get")
|
|
281
|
+
/// .auth("your_token_here")
|
|
282
|
+
/// .send()
|
|
283
|
+
/// .await?;
|
|
284
|
+
/// # Ok(())
|
|
285
|
+
/// # }
|
|
286
|
+
/// ```
|
|
287
|
+
pub fn auth<V>(self, token: V) -> RequestBuilder
|
|
288
|
+
where
|
|
289
|
+
HeaderValue: TryFrom<V>,
|
|
290
|
+
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
|
|
291
|
+
{
|
|
292
|
+
self.header_sensitive(AUTHORIZATION, token, true)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/// Enable HTTP basic authentication.
|
|
296
|
+
///
|
|
297
|
+
/// ```rust
|
|
298
|
+
/// # use wreq::Error;
|
|
299
|
+
///
|
|
300
|
+
/// # async fn run() -> Result<(), Error> {
|
|
301
|
+
/// let client = wreq::Client::new();
|
|
302
|
+
/// let resp = client
|
|
303
|
+
/// .delete("http://httpbin.org/delete")
|
|
304
|
+
/// .basic_auth("admin", Some("good password"))
|
|
305
|
+
/// .send()
|
|
306
|
+
/// .await?;
|
|
307
|
+
/// # Ok(())
|
|
308
|
+
/// # }
|
|
309
|
+
/// ```
|
|
310
|
+
pub fn basic_auth<U, P>(self, username: U, password: Option<P>) -> RequestBuilder
|
|
311
|
+
where
|
|
312
|
+
U: fmt::Display,
|
|
313
|
+
P: fmt::Display,
|
|
314
|
+
{
|
|
315
|
+
let header_value = crate::util::basic_auth(username, password);
|
|
316
|
+
self.header_sensitive(AUTHORIZATION, header_value, true)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/// Enable HTTP bearer authentication.
|
|
320
|
+
///
|
|
321
|
+
/// ```rust
|
|
322
|
+
/// # use wreq::Error;
|
|
323
|
+
/// #
|
|
324
|
+
/// # async fn run() -> Result<(), Error> {
|
|
325
|
+
/// let client = wreq::Client::new();
|
|
326
|
+
/// let resp = client
|
|
327
|
+
/// .get("http://httpbin.org/get")
|
|
328
|
+
/// .bearer_auth("your_token_here")
|
|
329
|
+
/// .send()
|
|
330
|
+
/// .await?;
|
|
331
|
+
/// # Ok(())
|
|
332
|
+
/// # }
|
|
333
|
+
/// ```
|
|
334
|
+
pub fn bearer_auth<T>(self, token: T) -> RequestBuilder
|
|
335
|
+
where
|
|
336
|
+
T: fmt::Display,
|
|
337
|
+
{
|
|
338
|
+
let header_value = format!("Bearer {token}");
|
|
339
|
+
self.header_sensitive(AUTHORIZATION, header_value, true)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/// Enables a request timeout.
|
|
343
|
+
///
|
|
344
|
+
/// The timeout is applied from when the request starts connecting until the
|
|
345
|
+
/// response body has finished. It affects only this request and overrides
|
|
346
|
+
/// the timeout configured using `ClientBuilder::timeout()`.
|
|
347
|
+
pub fn timeout(mut self, timeout: Duration) -> RequestBuilder {
|
|
348
|
+
if let Ok(ref mut req) = self.request {
|
|
349
|
+
req.config_mut::<TimeoutOptions>()
|
|
350
|
+
.get_or_insert_default()
|
|
351
|
+
.total_timeout(timeout);
|
|
352
|
+
}
|
|
353
|
+
self
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/// Enables a read timeout.
|
|
357
|
+
///
|
|
358
|
+
/// The read timeout is applied from when the response body starts being read
|
|
359
|
+
/// until the response body has finished. It affects only this request and
|
|
360
|
+
/// overrides the read timeout configured using `ClientBuilder::read_timeout()`.
|
|
361
|
+
pub fn read_timeout(mut self, timeout: Duration) -> RequestBuilder {
|
|
362
|
+
if let Ok(ref mut req) = self.request {
|
|
363
|
+
req.config_mut::<TimeoutOptions>()
|
|
364
|
+
.get_or_insert_default()
|
|
365
|
+
.read_timeout(timeout);
|
|
366
|
+
}
|
|
367
|
+
self
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/// Set the request body.
|
|
371
|
+
pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {
|
|
372
|
+
if let Ok(ref mut req) = self.request {
|
|
373
|
+
*req.body_mut() = Some(body.into());
|
|
374
|
+
}
|
|
375
|
+
self
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/// Sends a multipart/form-data body.
|
|
379
|
+
///
|
|
380
|
+
/// ```
|
|
381
|
+
/// # use wreq::Error;
|
|
382
|
+
///
|
|
383
|
+
/// # async fn run() -> Result<(), Error> {
|
|
384
|
+
/// let client = wreq::Client::new();
|
|
385
|
+
/// let form = wreq::multipart::Form::new()
|
|
386
|
+
/// .text("key3", "value3")
|
|
387
|
+
/// .text("key4", "value4");
|
|
388
|
+
///
|
|
389
|
+
/// let response = client.post("your uri").multipart(form).send().await?;
|
|
390
|
+
/// # Ok(())
|
|
391
|
+
/// # }
|
|
392
|
+
/// ```
|
|
393
|
+
#[cfg(feature = "multipart")]
|
|
394
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "multipart")))]
|
|
395
|
+
pub fn multipart(mut self, mut multipart: multipart::Form) -> RequestBuilder {
|
|
396
|
+
if let Ok(ref mut req) = self.request {
|
|
397
|
+
match HeaderValue::from_maybe_shared(Bytes::from(format!(
|
|
398
|
+
"multipart/form-data; boundary={}",
|
|
399
|
+
multipart.boundary()
|
|
400
|
+
))) {
|
|
401
|
+
Ok(content_type) => {
|
|
402
|
+
req.headers_mut()
|
|
403
|
+
.entry(CONTENT_TYPE)
|
|
404
|
+
.or_insert(content_type);
|
|
405
|
+
|
|
406
|
+
if let Some(length) = multipart.compute_length() {
|
|
407
|
+
req.headers_mut()
|
|
408
|
+
.entry(CONTENT_LENGTH)
|
|
409
|
+
.or_insert_with(|| HeaderValue::from(length));
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
*req.body_mut() = Some(multipart.stream())
|
|
413
|
+
}
|
|
414
|
+
Err(err) => {
|
|
415
|
+
self.request = Err(Error::builder(err));
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
self
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/// Modify the query string of the URI.
|
|
424
|
+
///
|
|
425
|
+
/// Modifies the URI of this request, adding the parameters provided.
|
|
426
|
+
/// This method appends and does not overwrite. This means that it can
|
|
427
|
+
/// be called multiple times and that existing query parameters are not
|
|
428
|
+
/// overwritten if the same key is used. The key will simply show up
|
|
429
|
+
/// twice in the query string.
|
|
430
|
+
/// Calling `.query(&[("foo", "a"), ("foo", "b")])` gives `"foo=a&foo=b"`.
|
|
431
|
+
///
|
|
432
|
+
/// # Note
|
|
433
|
+
/// This method does not support serializing a single key-value
|
|
434
|
+
/// pair. Instead of using `.query(("key", "val"))`, use a sequence, such
|
|
435
|
+
/// as `.query(&[("key", "val")])`. It's also possible to serialize structs
|
|
436
|
+
/// and maps into a key-value pair.
|
|
437
|
+
///
|
|
438
|
+
/// # Errors
|
|
439
|
+
/// This method will fail if the object you provide cannot be serialized
|
|
440
|
+
/// into a query string.
|
|
441
|
+
#[cfg(feature = "query")]
|
|
442
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "query")))]
|
|
443
|
+
pub fn query<T: Serialize + ?Sized>(mut self, query: &T) -> RequestBuilder {
|
|
444
|
+
let mut error = None;
|
|
445
|
+
if let Ok(ref mut req) = self.request {
|
|
446
|
+
match serde_urlencoded::to_string(query) {
|
|
447
|
+
Ok(serializer) => {
|
|
448
|
+
let uri = req.uri_mut();
|
|
449
|
+
uri.set_query(serializer);
|
|
450
|
+
}
|
|
451
|
+
Err(err) => error = Some(Error::builder(err)),
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if let Some(err) = error {
|
|
455
|
+
self.request = Err(err);
|
|
456
|
+
}
|
|
457
|
+
self
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/// Send a form body.
|
|
461
|
+
///
|
|
462
|
+
/// Sets the body to the uri encoded serialization of the passed value,
|
|
463
|
+
/// and also sets the `Content-Type: application/x-www-form-urlencoded`
|
|
464
|
+
/// header.
|
|
465
|
+
///
|
|
466
|
+
/// ```rust
|
|
467
|
+
/// # use wreq::Error;
|
|
468
|
+
/// # use std::collections::HashMap;
|
|
469
|
+
/// #
|
|
470
|
+
/// # async fn run() -> Result<(), Error> {
|
|
471
|
+
/// let mut params = HashMap::new();
|
|
472
|
+
/// params.insert("lang", "rust");
|
|
473
|
+
///
|
|
474
|
+
/// let client = wreq::Client::new();
|
|
475
|
+
/// let res = client
|
|
476
|
+
/// .post("http://httpbin.org")
|
|
477
|
+
/// .form(¶ms)
|
|
478
|
+
/// .send()
|
|
479
|
+
/// .await?;
|
|
480
|
+
/// # Ok(())
|
|
481
|
+
/// # }
|
|
482
|
+
/// ```
|
|
483
|
+
///
|
|
484
|
+
/// # Errors
|
|
485
|
+
///
|
|
486
|
+
/// This method fails if the passed value cannot be serialized into
|
|
487
|
+
/// uri encoded format
|
|
488
|
+
#[cfg(feature = "form")]
|
|
489
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "form")))]
|
|
490
|
+
pub fn form<T: Serialize + ?Sized>(mut self, form: &T) -> RequestBuilder {
|
|
491
|
+
if let Ok(ref mut req) = self.request {
|
|
492
|
+
match serde_urlencoded::to_string(form) {
|
|
493
|
+
Ok(body) => {
|
|
494
|
+
req.headers_mut().entry(CONTENT_TYPE).or_insert_with(|| {
|
|
495
|
+
HeaderValue::from_static("application/x-www-form-urlencoded")
|
|
496
|
+
});
|
|
497
|
+
*req.body_mut() = Some(body.into());
|
|
498
|
+
}
|
|
499
|
+
Err(err) => self.request = Err(Error::builder(err)),
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
self
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/// Send a JSON body.
|
|
506
|
+
///
|
|
507
|
+
/// # Optional
|
|
508
|
+
///
|
|
509
|
+
/// This requires the optional `json` feature enabled.
|
|
510
|
+
///
|
|
511
|
+
/// # Errors
|
|
512
|
+
///
|
|
513
|
+
/// Serialization can fail if `T`'s implementation of `Serialize` decides to
|
|
514
|
+
/// fail, or if `T` contains a map with non-string keys.
|
|
515
|
+
#[cfg(feature = "json")]
|
|
516
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
|
|
517
|
+
pub fn json<T: Serialize + ?Sized>(mut self, json: &T) -> RequestBuilder {
|
|
518
|
+
if let Ok(ref mut req) = self.request {
|
|
519
|
+
match serde_json::to_vec(json) {
|
|
520
|
+
Ok(body) => {
|
|
521
|
+
req.headers_mut()
|
|
522
|
+
.entry(CONTENT_TYPE)
|
|
523
|
+
.or_insert_with(|| HeaderValue::from_static("application/json"));
|
|
524
|
+
*req.body_mut() = Some(body.into());
|
|
525
|
+
}
|
|
526
|
+
Err(err) => self.request = Err(Error::builder(err)),
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
self
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/// Set HTTP version
|
|
534
|
+
pub fn version(mut self, version: Version) -> RequestBuilder {
|
|
535
|
+
if let Ok(ref mut req) = self.request {
|
|
536
|
+
req.version_mut().replace(version);
|
|
537
|
+
}
|
|
538
|
+
self
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/// Set the redirect policy for this request.
|
|
542
|
+
pub fn redirect(mut self, policy: redirect::Policy) -> RequestBuilder {
|
|
543
|
+
if let Ok(ref mut req) = self.request {
|
|
544
|
+
req.config_mut::<redirect::Policy>().replace(policy);
|
|
545
|
+
}
|
|
546
|
+
self
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/// Set the persistent cookie store for the request.
|
|
550
|
+
#[cfg(feature = "cookies")]
|
|
551
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "cookies")))]
|
|
552
|
+
pub fn cookie_provider<C>(mut self, cookie_store: C) -> RequestBuilder
|
|
553
|
+
where
|
|
554
|
+
C: IntoCookieStore,
|
|
555
|
+
{
|
|
556
|
+
if let Ok(ref mut req) = self.request {
|
|
557
|
+
req.config_mut::<Arc<dyn CookieStore>>()
|
|
558
|
+
.replace(cookie_store.into_cookie_store());
|
|
559
|
+
}
|
|
560
|
+
self
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/// Sets if this request will announce that it accepts gzip encoding.
|
|
564
|
+
#[cfg(feature = "gzip")]
|
|
565
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "gzip")))]
|
|
566
|
+
pub fn gzip(mut self, gzip: bool) -> RequestBuilder {
|
|
567
|
+
if let Ok(ref mut req) = self.request {
|
|
568
|
+
req.config_mut::<AcceptEncoding>()
|
|
569
|
+
.get_or_insert_default()
|
|
570
|
+
.gzip = gzip;
|
|
571
|
+
}
|
|
572
|
+
self
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/// Sets if this request will announce that it accepts brotli encoding.
|
|
576
|
+
#[cfg(feature = "brotli")]
|
|
577
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "brotli")))]
|
|
578
|
+
pub fn brotli(mut self, brotli: bool) -> RequestBuilder {
|
|
579
|
+
if let Ok(ref mut req) = self.request {
|
|
580
|
+
req.config_mut::<AcceptEncoding>()
|
|
581
|
+
.get_or_insert_default()
|
|
582
|
+
.brotli = brotli;
|
|
583
|
+
}
|
|
584
|
+
self
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
/// Sets if this request will announce that it accepts deflate encoding.
|
|
588
|
+
#[cfg(feature = "deflate")]
|
|
589
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "deflate")))]
|
|
590
|
+
pub fn deflate(mut self, deflate: bool) -> RequestBuilder {
|
|
591
|
+
if let Ok(ref mut req) = self.request {
|
|
592
|
+
req.config_mut::<AcceptEncoding>()
|
|
593
|
+
.get_or_insert_default()
|
|
594
|
+
.deflate = deflate;
|
|
595
|
+
}
|
|
596
|
+
self
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/// Sets if this request will announce that it accepts zstd encoding.
|
|
600
|
+
#[cfg(feature = "zstd")]
|
|
601
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "zstd")))]
|
|
602
|
+
pub fn zstd(mut self, zstd: bool) -> RequestBuilder {
|
|
603
|
+
if let Ok(ref mut req) = self.request {
|
|
604
|
+
req.config_mut::<AcceptEncoding>()
|
|
605
|
+
.get_or_insert_default()
|
|
606
|
+
.zstd = zstd;
|
|
607
|
+
}
|
|
608
|
+
self
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/// Set the proxy for this request.
|
|
612
|
+
pub fn proxy(mut self, proxy: Proxy) -> RequestBuilder {
|
|
613
|
+
if let Ok(ref mut req) = self.request {
|
|
614
|
+
req.config_mut::<RequestOptions>()
|
|
615
|
+
.get_or_insert_default()
|
|
616
|
+
.proxy_matcher_mut()
|
|
617
|
+
.replace(proxy.into_matcher());
|
|
618
|
+
}
|
|
619
|
+
self
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/// Set the local address for this request.
|
|
623
|
+
pub fn local_address<V>(mut self, local_address: V) -> RequestBuilder
|
|
624
|
+
where
|
|
625
|
+
V: Into<Option<IpAddr>>,
|
|
626
|
+
{
|
|
627
|
+
if let Ok(ref mut req) = self.request {
|
|
628
|
+
req.config_mut::<RequestOptions>()
|
|
629
|
+
.get_or_insert_default()
|
|
630
|
+
.tcp_connect_opts_mut()
|
|
631
|
+
.set_local_address(local_address.into());
|
|
632
|
+
}
|
|
633
|
+
self
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/// Set the local addresses for this request.
|
|
637
|
+
pub fn local_addresses<V4, V6>(mut self, ipv4: V4, ipv6: V6) -> RequestBuilder
|
|
638
|
+
where
|
|
639
|
+
V4: Into<Option<Ipv4Addr>>,
|
|
640
|
+
V6: Into<Option<Ipv6Addr>>,
|
|
641
|
+
{
|
|
642
|
+
if let Ok(ref mut req) = self.request {
|
|
643
|
+
req.config_mut::<RequestOptions>()
|
|
644
|
+
.get_or_insert_default()
|
|
645
|
+
.tcp_connect_opts_mut()
|
|
646
|
+
.set_local_addresses(ipv4, ipv6);
|
|
647
|
+
}
|
|
648
|
+
self
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/// Set the interface for this request.
|
|
652
|
+
#[cfg(any(
|
|
653
|
+
target_os = "android",
|
|
654
|
+
target_os = "fuchsia",
|
|
655
|
+
target_os = "illumos",
|
|
656
|
+
target_os = "ios",
|
|
657
|
+
target_os = "linux",
|
|
658
|
+
target_os = "macos",
|
|
659
|
+
target_os = "solaris",
|
|
660
|
+
target_os = "tvos",
|
|
661
|
+
target_os = "visionos",
|
|
662
|
+
target_os = "watchos",
|
|
663
|
+
))]
|
|
664
|
+
#[cfg_attr(
|
|
665
|
+
docsrs,
|
|
666
|
+
doc(cfg(any(
|
|
667
|
+
target_os = "android",
|
|
668
|
+
target_os = "fuchsia",
|
|
669
|
+
target_os = "illumos",
|
|
670
|
+
target_os = "ios",
|
|
671
|
+
target_os = "linux",
|
|
672
|
+
target_os = "macos",
|
|
673
|
+
target_os = "solaris",
|
|
674
|
+
target_os = "tvos",
|
|
675
|
+
target_os = "visionos",
|
|
676
|
+
target_os = "watchos",
|
|
677
|
+
)))
|
|
678
|
+
)]
|
|
679
|
+
pub fn interface<I>(mut self, interface: I) -> RequestBuilder
|
|
680
|
+
where
|
|
681
|
+
I: Into<std::borrow::Cow<'static, str>>,
|
|
682
|
+
{
|
|
683
|
+
if let Ok(ref mut req) = self.request {
|
|
684
|
+
req.config_mut::<RequestOptions>()
|
|
685
|
+
.get_or_insert_default()
|
|
686
|
+
.tcp_connect_opts_mut()
|
|
687
|
+
.set_interface(interface);
|
|
688
|
+
}
|
|
689
|
+
self
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/// Set the emulation for this request.
|
|
693
|
+
pub fn emulation<P>(mut self, factory: P) -> RequestBuilder
|
|
694
|
+
where
|
|
695
|
+
P: EmulationFactory,
|
|
696
|
+
{
|
|
697
|
+
if let Ok(ref mut req) = self.request {
|
|
698
|
+
let emulation = factory.emulation();
|
|
699
|
+
let (transport_opts, default_headers, orig_headers) = emulation.into_parts();
|
|
700
|
+
req.config_mut::<RequestOptions>()
|
|
701
|
+
.get_or_insert_default()
|
|
702
|
+
.transport_opts_mut()
|
|
703
|
+
.apply_transport_options(transport_opts);
|
|
704
|
+
self = self.headers(default_headers).orig_headers(orig_headers);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
self
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/// Build a `Request`, which can be inspected, modified and executed with
|
|
711
|
+
/// [`Client::execute()`].
|
|
712
|
+
pub fn build(self) -> crate::Result<Request> {
|
|
713
|
+
self.request
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/// Build a `Request`, which can be inspected, modified and executed with
|
|
717
|
+
/// [`Client::execute()`].
|
|
718
|
+
///
|
|
719
|
+
/// This is similar to [`RequestBuilder::build()`], but also returns the
|
|
720
|
+
/// embedded [`Client`].
|
|
721
|
+
pub fn build_split(self) -> (Client, crate::Result<Request>) {
|
|
722
|
+
(self.client, self.request)
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
/// Constructs the Request and sends it to the target URI, returning a
|
|
726
|
+
/// future Response.
|
|
727
|
+
///
|
|
728
|
+
/// # Errors
|
|
729
|
+
///
|
|
730
|
+
/// This method fails if there was an error while sending request,
|
|
731
|
+
/// redirect loop was detected or redirect limit was exhausted.
|
|
732
|
+
///
|
|
733
|
+
/// # Example
|
|
734
|
+
///
|
|
735
|
+
/// ```no_run
|
|
736
|
+
/// # use wreq::Error;
|
|
737
|
+
/// #
|
|
738
|
+
/// # async fn run() -> Result<(), Error> {
|
|
739
|
+
/// let response = wreq::Client::new().get("https://hyper.rs").send().await?;
|
|
740
|
+
/// # Ok(())
|
|
741
|
+
/// # }
|
|
742
|
+
/// ```
|
|
743
|
+
pub fn send(self) -> impl Future<Output = crate::Result<Response>> {
|
|
744
|
+
match self.request {
|
|
745
|
+
Ok(req) => self.client.execute(req),
|
|
746
|
+
Err(err) => Pending::error(err),
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/// Attempt to clone the RequestBuilder.
|
|
751
|
+
///
|
|
752
|
+
/// `None` is returned if the RequestBuilder can not be cloned,
|
|
753
|
+
/// i.e. if the request body is a stream.
|
|
754
|
+
///
|
|
755
|
+
/// # Examples
|
|
756
|
+
///
|
|
757
|
+
/// ```
|
|
758
|
+
/// # use wreq::Error;
|
|
759
|
+
/// #
|
|
760
|
+
/// # fn run() -> Result<(), Error> {
|
|
761
|
+
/// let client = wreq::Client::new();
|
|
762
|
+
/// let builder = client.post("http://httpbin.org/post").body("from a &str!");
|
|
763
|
+
/// let clone = builder.try_clone();
|
|
764
|
+
/// assert!(clone.is_some());
|
|
765
|
+
/// # Ok(())
|
|
766
|
+
/// # }
|
|
767
|
+
/// ```
|
|
768
|
+
pub fn try_clone(&self) -> Option<RequestBuilder> {
|
|
769
|
+
self.request
|
|
770
|
+
.as_ref()
|
|
771
|
+
.ok()
|
|
772
|
+
.and_then(|req| req.try_clone())
|
|
773
|
+
.map(|req| RequestBuilder {
|
|
774
|
+
client: self.client.clone(),
|
|
775
|
+
request: Ok(req),
|
|
776
|
+
})
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/// Check the request URI for a "username:password" type authority, and if
|
|
781
|
+
/// found, remove it from the URI and return it.
|
|
782
|
+
fn extract_authority(uri: &mut Uri) -> Option<(String, Option<String>)> {
|
|
783
|
+
use percent_encoding::percent_decode;
|
|
784
|
+
|
|
785
|
+
let (username, password) = uri.userinfo();
|
|
786
|
+
|
|
787
|
+
let username: String = percent_decode(username?.as_bytes())
|
|
788
|
+
.decode_utf8()
|
|
789
|
+
.ok()?
|
|
790
|
+
.into();
|
|
791
|
+
let password = password.and_then(|pass| {
|
|
792
|
+
percent_decode(pass.as_bytes())
|
|
793
|
+
.decode_utf8()
|
|
794
|
+
.ok()
|
|
795
|
+
.map(String::from)
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
if !username.is_empty() || password.is_some() {
|
|
799
|
+
uri.set_userinfo("", None);
|
|
800
|
+
return Some((username, password));
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
None
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
impl<T: Into<Body>> From<HttpRequest<T>> for Request {
|
|
807
|
+
#[inline]
|
|
808
|
+
fn from(req: HttpRequest<T>) -> Request {
|
|
809
|
+
Request(req.map(Into::into).map(Some))
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
impl From<Request> for HttpRequest<Body> {
|
|
814
|
+
#[inline]
|
|
815
|
+
fn from(req: Request) -> HttpRequest<Body> {
|
|
816
|
+
req.0.map(|body| body.unwrap_or_else(Body::empty))
|
|
817
|
+
}
|
|
818
|
+
}
|