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,161 @@
|
|
|
1
|
+
use http::HeaderMap;
|
|
2
|
+
|
|
3
|
+
use super::{
|
|
4
|
+
core::{http1::Http1Options, http2::Http2Options},
|
|
5
|
+
layer::config::TransportOptions,
|
|
6
|
+
};
|
|
7
|
+
use crate::{header::OrigHeaderMap, tls::TlsOptions};
|
|
8
|
+
|
|
9
|
+
/// Factory trait for creating emulation configurations.
|
|
10
|
+
///
|
|
11
|
+
/// This trait allows different types (enums, structs, etc.) to provide
|
|
12
|
+
/// their own emulation configurations. It's particularly useful for:
|
|
13
|
+
/// - Predefined browser profiles
|
|
14
|
+
/// - Dynamic configuration based on runtime conditions
|
|
15
|
+
/// - User-defined custom emulation strategies
|
|
16
|
+
pub trait EmulationFactory {
|
|
17
|
+
/// Creates an [`Emulation`] instance from this factory.
|
|
18
|
+
fn emulation(self) -> Emulation;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// Builder for creating an [`Emulation`] configuration.
|
|
22
|
+
#[derive(Debug)]
|
|
23
|
+
#[must_use]
|
|
24
|
+
pub struct EmulationBuilder {
|
|
25
|
+
emulation: Emulation,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/// HTTP emulation configuration for mimicking different HTTP clients.
|
|
29
|
+
///
|
|
30
|
+
/// This struct combines transport-layer options (HTTP/1, HTTP/2, TLS) with
|
|
31
|
+
/// request-level settings (headers, header case preservation) to provide
|
|
32
|
+
/// a complete emulation profile for web browsers, mobile applications,
|
|
33
|
+
/// API clients, and other HTTP implementations.
|
|
34
|
+
#[derive(Debug, Clone, Default)]
|
|
35
|
+
#[non_exhaustive]
|
|
36
|
+
pub struct Emulation {
|
|
37
|
+
headers: HeaderMap,
|
|
38
|
+
orig_headers: OrigHeaderMap,
|
|
39
|
+
transport: TransportOptions,
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// ==== impl EmulationBuilder ====
|
|
43
|
+
|
|
44
|
+
impl EmulationBuilder {
|
|
45
|
+
/// Sets the HTTP/1 options configuration.
|
|
46
|
+
#[inline]
|
|
47
|
+
pub fn http1_options(mut self, opts: Http1Options) -> Self {
|
|
48
|
+
*self.emulation.http1_options_mut() = Some(opts);
|
|
49
|
+
self
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/// Sets the HTTP/2 options configuration.
|
|
53
|
+
#[inline]
|
|
54
|
+
pub fn http2_options(mut self, opts: Http2Options) -> Self {
|
|
55
|
+
*self.emulation.http2_options_mut() = Some(opts);
|
|
56
|
+
self
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// Sets the TLS options configuration.
|
|
60
|
+
#[inline]
|
|
61
|
+
pub fn tls_options(mut self, opts: TlsOptions) -> Self {
|
|
62
|
+
*self.emulation.tls_options_mut() = Some(opts);
|
|
63
|
+
self
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// Sets the default headers.
|
|
67
|
+
#[inline]
|
|
68
|
+
pub fn headers(mut self, src: HeaderMap) -> Self {
|
|
69
|
+
crate::util::replace_headers(&mut self.emulation.headers, src);
|
|
70
|
+
self
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// Sets the original headers.
|
|
74
|
+
#[inline]
|
|
75
|
+
pub fn orig_headers(mut self, src: OrigHeaderMap) -> Self {
|
|
76
|
+
self.emulation.orig_headers.extend(src);
|
|
77
|
+
self
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Builds the [`Emulation`] instance.
|
|
81
|
+
#[inline]
|
|
82
|
+
pub fn build(self) -> Emulation {
|
|
83
|
+
self.emulation
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ==== impl Emulation ====
|
|
88
|
+
|
|
89
|
+
impl Emulation {
|
|
90
|
+
/// Creates a new [`EmulationBuilder`].
|
|
91
|
+
#[inline]
|
|
92
|
+
pub fn builder() -> EmulationBuilder {
|
|
93
|
+
EmulationBuilder {
|
|
94
|
+
emulation: Emulation::default(),
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// Returns a mutable reference to the TLS options, if set.
|
|
99
|
+
#[inline]
|
|
100
|
+
pub fn tls_options_mut(&mut self) -> &mut Option<TlsOptions> {
|
|
101
|
+
self.transport.tls_options_mut()
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/// Returns a mutable reference to the HTTP/1 options, if set.
|
|
105
|
+
#[inline]
|
|
106
|
+
pub fn http1_options_mut(&mut self) -> &mut Option<Http1Options> {
|
|
107
|
+
self.transport.http1_options_mut()
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// Returns a mutable reference to the HTTP/2 options, if set.
|
|
111
|
+
#[inline]
|
|
112
|
+
pub fn http2_options_mut(&mut self) -> &mut Option<Http2Options> {
|
|
113
|
+
self.transport.http2_options_mut()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// Returns a mutable reference to the emulation headers, if set.
|
|
117
|
+
#[inline]
|
|
118
|
+
pub fn headers_mut(&mut self) -> &mut HeaderMap {
|
|
119
|
+
&mut self.headers
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// Returns a mutable reference to the original headers, if set.
|
|
123
|
+
#[inline]
|
|
124
|
+
pub fn orig_headers_mut(&mut self) -> &mut OrigHeaderMap {
|
|
125
|
+
&mut self.orig_headers
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/// Decomposes the [`Emulation`] into its components.
|
|
129
|
+
#[inline]
|
|
130
|
+
pub(crate) fn into_parts(self) -> (TransportOptions, HeaderMap, OrigHeaderMap) {
|
|
131
|
+
(self.transport, self.headers, self.orig_headers)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
impl EmulationFactory for Emulation {
|
|
136
|
+
#[inline]
|
|
137
|
+
fn emulation(self) -> Emulation {
|
|
138
|
+
self
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
impl EmulationFactory for Http1Options {
|
|
143
|
+
#[inline]
|
|
144
|
+
fn emulation(self) -> Emulation {
|
|
145
|
+
Emulation::builder().http1_options(self).build()
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
impl EmulationFactory for Http2Options {
|
|
150
|
+
#[inline]
|
|
151
|
+
fn emulation(self) -> Emulation {
|
|
152
|
+
Emulation::builder().http2_options(self).build()
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
impl EmulationFactory for TlsOptions {
|
|
157
|
+
#[inline]
|
|
158
|
+
fn emulation(self) -> Emulation {
|
|
159
|
+
Emulation::builder().tls_options(self).build()
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
use std::{error::Error as StdError, fmt};
|
|
2
|
+
|
|
3
|
+
use http::Request;
|
|
4
|
+
|
|
5
|
+
use super::pool;
|
|
6
|
+
#[cfg(feature = "socks")]
|
|
7
|
+
use crate::client::conn::socks;
|
|
8
|
+
use crate::{
|
|
9
|
+
client::{
|
|
10
|
+
conn::{Connected, tunnel},
|
|
11
|
+
core::{self},
|
|
12
|
+
},
|
|
13
|
+
error::{BoxError, ProxyConnect},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
#[derive(Debug)]
|
|
17
|
+
pub struct Error {
|
|
18
|
+
pub(super) kind: ErrorKind,
|
|
19
|
+
pub(super) source: Option<BoxError>,
|
|
20
|
+
pub(super) connect_info: Option<Connected>,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[derive(Debug)]
|
|
24
|
+
pub(super) enum ErrorKind {
|
|
25
|
+
Canceled,
|
|
26
|
+
ChannelClosed,
|
|
27
|
+
Connect,
|
|
28
|
+
ProxyConnect,
|
|
29
|
+
UserUnsupportedRequestMethod,
|
|
30
|
+
UserUnsupportedVersion,
|
|
31
|
+
UserAbsoluteUriRequired,
|
|
32
|
+
SendRequest,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pub(super) enum ClientConnectError {
|
|
36
|
+
Normal(Error),
|
|
37
|
+
CheckoutIsClosed(pool::Error),
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#[allow(clippy::large_enum_variant)]
|
|
41
|
+
pub(super) enum TrySendError<B> {
|
|
42
|
+
Retryable {
|
|
43
|
+
error: Error,
|
|
44
|
+
req: Request<B>,
|
|
45
|
+
connection_reused: bool,
|
|
46
|
+
},
|
|
47
|
+
Nope(Error),
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ==== impl Error ====
|
|
51
|
+
|
|
52
|
+
impl fmt::Display for Error {
|
|
53
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
54
|
+
write!(f, "client error ({:?})", self.kind)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
impl StdError for Error {
|
|
59
|
+
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
|
60
|
+
self.source.as_ref().map(|e| &**e as _)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
impl Error {
|
|
65
|
+
pub(super) fn new<E>(kind: ErrorKind, error: E) -> Self
|
|
66
|
+
where
|
|
67
|
+
E: Into<BoxError>,
|
|
68
|
+
{
|
|
69
|
+
let error = error.into();
|
|
70
|
+
|
|
71
|
+
let kind = if error.is::<tunnel::TunnelError>() || error.is::<ProxyConnect>() || {
|
|
72
|
+
#[cfg(feature = "socks")]
|
|
73
|
+
{
|
|
74
|
+
error.is::<socks::SocksError>()
|
|
75
|
+
}
|
|
76
|
+
#[cfg(not(feature = "socks"))]
|
|
77
|
+
{
|
|
78
|
+
false
|
|
79
|
+
}
|
|
80
|
+
} {
|
|
81
|
+
ErrorKind::ProxyConnect
|
|
82
|
+
} else {
|
|
83
|
+
kind
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
Self {
|
|
87
|
+
kind,
|
|
88
|
+
source: Some(error),
|
|
89
|
+
connect_info: None,
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
#[inline]
|
|
94
|
+
pub(super) fn new_kind(kind: ErrorKind) -> Self {
|
|
95
|
+
Self {
|
|
96
|
+
kind,
|
|
97
|
+
source: None,
|
|
98
|
+
connect_info: None,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// Returns true if this was an error from [`ErrorKind::Connect`].
|
|
103
|
+
#[inline]
|
|
104
|
+
pub fn is_connect(&self) -> bool {
|
|
105
|
+
matches!(self.kind, ErrorKind::Connect)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/// Returns true if this was an error from [`ErrorKind::ProxyConnect`].
|
|
109
|
+
#[inline]
|
|
110
|
+
pub fn is_proxy_connect(&self) -> bool {
|
|
111
|
+
matches!(self.kind, ErrorKind::ProxyConnect)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// Returns the info of the client connection on which this error occurred.
|
|
115
|
+
#[inline]
|
|
116
|
+
pub fn connect_info(&self) -> Option<&Connected> {
|
|
117
|
+
self.connect_info.as_ref()
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#[inline]
|
|
121
|
+
pub(super) fn with_connect_info(self, connect_info: Connected) -> Self {
|
|
122
|
+
Self {
|
|
123
|
+
connect_info: Some(connect_info),
|
|
124
|
+
..self
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#[inline]
|
|
129
|
+
pub(super) fn is_canceled(&self) -> bool {
|
|
130
|
+
matches!(self.kind, ErrorKind::Canceled)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
#[inline]
|
|
134
|
+
pub(super) fn tx(src: core::Error) -> Self {
|
|
135
|
+
Self::new(ErrorKind::SendRequest, src)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
#[inline]
|
|
139
|
+
pub(super) fn closed(src: core::Error) -> Self {
|
|
140
|
+
Self::new(ErrorKind::ChannelClosed, src)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
use std::{future::Future, pin::Pin, sync::Arc};
|
|
2
|
+
|
|
3
|
+
use crate::client::core::rt::Executor;
|
|
4
|
+
|
|
5
|
+
pub(crate) type BoxSendFuture = Pin<Box<dyn Future<Output = ()> + Send>>;
|
|
6
|
+
|
|
7
|
+
// Either the user provides an executor for background tasks, or we use `tokio::spawn`.
|
|
8
|
+
#[derive(Clone)]
|
|
9
|
+
pub struct Exec(Arc<dyn Executor<BoxSendFuture> + Send + Sync>);
|
|
10
|
+
|
|
11
|
+
// ===== impl Exec =====
|
|
12
|
+
|
|
13
|
+
impl Exec {
|
|
14
|
+
pub(crate) fn new<E>(inner: E) -> Self
|
|
15
|
+
where
|
|
16
|
+
E: Executor<BoxSendFuture> + Send + Sync + 'static,
|
|
17
|
+
{
|
|
18
|
+
Exec(Arc::new(inner))
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
impl<F> Executor<F> for Exec
|
|
23
|
+
where
|
|
24
|
+
F: Future<Output = ()> + Send + 'static,
|
|
25
|
+
{
|
|
26
|
+
fn execute(&self, fut: F) {
|
|
27
|
+
self.0.execute(Box::pin(fut));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
use std::sync::Arc;
|
|
2
|
+
|
|
3
|
+
use http::{Uri, Version};
|
|
4
|
+
|
|
5
|
+
use crate::{
|
|
6
|
+
client::{
|
|
7
|
+
conn::TcpConnectOptions,
|
|
8
|
+
layer::config::{RequestOptions, TransportOptions},
|
|
9
|
+
},
|
|
10
|
+
hash::HashMemo,
|
|
11
|
+
proxy::Matcher as ProxyMacher,
|
|
12
|
+
tls::{AlpnProtocol, TlsOptions},
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/// Unique identity for a reusable connection.
|
|
16
|
+
pub(crate) type ConnectIdentity = Arc<HashMemo<ConnectExtra>>;
|
|
17
|
+
|
|
18
|
+
/// Metadata describing a reusable network connection.
|
|
19
|
+
///
|
|
20
|
+
/// [`ConnectExtra`] holds connection-specific parameters such as the target URI, ALPN protocol,
|
|
21
|
+
/// proxy settings, and optional TCP/TLS options. Used for connection
|
|
22
|
+
#[must_use]
|
|
23
|
+
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
|
24
|
+
pub(crate) struct ConnectExtra {
|
|
25
|
+
uri: Uri,
|
|
26
|
+
extra: Option<RequestOptions>,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
impl ConnectExtra {
|
|
30
|
+
/// Create a new [`ConnectExtra`] with the given URI and extra.
|
|
31
|
+
#[inline]
|
|
32
|
+
pub(super) fn new<T>(uri: Uri, extra: T) -> Self
|
|
33
|
+
where
|
|
34
|
+
T: Into<Option<RequestOptions>>,
|
|
35
|
+
{
|
|
36
|
+
Self {
|
|
37
|
+
uri,
|
|
38
|
+
extra: extra.into(),
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Return the negotiated [`AlpnProtocol`].
|
|
43
|
+
pub fn alpn_protocol(&self) -> Option<AlpnProtocol> {
|
|
44
|
+
match self
|
|
45
|
+
.extra
|
|
46
|
+
.as_ref()
|
|
47
|
+
.and_then(RequestOptions::enforced_version)
|
|
48
|
+
{
|
|
49
|
+
Some(Version::HTTP_11 | Version::HTTP_10 | Version::HTTP_09) => {
|
|
50
|
+
Some(AlpnProtocol::HTTP1)
|
|
51
|
+
}
|
|
52
|
+
Some(Version::HTTP_2) => Some(AlpnProtocol::HTTP2),
|
|
53
|
+
_ => None,
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/// Return a reference to the [`ProxyMacher`].
|
|
58
|
+
#[inline]
|
|
59
|
+
pub fn proxy_matcher(&self) -> Option<&ProxyMacher> {
|
|
60
|
+
self.extra.as_ref().and_then(RequestOptions::proxy_matcher)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/// Return a reference to the [`TlsOptions`].
|
|
64
|
+
#[inline]
|
|
65
|
+
pub fn tls_options(&self) -> Option<&TlsOptions> {
|
|
66
|
+
self.extra
|
|
67
|
+
.as_ref()
|
|
68
|
+
.map(RequestOptions::transport_opts)
|
|
69
|
+
.and_then(TransportOptions::tls_options)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// Return a reference to the [`TcpConnectOptions`].
|
|
73
|
+
#[inline]
|
|
74
|
+
pub fn tcp_options(&self) -> Option<&TcpConnectOptions> {
|
|
75
|
+
self.extra.as_ref().map(RequestOptions::tcp_connect_opts)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
use std::{
|
|
2
|
+
future::Future,
|
|
3
|
+
pin::Pin,
|
|
4
|
+
task::{self, Poll},
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
use pin_project_lite::pin_project;
|
|
8
|
+
|
|
9
|
+
pub(crate) trait Started: Future {
|
|
10
|
+
fn started(&self) -> bool;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
pub(crate) fn lazy<F, R>(func: F) -> Lazy<F, R>
|
|
14
|
+
where
|
|
15
|
+
F: FnOnce() -> R,
|
|
16
|
+
R: Future + Unpin,
|
|
17
|
+
{
|
|
18
|
+
Lazy {
|
|
19
|
+
inner: Inner::Init { func },
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// FIXME: allow() required due to `impl Trait` leaking types to this lint
|
|
24
|
+
pin_project! {
|
|
25
|
+
pub(crate) struct Lazy<F, R> {
|
|
26
|
+
#[pin]
|
|
27
|
+
inner: Inner<F, R>,
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pin_project! {
|
|
32
|
+
#[project = InnerProj]
|
|
33
|
+
#[project_replace = InnerProjReplace]
|
|
34
|
+
enum Inner<F, R> {
|
|
35
|
+
Init { func: F },
|
|
36
|
+
Fut { #[pin] fut: R },
|
|
37
|
+
Empty,
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
impl<F, R> Started for Lazy<F, R>
|
|
42
|
+
where
|
|
43
|
+
F: FnOnce() -> R,
|
|
44
|
+
R: Future,
|
|
45
|
+
{
|
|
46
|
+
fn started(&self) -> bool {
|
|
47
|
+
match self.inner {
|
|
48
|
+
Inner::Init { .. } => false,
|
|
49
|
+
Inner::Fut { .. } | Inner::Empty => true,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
impl<F, R> Future for Lazy<F, R>
|
|
55
|
+
where
|
|
56
|
+
F: FnOnce() -> R,
|
|
57
|
+
R: Future,
|
|
58
|
+
{
|
|
59
|
+
type Output = R::Output;
|
|
60
|
+
|
|
61
|
+
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
|
|
62
|
+
let mut this = self.project();
|
|
63
|
+
|
|
64
|
+
if let InnerProj::Fut { fut } = this.inner.as_mut().project() {
|
|
65
|
+
return fut.poll(cx);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
match this.inner.as_mut().project_replace(Inner::Empty) {
|
|
69
|
+
InnerProjReplace::Init { func } => {
|
|
70
|
+
this.inner.set(Inner::Fut { fut: func() });
|
|
71
|
+
if let InnerProj::Fut { fut } = this.inner.project() {
|
|
72
|
+
return fut.poll(cx);
|
|
73
|
+
}
|
|
74
|
+
unreachable!()
|
|
75
|
+
}
|
|
76
|
+
_ => unreachable!("lazy state wrong"),
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|