wreq-rb 0.5.0 → 0.5.1
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 +4 -4
- data/Cargo.lock +1922 -397
- data/LICENSE +203 -0
- data/README.md +19 -15
- data/ext/wreq_rb/Cargo.toml +4 -6
- data/ext/wreq_rb/src/client.rs +41 -48
- data/lib/wreq-rb/version.rb +1 -1
- data/patches/0001-add-transfer-size-tracking.patch +76 -67
- data/vendor/wreq/Cargo.toml +119 -71
- data/vendor/wreq/README.md +25 -20
- data/vendor/wreq/bench/http1.rs +25 -0
- data/vendor/wreq/bench/http1_over_tls.rs +25 -0
- data/vendor/wreq/bench/http2.rs +25 -0
- data/vendor/wreq/bench/http2_over_tls.rs +25 -0
- data/vendor/wreq/bench/support/bench.rs +91 -0
- data/vendor/wreq/bench/support/client.rs +217 -0
- data/vendor/wreq/bench/support/server.rs +188 -0
- data/vendor/wreq/bench/support.rs +56 -0
- data/vendor/wreq/examples/cert_store.rs +4 -4
- data/vendor/wreq/examples/{emulation.rs → emulate.rs} +2 -2
- data/vendor/wreq/examples/http2_websocket.rs +2 -2
- data/vendor/wreq/examples/keylog.rs +3 -3
- data/vendor/wreq/examples/{request_with_emulation.rs → request_with_emulate.rs} +2 -2
- data/vendor/wreq/examples/rt.rs +23 -0
- data/vendor/wreq/src/client/body.rs +23 -61
- data/vendor/wreq/src/client/emulate.rs +119 -0
- data/vendor/wreq/src/client/{http/future.rs → future.rs} +11 -32
- data/vendor/wreq/src/client/{http → layer}/client/pool.rs +66 -61
- data/vendor/wreq/src/client/{http → layer}/client.rs +416 -270
- data/vendor/wreq/src/client/layer/config.rs +27 -6
- data/vendor/wreq/src/client/layer/decoder.rs +9 -4
- data/vendor/wreq/src/client/layer/redirect/future.rs +6 -3
- data/vendor/wreq/src/client/layer/redirect.rs +4 -5
- data/vendor/wreq/src/client/layer/retry.rs +8 -5
- data/vendor/wreq/src/client/layer/timeout/body.rs +15 -6
- data/vendor/wreq/src/client/layer/timeout/future.rs +23 -18
- data/vendor/wreq/src/client/layer/timeout.rs +24 -74
- data/vendor/wreq/src/client/layer.rs +1 -2
- data/vendor/wreq/src/client/multipart.rs +137 -154
- data/vendor/wreq/src/client/request.rs +202 -118
- data/vendor/wreq/src/client/response.rs +46 -45
- data/vendor/wreq/src/client/upgrade.rs +15 -0
- data/vendor/wreq/src/client/ws.rs +73 -25
- data/vendor/wreq/src/client.rs +1655 -17
- data/vendor/wreq/src/config.rs +11 -11
- data/vendor/wreq/src/{client/conn → conn}/connector.rs +139 -137
- data/vendor/wreq/src/conn/descriptor.rs +143 -0
- data/vendor/wreq/src/conn/http.rs +484 -0
- data/vendor/wreq/src/conn/net/io.rs +75 -0
- data/vendor/wreq/src/conn/net/tcp/compio.rs +71 -0
- data/vendor/wreq/src/conn/net/tcp/tokio.rs +57 -0
- data/vendor/wreq/src/conn/net/tcp.rs +561 -0
- data/vendor/wreq/src/conn/net/uds/compio.rs +60 -0
- data/vendor/wreq/src/{client/conn/uds.rs → conn/net/uds/tokio.rs} +18 -12
- data/vendor/wreq/src/conn/net/uds.rs +11 -0
- data/vendor/wreq/src/conn/net.rs +130 -0
- data/vendor/wreq/src/{client/conn → conn}/proxy/socks.rs +2 -9
- data/vendor/wreq/src/{client/conn → conn}/proxy/tunnel.rs +21 -56
- data/vendor/wreq/src/conn/tls_info.rs +47 -0
- data/vendor/wreq/src/{client/conn.rs → conn.rs} +202 -54
- data/vendor/wreq/src/cookie.rs +302 -142
- data/vendor/wreq/src/dns/gai/compio.rs +77 -0
- data/vendor/wreq/src/dns/gai/tokio.rs +90 -0
- data/vendor/wreq/src/dns/gai.rs +14 -164
- data/vendor/wreq/src/dns/hickory.rs +16 -23
- data/vendor/wreq/src/dns/resolve.rs +7 -41
- data/vendor/wreq/src/dns.rs +90 -7
- data/vendor/wreq/src/error.rs +57 -31
- data/vendor/wreq/src/ext.rs +25 -0
- data/vendor/wreq/src/group.rs +211 -0
- data/vendor/wreq/src/header.rs +100 -112
- data/vendor/wreq/src/lib.rs +124 -73
- data/vendor/wreq/src/proxy.rs +6 -20
- data/vendor/wreq/src/redirect.rs +1 -1
- data/vendor/wreq/src/rt.rs +208 -0
- data/vendor/wreq/src/sync.rs +97 -98
- data/vendor/wreq/src/tls/compress.rs +124 -0
- data/vendor/wreq/src/tls/conn/ext.rs +54 -45
- data/vendor/wreq/src/tls/conn/service.rs +14 -18
- data/vendor/wreq/src/tls/conn.rs +169 -241
- data/vendor/wreq/src/tls/keylog.rs +68 -5
- data/vendor/wreq/src/tls/session.rs +205 -0
- data/vendor/wreq/src/tls/{x509 → trust}/identity.rs +4 -21
- data/vendor/wreq/src/tls/{x509/parser.rs → trust/parse.rs} +1 -1
- data/vendor/wreq/src/tls/{x509 → trust}/store.rs +42 -81
- data/vendor/wreq/src/tls/{x509.rs → trust.rs} +8 -2
- data/vendor/wreq/src/tls.rs +489 -25
- data/vendor/wreq/src/trace.rs +0 -12
- data/vendor/wreq/src/util.rs +1 -1
- data/vendor/wreq/tests/badssl.rs +10 -10
- data/vendor/wreq/tests/client.rs +3 -9
- data/vendor/wreq/tests/cookie.rs +6 -8
- data/vendor/wreq/tests/{emulation.rs → emulate.rs} +130 -22
- data/vendor/wreq/tests/multipart.rs +43 -1
- data/vendor/wreq/tests/proxy.rs +1 -1
- data/vendor/wreq/tests/support/layer.rs +1 -0
- metadata +49 -71
- data/patches/0002-add-cancel-connections.patch +0 -181
- data/vendor/wreq/src/client/conn/conn.rs +0 -231
- data/vendor/wreq/src/client/conn/http.rs +0 -1023
- data/vendor/wreq/src/client/conn/tls_info.rs +0 -98
- data/vendor/wreq/src/client/core/body/incoming.rs +0 -485
- data/vendor/wreq/src/client/core/body/length.rs +0 -118
- data/vendor/wreq/src/client/core/body.rs +0 -34
- data/vendor/wreq/src/client/core/common/buf.rs +0 -149
- data/vendor/wreq/src/client/core/common/rewind.rs +0 -141
- data/vendor/wreq/src/client/core/common/watch.rs +0 -76
- data/vendor/wreq/src/client/core/common.rs +0 -3
- data/vendor/wreq/src/client/core/conn/http1.rs +0 -342
- data/vendor/wreq/src/client/core/conn/http2.rs +0 -307
- data/vendor/wreq/src/client/core/conn.rs +0 -11
- data/vendor/wreq/src/client/core/dispatch.rs +0 -299
- data/vendor/wreq/src/client/core/error.rs +0 -435
- data/vendor/wreq/src/client/core/ext.rs +0 -201
- data/vendor/wreq/src/client/core/http1.rs +0 -178
- data/vendor/wreq/src/client/core/http2.rs +0 -483
- data/vendor/wreq/src/client/core/proto/h1/conn.rs +0 -988
- data/vendor/wreq/src/client/core/proto/h1/decode.rs +0 -1170
- data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +0 -684
- data/vendor/wreq/src/client/core/proto/h1/encode.rs +0 -580
- data/vendor/wreq/src/client/core/proto/h1/io.rs +0 -879
- data/vendor/wreq/src/client/core/proto/h1/role.rs +0 -694
- data/vendor/wreq/src/client/core/proto/h1.rs +0 -104
- data/vendor/wreq/src/client/core/proto/h2/client.rs +0 -650
- data/vendor/wreq/src/client/core/proto/h2/ping.rs +0 -539
- data/vendor/wreq/src/client/core/proto/h2.rs +0 -379
- data/vendor/wreq/src/client/core/proto/headers.rs +0 -138
- data/vendor/wreq/src/client/core/proto.rs +0 -58
- data/vendor/wreq/src/client/core/rt/bounds.rs +0 -57
- data/vendor/wreq/src/client/core/rt/timer.rs +0 -150
- data/vendor/wreq/src/client/core/rt/tokio.rs +0 -99
- data/vendor/wreq/src/client/core/rt.rs +0 -25
- data/vendor/wreq/src/client/core/upgrade.rs +0 -267
- data/vendor/wreq/src/client/core.rs +0 -16
- data/vendor/wreq/src/client/emulation.rs +0 -161
- data/vendor/wreq/src/client/http/client/error.rs +0 -142
- data/vendor/wreq/src/client/http/client/exec.rs +0 -29
- data/vendor/wreq/src/client/http/client/extra.rs +0 -77
- data/vendor/wreq/src/client/http/client/util.rs +0 -104
- data/vendor/wreq/src/client/http.rs +0 -1629
- data/vendor/wreq/src/client/layer/config/options.rs +0 -156
- data/vendor/wreq/src/client/layer/cookie.rs +0 -161
- data/vendor/wreq/src/hash.rs +0 -143
- data/vendor/wreq/src/tls/conn/cache.rs +0 -123
- data/vendor/wreq/src/tls/conn/cert_compression.rs +0 -125
- data/vendor/wreq/src/tls/keylog/handle.rs +0 -64
- data/vendor/wreq/src/tls/options.rs +0 -464
- /data/vendor/wreq/src/client/{http → layer}/client/lazy.rs +0 -0
- /data/vendor/wreq/src/{client/conn → conn}/proxy.rs +0 -0
- /data/vendor/wreq/src/{client/conn → conn}/verbose.rs +0 -0
|
@@ -6,16 +6,13 @@ use std::{
|
|
|
6
6
|
time::Duration,
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
#[cfg(any(feature = "form", feature = "json", feature = "multipart"))]
|
|
10
|
+
use http::header::CONTENT_TYPE;
|
|
11
|
+
use http::{Extensions, Uri, Version};
|
|
10
12
|
#[cfg(any(feature = "query", feature = "form", feature = "json"))]
|
|
11
13
|
use serde::Serialize;
|
|
12
14
|
#[cfg(feature = "multipart")]
|
|
13
15
|
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
16
|
|
|
20
17
|
#[cfg(any(
|
|
21
18
|
feature = "gzip",
|
|
@@ -25,19 +22,20 @@ use {
|
|
|
25
22
|
))]
|
|
26
23
|
use super::layer::decoder::AcceptEncoding;
|
|
27
24
|
use super::{
|
|
28
|
-
Body,
|
|
29
|
-
|
|
25
|
+
Body, Client, IntoEmulation, Response,
|
|
26
|
+
future::Pending,
|
|
30
27
|
layer::{
|
|
31
28
|
config::{DefaultHeaders, RequestOptions},
|
|
32
29
|
timeout::TimeoutOptions,
|
|
33
30
|
},
|
|
34
31
|
};
|
|
35
|
-
#[cfg(
|
|
36
|
-
use crate::
|
|
32
|
+
#[cfg(feature = "cookies")]
|
|
33
|
+
use crate::cookie::{CookieStore, IntoCookieStore};
|
|
37
34
|
use crate::{
|
|
38
35
|
Error, Method, Proxy,
|
|
39
36
|
config::{RequestConfig, RequestConfigValue},
|
|
40
37
|
ext::UriExt,
|
|
38
|
+
group::Group,
|
|
41
39
|
header::{AUTHORIZATION, HeaderMap, HeaderName, HeaderValue, OrigHeaderMap},
|
|
42
40
|
redirect,
|
|
43
41
|
};
|
|
@@ -116,15 +114,49 @@ impl Request {
|
|
|
116
114
|
#[inline]
|
|
117
115
|
pub fn version(&self) -> Option<Version> {
|
|
118
116
|
self.config::<RequestOptions>()
|
|
119
|
-
.and_then(
|
|
117
|
+
.and_then(|opts| opts.version)
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
/// Get a mutable reference to the http version.
|
|
123
121
|
#[inline]
|
|
124
122
|
pub fn version_mut(&mut self) -> &mut Option<Version> {
|
|
125
|
-
self
|
|
123
|
+
&mut self
|
|
124
|
+
.config_mut::<RequestOptions>()
|
|
126
125
|
.get_or_insert_default()
|
|
127
|
-
.
|
|
126
|
+
.version
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/// Returns a reference to the associated extensions.
|
|
130
|
+
///
|
|
131
|
+
/// # Examples
|
|
132
|
+
///
|
|
133
|
+
/// ```
|
|
134
|
+
/// # use wreq;
|
|
135
|
+
/// let request = wreq::get("http://httpbin.org/get")
|
|
136
|
+
/// .build()
|
|
137
|
+
/// .expect("failed to build request");
|
|
138
|
+
/// assert!(request.extensions().get::<i32>().is_none());
|
|
139
|
+
/// ```
|
|
140
|
+
#[inline]
|
|
141
|
+
pub fn extensions(&self) -> &Extensions {
|
|
142
|
+
self.0.extensions()
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// Returns a mutable reference to the associated extensions.
|
|
146
|
+
///
|
|
147
|
+
/// # Examples
|
|
148
|
+
///
|
|
149
|
+
/// ```
|
|
150
|
+
/// # use wreq;
|
|
151
|
+
/// let mut request = wreq::get("http://httpbin.org/get")
|
|
152
|
+
/// .build()
|
|
153
|
+
/// .expect("failed to build request");
|
|
154
|
+
/// request.extensions_mut().insert("hello");
|
|
155
|
+
/// assert_eq!(request.extensions().get(), Some(&"hello"));
|
|
156
|
+
/// ```
|
|
157
|
+
#[inline]
|
|
158
|
+
pub fn extensions_mut(&mut self) -> &mut Extensions {
|
|
159
|
+
self.0.extensions_mut()
|
|
128
160
|
}
|
|
129
161
|
|
|
130
162
|
/// Attempt to clone the request.
|
|
@@ -143,16 +175,6 @@ impl Request {
|
|
|
143
175
|
Some(req)
|
|
144
176
|
}
|
|
145
177
|
|
|
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
178
|
#[inline]
|
|
157
179
|
pub(crate) fn config<T>(&self) -> Option<&T::Value>
|
|
158
180
|
where
|
|
@@ -331,10 +353,7 @@ impl RequestBuilder {
|
|
|
331
353
|
/// # Ok(())
|
|
332
354
|
/// # }
|
|
333
355
|
/// ```
|
|
334
|
-
pub fn bearer_auth<T>(self, token: T) -> RequestBuilder
|
|
335
|
-
where
|
|
336
|
-
T: fmt::Display,
|
|
337
|
-
{
|
|
356
|
+
pub fn bearer_auth<T: fmt::Display>(self, token: T) -> RequestBuilder {
|
|
338
357
|
let header_value = format!("Bearer {token}");
|
|
339
358
|
self.header_sensitive(AUTHORIZATION, header_value, true)
|
|
340
359
|
}
|
|
@@ -367,59 +386,6 @@ impl RequestBuilder {
|
|
|
367
386
|
self
|
|
368
387
|
}
|
|
369
388
|
|
|
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
389
|
/// Modify the query string of the URI.
|
|
424
390
|
///
|
|
425
391
|
/// Modifies the URI of this request, adding the parameters provided.
|
|
@@ -443,7 +409,7 @@ impl RequestBuilder {
|
|
|
443
409
|
pub fn query<T: Serialize + ?Sized>(mut self, query: &T) -> RequestBuilder {
|
|
444
410
|
let mut error = None;
|
|
445
411
|
if let Ok(ref mut req) = self.request {
|
|
446
|
-
match
|
|
412
|
+
match serde_html_form::to_string(query) {
|
|
447
413
|
Ok(serializer) => {
|
|
448
414
|
let uri = req.uri_mut();
|
|
449
415
|
uri.set_query(serializer);
|
|
@@ -489,12 +455,15 @@ impl RequestBuilder {
|
|
|
489
455
|
#[cfg_attr(docsrs, doc(cfg(feature = "form")))]
|
|
490
456
|
pub fn form<T: Serialize + ?Sized>(mut self, form: &T) -> RequestBuilder {
|
|
491
457
|
if let Ok(ref mut req) = self.request {
|
|
492
|
-
match
|
|
458
|
+
match serde_html_form::to_string(form) {
|
|
493
459
|
Ok(body) => {
|
|
494
|
-
|
|
495
|
-
HeaderValue::from_static("application/x-www-form-urlencoded")
|
|
496
|
-
|
|
497
|
-
|
|
460
|
+
const HEADER_VALUE: HeaderValue =
|
|
461
|
+
HeaderValue::from_static("application/x-www-form-urlencoded");
|
|
462
|
+
|
|
463
|
+
req.headers_mut()
|
|
464
|
+
.entry(CONTENT_TYPE)
|
|
465
|
+
.or_insert(HEADER_VALUE);
|
|
466
|
+
req.body_mut().replace(body.into());
|
|
498
467
|
}
|
|
499
468
|
Err(err) => self.request = Err(Error::builder(err)),
|
|
500
469
|
}
|
|
@@ -518,10 +487,12 @@ impl RequestBuilder {
|
|
|
518
487
|
if let Ok(ref mut req) = self.request {
|
|
519
488
|
match serde_json::to_vec(json) {
|
|
520
489
|
Ok(body) => {
|
|
490
|
+
const HEADER_VALUE: HeaderValue = HeaderValue::from_static("application/json");
|
|
491
|
+
|
|
521
492
|
req.headers_mut()
|
|
522
493
|
.entry(CONTENT_TYPE)
|
|
523
|
-
.
|
|
524
|
-
|
|
494
|
+
.or_insert(HEADER_VALUE);
|
|
495
|
+
req.body_mut().replace(body.into());
|
|
525
496
|
}
|
|
526
497
|
Err(err) => self.request = Err(Error::builder(err)),
|
|
527
498
|
}
|
|
@@ -530,10 +501,66 @@ impl RequestBuilder {
|
|
|
530
501
|
self
|
|
531
502
|
}
|
|
532
503
|
|
|
504
|
+
/// Set the request body.
|
|
505
|
+
pub fn body<T: Into<Body>>(mut self, body: T) -> RequestBuilder {
|
|
506
|
+
if let Ok(ref mut req) = self.request {
|
|
507
|
+
*req.body_mut() = Some(body.into());
|
|
508
|
+
}
|
|
509
|
+
self
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/// Sends a multipart/form-data body.
|
|
513
|
+
///
|
|
514
|
+
/// ```
|
|
515
|
+
/// # use wreq::Error;
|
|
516
|
+
///
|
|
517
|
+
/// # async fn run() -> Result<(), Error> {
|
|
518
|
+
/// let client = wreq::Client::new();
|
|
519
|
+
/// let form = wreq::multipart::Form::new()
|
|
520
|
+
/// .text("key3", "value3")
|
|
521
|
+
/// .text("key4", "value4");
|
|
522
|
+
///
|
|
523
|
+
/// let response = client.post("your uri").multipart(form).send().await?;
|
|
524
|
+
/// # Ok(())
|
|
525
|
+
/// # }
|
|
526
|
+
/// ```
|
|
527
|
+
#[cfg(feature = "multipart")]
|
|
528
|
+
#[cfg_attr(docsrs, doc(cfg(feature = "multipart")))]
|
|
529
|
+
pub fn multipart(mut self, mut multipart: multipart::Form) -> RequestBuilder {
|
|
530
|
+
if let Ok(ref mut req) = self.request {
|
|
531
|
+
match HeaderValue::from_maybe_shared(Bytes::from(format!(
|
|
532
|
+
"multipart/form-data; boundary={}",
|
|
533
|
+
multipart.boundary()
|
|
534
|
+
))) {
|
|
535
|
+
Ok(content_type) => {
|
|
536
|
+
req.headers_mut()
|
|
537
|
+
.entry(CONTENT_TYPE)
|
|
538
|
+
.or_insert(content_type);
|
|
539
|
+
|
|
540
|
+
if let Some(length) = multipart.compute_length() {
|
|
541
|
+
req.headers_mut()
|
|
542
|
+
.entry(CONTENT_LENGTH)
|
|
543
|
+
.or_insert_with(|| HeaderValue::from(length));
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
*req.body_mut() = Some(multipart.stream())
|
|
547
|
+
}
|
|
548
|
+
Err(err) => {
|
|
549
|
+
self.request = Err(Error::builder(err));
|
|
550
|
+
}
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
self
|
|
555
|
+
}
|
|
556
|
+
|
|
533
557
|
/// Set HTTP version
|
|
534
558
|
pub fn version(mut self, version: Version) -> RequestBuilder {
|
|
535
559
|
if let Ok(ref mut req) = self.request {
|
|
536
560
|
req.version_mut().replace(version);
|
|
561
|
+
req.config_mut::<RequestOptions>()
|
|
562
|
+
.get_or_insert_default()
|
|
563
|
+
.version = Some(version);
|
|
537
564
|
}
|
|
538
565
|
self
|
|
539
566
|
}
|
|
@@ -549,13 +576,12 @@ impl RequestBuilder {
|
|
|
549
576
|
/// Set the persistent cookie store for the request.
|
|
550
577
|
#[cfg(feature = "cookies")]
|
|
551
578
|
#[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
|
-
{
|
|
579
|
+
pub fn cookie_provider<C: IntoCookieStore>(mut self, cookie_store: C) -> RequestBuilder {
|
|
556
580
|
if let Ok(ref mut req) = self.request {
|
|
581
|
+
use std::sync::Arc;
|
|
582
|
+
|
|
557
583
|
req.config_mut::<Arc<dyn CookieStore>>()
|
|
558
|
-
.replace(cookie_store.
|
|
584
|
+
.replace(cookie_store.into_shared());
|
|
559
585
|
}
|
|
560
586
|
self
|
|
561
587
|
}
|
|
@@ -613,8 +639,7 @@ impl RequestBuilder {
|
|
|
613
639
|
if let Ok(ref mut req) = self.request {
|
|
614
640
|
req.config_mut::<RequestOptions>()
|
|
615
641
|
.get_or_insert_default()
|
|
616
|
-
.
|
|
617
|
-
.replace(proxy.into_matcher());
|
|
642
|
+
.proxy = Some(proxy.into_matcher());
|
|
618
643
|
}
|
|
619
644
|
self
|
|
620
645
|
}
|
|
@@ -627,14 +652,15 @@ impl RequestBuilder {
|
|
|
627
652
|
if let Ok(ref mut req) = self.request {
|
|
628
653
|
req.config_mut::<RequestOptions>()
|
|
629
654
|
.get_or_insert_default()
|
|
630
|
-
.
|
|
631
|
-
.
|
|
655
|
+
.socket_bind_options
|
|
656
|
+
.get_or_insert_default()
|
|
657
|
+
.set_local_address(local_address);
|
|
632
658
|
}
|
|
633
659
|
self
|
|
634
660
|
}
|
|
635
661
|
|
|
636
662
|
/// Set the local addresses for this request.
|
|
637
|
-
pub fn local_addresses<V4, V6>(mut self,
|
|
663
|
+
pub fn local_addresses<V4, V6>(mut self, ipv4_address: V4, ipv6_address: V6) -> RequestBuilder
|
|
638
664
|
where
|
|
639
665
|
V4: Into<Option<Ipv4Addr>>,
|
|
640
666
|
V6: Into<Option<Ipv6Addr>>,
|
|
@@ -642,13 +668,45 @@ impl RequestBuilder {
|
|
|
642
668
|
if let Ok(ref mut req) = self.request {
|
|
643
669
|
req.config_mut::<RequestOptions>()
|
|
644
670
|
.get_or_insert_default()
|
|
645
|
-
.
|
|
646
|
-
.
|
|
671
|
+
.socket_bind_options
|
|
672
|
+
.get_or_insert_default()
|
|
673
|
+
.set_local_addresses(ipv4_address, ipv6_address);
|
|
647
674
|
}
|
|
648
675
|
self
|
|
649
676
|
}
|
|
650
677
|
|
|
651
|
-
///
|
|
678
|
+
/// Bind connections only on the specified network interface.
|
|
679
|
+
///
|
|
680
|
+
/// This option is only available on the following operating systems:
|
|
681
|
+
///
|
|
682
|
+
/// - Android
|
|
683
|
+
/// - Fuchsia
|
|
684
|
+
/// - Linux,
|
|
685
|
+
/// - macOS and macOS-like systems (iOS, tvOS, watchOS and visionOS)
|
|
686
|
+
/// - Solaris and illumos
|
|
687
|
+
///
|
|
688
|
+
/// On Android, Linux, and Fuchsia, this uses the
|
|
689
|
+
/// [`SO_BINDTODEVICE`][man-7-socket] socket option. On macOS and macOS-like
|
|
690
|
+
/// systems, Solaris, and illumos, this instead uses the [`IP_BOUND_IF` and
|
|
691
|
+
/// `IPV6_BOUND_IF`][man-7p-ip] socket options (as appropriate).
|
|
692
|
+
///
|
|
693
|
+
/// Note that connections will fail if the provided interface name is not a
|
|
694
|
+
/// network interface that currently exists when a connection is established.
|
|
695
|
+
///
|
|
696
|
+
/// # Example
|
|
697
|
+
///
|
|
698
|
+
/// ```
|
|
699
|
+
/// # fn doc() -> Result<(), wreq::Error> {
|
|
700
|
+
/// let interface = "lo";
|
|
701
|
+
/// let client = wreq::Client::builder()
|
|
702
|
+
/// .interface(interface)
|
|
703
|
+
/// .build()?;
|
|
704
|
+
/// # Ok(())
|
|
705
|
+
/// # }
|
|
706
|
+
/// ```
|
|
707
|
+
///
|
|
708
|
+
/// [man-7-socket]: https://man7.org/linux/man-pages/man7/socket.7.html
|
|
709
|
+
/// [man-7p-ip]: https://docs.oracle.com/cd/E86824_01/html/E54777/ip-7p.html
|
|
652
710
|
#[cfg(any(
|
|
653
711
|
target_os = "android",
|
|
654
712
|
target_os = "fuchsia",
|
|
@@ -683,32 +741,57 @@ impl RequestBuilder {
|
|
|
683
741
|
if let Ok(ref mut req) = self.request {
|
|
684
742
|
req.config_mut::<RequestOptions>()
|
|
685
743
|
.get_or_insert_default()
|
|
686
|
-
.
|
|
744
|
+
.socket_bind_options
|
|
745
|
+
.get_or_insert_default()
|
|
687
746
|
.set_interface(interface);
|
|
688
747
|
}
|
|
689
748
|
self
|
|
690
749
|
}
|
|
691
750
|
|
|
692
|
-
///
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
751
|
+
/// Sets the request builder to emulation the specified HTTP context.
|
|
752
|
+
///
|
|
753
|
+
/// This method sets the necessary headers, HTTP/1 and HTTP/2 options configurations, and TLS
|
|
754
|
+
/// options config to use the specified HTTP context. It allows the client to mimic the
|
|
755
|
+
/// behavior of different versions or setups, which can be useful for testing or ensuring
|
|
756
|
+
/// compatibility with various environments.
|
|
757
|
+
///
|
|
758
|
+
/// # Note
|
|
759
|
+
/// This will overwrite the existing configuration.
|
|
760
|
+
/// You must set emulation before you can perform subsequent HTTP1/HTTP2/TLS fine-tuning.
|
|
761
|
+
pub fn emulation<T: IntoEmulation>(mut self, emulation: T) -> RequestBuilder {
|
|
762
|
+
if let Ok(ref mut req) = self.request {
|
|
763
|
+
let emulation = emulation.into_emulation();
|
|
764
|
+
let opts = req.config_mut::<RequestOptions>().get_or_insert_default();
|
|
765
|
+
opts.group.emulate(emulation.group);
|
|
766
|
+
opts.tls_options = emulation.tls_options;
|
|
767
|
+
opts.http1_options = emulation.http1_options;
|
|
768
|
+
opts.http2_options = emulation.http2_options;
|
|
769
|
+
return self
|
|
770
|
+
.headers(emulation.headers)
|
|
771
|
+
.orig_headers(emulation.orig_headers);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
self
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/// Assigns a logical group to this request.
|
|
778
|
+
///
|
|
779
|
+
/// Groups define the request's identity and execution context.
|
|
780
|
+
/// Requests in different groups are logically partitioned to ensure
|
|
781
|
+
/// resource isolation and prevent metadata leakage.
|
|
782
|
+
pub fn group(mut self, group: Group) -> RequestBuilder {
|
|
697
783
|
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
784
|
req.config_mut::<RequestOptions>()
|
|
701
785
|
.get_or_insert_default()
|
|
702
|
-
.
|
|
703
|
-
.
|
|
704
|
-
self = self.headers(default_headers).orig_headers(orig_headers);
|
|
786
|
+
.group
|
|
787
|
+
.request(group);
|
|
705
788
|
}
|
|
706
|
-
|
|
707
789
|
self
|
|
708
790
|
}
|
|
709
791
|
|
|
710
792
|
/// Build a `Request`, which can be inspected, modified and executed with
|
|
711
793
|
/// [`Client::execute()`].
|
|
794
|
+
#[inline]
|
|
712
795
|
pub fn build(self) -> crate::Result<Request> {
|
|
713
796
|
self.request
|
|
714
797
|
}
|
|
@@ -718,6 +801,7 @@ impl RequestBuilder {
|
|
|
718
801
|
///
|
|
719
802
|
/// This is similar to [`RequestBuilder::build()`], but also returns the
|
|
720
803
|
/// embedded [`Client`].
|
|
804
|
+
#[inline]
|
|
721
805
|
pub fn build_split(self) -> (Client, crate::Result<Request>) {
|
|
722
806
|
(self.client, self.request)
|
|
723
807
|
}
|
|
@@ -743,7 +827,7 @@ impl RequestBuilder {
|
|
|
743
827
|
pub fn send(self) -> impl Future<Output = crate::Result<Response>> {
|
|
744
828
|
match self.request {
|
|
745
829
|
Ok(req) => self.client.execute(req),
|
|
746
|
-
Err(err) => Pending::error(err),
|
|
830
|
+
Err(err) => Pending::Error { error: Some(err) },
|
|
747
831
|
}
|
|
748
832
|
}
|
|
749
833
|
|
|
@@ -803,16 +887,16 @@ fn extract_authority(uri: &mut Uri) -> Option<(String, Option<String>)> {
|
|
|
803
887
|
None
|
|
804
888
|
}
|
|
805
889
|
|
|
806
|
-
impl<T: Into<Body>> From<
|
|
890
|
+
impl<T: Into<Body>> From<http::Request<T>> for Request {
|
|
807
891
|
#[inline]
|
|
808
|
-
fn from(req:
|
|
892
|
+
fn from(req: http::Request<T>) -> Request {
|
|
809
893
|
Request(req.map(Into::into).map(Some))
|
|
810
894
|
}
|
|
811
895
|
}
|
|
812
896
|
|
|
813
|
-
impl From<Request> for
|
|
897
|
+
impl From<Request> for http::Request<Body> {
|
|
814
898
|
#[inline]
|
|
815
|
-
fn from(req: Request) ->
|
|
899
|
+
fn from(req: Request) -> http::Request<Body> {
|
|
816
900
|
req.0.map(|body| body.unwrap_or_else(Body::empty))
|
|
817
901
|
}
|
|
818
902
|
}
|
|
@@ -16,14 +16,16 @@ use http_body_util::{BodyExt, Collected};
|
|
|
16
16
|
use mime::Mime;
|
|
17
17
|
#[cfg(feature = "json")]
|
|
18
18
|
use serde::de::DeserializeOwned;
|
|
19
|
+
use wreq_proto::ext::ReasonPhrase;
|
|
19
20
|
|
|
20
|
-
use super::{
|
|
21
|
-
conn::HttpInfo,
|
|
22
|
-
core::{ext::ReasonPhrase, upgrade},
|
|
23
|
-
};
|
|
24
21
|
#[cfg(feature = "cookies")]
|
|
25
22
|
use crate::cookie;
|
|
26
|
-
use crate::{
|
|
23
|
+
use crate::{
|
|
24
|
+
Body, Error,
|
|
25
|
+
conn::{Connected, http::HttpInfo},
|
|
26
|
+
error::BoxError,
|
|
27
|
+
ext::RequestUri,
|
|
28
|
+
};
|
|
27
29
|
|
|
28
30
|
/// A Response to a submitted [`crate::Request`].
|
|
29
31
|
#[derive(Debug)]
|
|
@@ -33,14 +35,18 @@ pub struct Response {
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
impl Response {
|
|
36
|
-
|
|
38
|
+
#[inline]
|
|
39
|
+
pub(super) fn new<B>(mut res: http::Response<B>, uri: Uri) -> Response
|
|
37
40
|
where
|
|
38
41
|
B: HttpBody + Send + Sync + 'static,
|
|
39
42
|
B::Data: Into<Bytes>,
|
|
40
43
|
B::Error: Into<BoxError>,
|
|
41
44
|
{
|
|
42
45
|
Response {
|
|
43
|
-
uri
|
|
46
|
+
uri: res
|
|
47
|
+
.extensions_mut()
|
|
48
|
+
.remove::<RequestUri>()
|
|
49
|
+
.map_or(uri, |request_uri| request_uri.0),
|
|
44
50
|
res: res.map(Body::wrap),
|
|
45
51
|
}
|
|
46
52
|
}
|
|
@@ -269,8 +275,15 @@ impl Response {
|
|
|
269
275
|
#[cfg(feature = "json")]
|
|
270
276
|
#[cfg_attr(docsrs, doc(cfg(feature = "json")))]
|
|
271
277
|
pub async fn json<T: DeserializeOwned>(self) -> crate::Result<T> {
|
|
272
|
-
|
|
273
|
-
|
|
278
|
+
match http_body_util::BodyExt::collect(self.res.into_body())
|
|
279
|
+
.await
|
|
280
|
+
.map(Collected::<Bytes>::to_bytes)
|
|
281
|
+
{
|
|
282
|
+
Ok(full) => serde_json::from_slice(&full)
|
|
283
|
+
.map_err(Error::decode)
|
|
284
|
+
.map_err(|err| err.with_uri(self.uri)),
|
|
285
|
+
Err(err) => Err(err.with_uri(self.uri)),
|
|
286
|
+
}
|
|
274
287
|
}
|
|
275
288
|
|
|
276
289
|
/// Get the full response body as [`Bytes`].
|
|
@@ -290,38 +303,12 @@ impl Response {
|
|
|
290
303
|
/// # Ok(())
|
|
291
304
|
/// # }
|
|
292
305
|
/// ```
|
|
306
|
+
#[inline]
|
|
293
307
|
pub async fn bytes(self) -> crate::Result<Bytes> {
|
|
294
308
|
BodyExt::collect(self.res.into_body())
|
|
295
309
|
.await
|
|
296
310
|
.map(Collected::<Bytes>::to_bytes)
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
/// Stream a chunk of the response body.
|
|
300
|
-
///
|
|
301
|
-
/// When the response body has been exhausted, this will return `None`.
|
|
302
|
-
///
|
|
303
|
-
/// # Example
|
|
304
|
-
///
|
|
305
|
-
/// ```
|
|
306
|
-
/// # async fn run() -> Result<(), Box<dyn std::error::Error>> {
|
|
307
|
-
/// let mut res = wreq::get("https://hyper.rs").send().await?;
|
|
308
|
-
///
|
|
309
|
-
/// while let Some(chunk) = res.chunk().await? {
|
|
310
|
-
/// println!("Chunk: {chunk:?}");
|
|
311
|
-
/// }
|
|
312
|
-
/// # Ok(())
|
|
313
|
-
/// # }
|
|
314
|
-
/// ```
|
|
315
|
-
pub async fn chunk(&mut self) -> crate::Result<Option<Bytes>> {
|
|
316
|
-
loop {
|
|
317
|
-
if let Some(res) = self.res.body_mut().frame().await {
|
|
318
|
-
if let Ok(buf) = res?.into_data() {
|
|
319
|
-
return Ok(Some(buf));
|
|
320
|
-
}
|
|
321
|
-
} else {
|
|
322
|
-
return Ok(None);
|
|
323
|
-
}
|
|
324
|
-
}
|
|
311
|
+
.map_err(|err| err.with_uri(self.uri))
|
|
325
312
|
}
|
|
326
313
|
|
|
327
314
|
/// Convert the response into a [`Stream`] of [`Bytes`] from the body.
|
|
@@ -348,6 +335,7 @@ impl Response {
|
|
|
348
335
|
/// # Optional
|
|
349
336
|
///
|
|
350
337
|
/// This requires the optional `stream` feature to be enabled.
|
|
338
|
+
#[inline]
|
|
351
339
|
#[cfg(feature = "stream")]
|
|
352
340
|
#[cfg_attr(docsrs, doc(cfg(feature = "stream")))]
|
|
353
341
|
pub fn bytes_stream(self) -> impl Stream<Item = crate::Result<Bytes>> {
|
|
@@ -414,6 +402,23 @@ impl Response {
|
|
|
414
402
|
self.res.extensions_mut()
|
|
415
403
|
}
|
|
416
404
|
|
|
405
|
+
/// Forbids the [`Response`] connection from being recycled back into the pool.
|
|
406
|
+
///
|
|
407
|
+
/// This marks the underlying connection as "poisoned." Once marked, the connection
|
|
408
|
+
/// will be discarded instead of reused after the current request-response cycle completes.
|
|
409
|
+
///
|
|
410
|
+
/// # Note on Lifecycle
|
|
411
|
+
/// Marking the connection does not trigger an immediate shutdown. For pooled
|
|
412
|
+
/// connections, the physical closure is deferred until the `Response` body
|
|
413
|
+
/// is dropped or the pool's background cleaner reclaims the resource.
|
|
414
|
+
#[inline]
|
|
415
|
+
pub fn forbid_recycle(&self) {
|
|
416
|
+
self.res
|
|
417
|
+
.extensions()
|
|
418
|
+
.get::<Connected>()
|
|
419
|
+
.map(Connected::poison);
|
|
420
|
+
}
|
|
421
|
+
|
|
417
422
|
// util methods
|
|
418
423
|
|
|
419
424
|
/// Turn a response into an error if the server returned an error.
|
|
@@ -471,11 +476,6 @@ impl Response {
|
|
|
471
476
|
Ok(self)
|
|
472
477
|
}
|
|
473
478
|
}
|
|
474
|
-
|
|
475
|
-
/// Consumes the [`Response`] and returns a future for a possible HTTP upgrade.
|
|
476
|
-
pub async fn upgrade(self) -> crate::Result<Upgraded> {
|
|
477
|
-
upgrade::on(self.res).await.map_err(Error::upgrade)
|
|
478
|
-
}
|
|
479
479
|
}
|
|
480
480
|
|
|
481
481
|
/// I'm not sure this conversion is that useful... People should be encouraged
|
|
@@ -503,6 +503,7 @@ impl From<Response> for http::Response<Body> {
|
|
|
503
503
|
|
|
504
504
|
/// A [`Response`] can be piped as the [`Body`] of another request.
|
|
505
505
|
impl From<Response> for Body {
|
|
506
|
+
#[inline]
|
|
506
507
|
fn from(r: Response) -> Body {
|
|
507
508
|
Body::wrap(r.res.into_body())
|
|
508
509
|
}
|
|
@@ -514,7 +515,7 @@ impl HttpBody for Response {
|
|
|
514
515
|
|
|
515
516
|
type Error = Error;
|
|
516
517
|
|
|
517
|
-
#[inline]
|
|
518
|
+
#[inline(always)]
|
|
518
519
|
fn poll_frame(
|
|
519
520
|
mut self: Pin<&mut Self>,
|
|
520
521
|
cx: &mut Context<'_>,
|
|
@@ -522,12 +523,12 @@ impl HttpBody for Response {
|
|
|
522
523
|
Pin::new(self.res.body_mut()).poll_frame(cx)
|
|
523
524
|
}
|
|
524
525
|
|
|
525
|
-
#[inline]
|
|
526
|
+
#[inline(always)]
|
|
526
527
|
fn is_end_stream(&self) -> bool {
|
|
527
528
|
self.res.body().is_end_stream()
|
|
528
529
|
}
|
|
529
530
|
|
|
530
|
-
#[inline]
|
|
531
|
+
#[inline(always)]
|
|
531
532
|
fn size_hint(&self) -> http_body::SizeHint {
|
|
532
533
|
self.res.body().size_hint()
|
|
533
534
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
pub use upgrade::Upgraded;
|
|
2
|
+
use wreq_proto::upgrade;
|
|
3
|
+
|
|
4
|
+
use super::response::Response;
|
|
5
|
+
use crate::Error;
|
|
6
|
+
|
|
7
|
+
impl Response {
|
|
8
|
+
/// Consumes the [`Response`] and returns a future for a possible HTTP upgrade.
|
|
9
|
+
#[inline]
|
|
10
|
+
pub async fn upgrade(self) -> crate::Result<Upgraded> {
|
|
11
|
+
upgrade::on(http::Response::from(self))
|
|
12
|
+
.await
|
|
13
|
+
.map_err(Error::upgrade)
|
|
14
|
+
}
|
|
15
|
+
}
|