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.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.lock +2688 -0
  3. data/Cargo.toml +6 -0
  4. data/README.md +179 -0
  5. data/ext/wreq_rb/Cargo.toml +39 -0
  6. data/ext/wreq_rb/extconf.rb +22 -0
  7. data/ext/wreq_rb/src/client.rs +565 -0
  8. data/ext/wreq_rb/src/error.rs +25 -0
  9. data/ext/wreq_rb/src/lib.rs +20 -0
  10. data/ext/wreq_rb/src/response.rs +132 -0
  11. data/lib/wreq-rb/version.rb +5 -0
  12. data/lib/wreq-rb.rb +17 -0
  13. data/patches/0001-add-transfer-size-tracking.patch +292 -0
  14. data/vendor/wreq/Cargo.toml +306 -0
  15. data/vendor/wreq/LICENSE +202 -0
  16. data/vendor/wreq/README.md +122 -0
  17. data/vendor/wreq/examples/cert_store.rs +77 -0
  18. data/vendor/wreq/examples/connect_via_lower_priority_tokio_runtime.rs +258 -0
  19. data/vendor/wreq/examples/emulation.rs +118 -0
  20. data/vendor/wreq/examples/form.rs +14 -0
  21. data/vendor/wreq/examples/http1_websocket.rs +37 -0
  22. data/vendor/wreq/examples/http2_websocket.rs +45 -0
  23. data/vendor/wreq/examples/json_dynamic.rs +41 -0
  24. data/vendor/wreq/examples/json_typed.rs +47 -0
  25. data/vendor/wreq/examples/keylog.rs +16 -0
  26. data/vendor/wreq/examples/request_with_emulation.rs +115 -0
  27. data/vendor/wreq/examples/request_with_interface.rs +37 -0
  28. data/vendor/wreq/examples/request_with_local_address.rs +16 -0
  29. data/vendor/wreq/examples/request_with_proxy.rs +13 -0
  30. data/vendor/wreq/examples/request_with_redirect.rs +22 -0
  31. data/vendor/wreq/examples/request_with_version.rs +15 -0
  32. data/vendor/wreq/examples/tor_socks.rs +24 -0
  33. data/vendor/wreq/examples/unix_socket.rs +33 -0
  34. data/vendor/wreq/src/client/body.rs +304 -0
  35. data/vendor/wreq/src/client/conn/conn.rs +231 -0
  36. data/vendor/wreq/src/client/conn/connector.rs +549 -0
  37. data/vendor/wreq/src/client/conn/http.rs +1023 -0
  38. data/vendor/wreq/src/client/conn/proxy/socks.rs +233 -0
  39. data/vendor/wreq/src/client/conn/proxy/tunnel.rs +260 -0
  40. data/vendor/wreq/src/client/conn/proxy.rs +39 -0
  41. data/vendor/wreq/src/client/conn/tls_info.rs +98 -0
  42. data/vendor/wreq/src/client/conn/uds.rs +44 -0
  43. data/vendor/wreq/src/client/conn/verbose.rs +149 -0
  44. data/vendor/wreq/src/client/conn.rs +323 -0
  45. data/vendor/wreq/src/client/core/body/incoming.rs +485 -0
  46. data/vendor/wreq/src/client/core/body/length.rs +118 -0
  47. data/vendor/wreq/src/client/core/body.rs +34 -0
  48. data/vendor/wreq/src/client/core/common/buf.rs +149 -0
  49. data/vendor/wreq/src/client/core/common/rewind.rs +141 -0
  50. data/vendor/wreq/src/client/core/common/watch.rs +76 -0
  51. data/vendor/wreq/src/client/core/common.rs +3 -0
  52. data/vendor/wreq/src/client/core/conn/http1.rs +342 -0
  53. data/vendor/wreq/src/client/core/conn/http2.rs +307 -0
  54. data/vendor/wreq/src/client/core/conn.rs +11 -0
  55. data/vendor/wreq/src/client/core/dispatch.rs +299 -0
  56. data/vendor/wreq/src/client/core/error.rs +435 -0
  57. data/vendor/wreq/src/client/core/ext.rs +201 -0
  58. data/vendor/wreq/src/client/core/http1.rs +178 -0
  59. data/vendor/wreq/src/client/core/http2.rs +483 -0
  60. data/vendor/wreq/src/client/core/proto/h1/conn.rs +988 -0
  61. data/vendor/wreq/src/client/core/proto/h1/decode.rs +1170 -0
  62. data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +684 -0
  63. data/vendor/wreq/src/client/core/proto/h1/encode.rs +580 -0
  64. data/vendor/wreq/src/client/core/proto/h1/io.rs +879 -0
  65. data/vendor/wreq/src/client/core/proto/h1/role.rs +694 -0
  66. data/vendor/wreq/src/client/core/proto/h1.rs +104 -0
  67. data/vendor/wreq/src/client/core/proto/h2/client.rs +650 -0
  68. data/vendor/wreq/src/client/core/proto/h2/ping.rs +539 -0
  69. data/vendor/wreq/src/client/core/proto/h2.rs +379 -0
  70. data/vendor/wreq/src/client/core/proto/headers.rs +138 -0
  71. data/vendor/wreq/src/client/core/proto.rs +58 -0
  72. data/vendor/wreq/src/client/core/rt/bounds.rs +57 -0
  73. data/vendor/wreq/src/client/core/rt/timer.rs +150 -0
  74. data/vendor/wreq/src/client/core/rt/tokio.rs +99 -0
  75. data/vendor/wreq/src/client/core/rt.rs +25 -0
  76. data/vendor/wreq/src/client/core/upgrade.rs +267 -0
  77. data/vendor/wreq/src/client/core.rs +16 -0
  78. data/vendor/wreq/src/client/emulation.rs +161 -0
  79. data/vendor/wreq/src/client/http/client/error.rs +142 -0
  80. data/vendor/wreq/src/client/http/client/exec.rs +29 -0
  81. data/vendor/wreq/src/client/http/client/extra.rs +77 -0
  82. data/vendor/wreq/src/client/http/client/lazy.rs +79 -0
  83. data/vendor/wreq/src/client/http/client/pool.rs +1105 -0
  84. data/vendor/wreq/src/client/http/client/util.rs +104 -0
  85. data/vendor/wreq/src/client/http/client.rs +1003 -0
  86. data/vendor/wreq/src/client/http/future.rs +99 -0
  87. data/vendor/wreq/src/client/http.rs +1629 -0
  88. data/vendor/wreq/src/client/layer/config/options.rs +156 -0
  89. data/vendor/wreq/src/client/layer/config.rs +116 -0
  90. data/vendor/wreq/src/client/layer/cookie.rs +161 -0
  91. data/vendor/wreq/src/client/layer/decoder.rs +139 -0
  92. data/vendor/wreq/src/client/layer/redirect/future.rs +270 -0
  93. data/vendor/wreq/src/client/layer/redirect/policy.rs +63 -0
  94. data/vendor/wreq/src/client/layer/redirect.rs +145 -0
  95. data/vendor/wreq/src/client/layer/retry/classify.rs +105 -0
  96. data/vendor/wreq/src/client/layer/retry/scope.rs +51 -0
  97. data/vendor/wreq/src/client/layer/retry.rs +151 -0
  98. data/vendor/wreq/src/client/layer/timeout/body.rs +233 -0
  99. data/vendor/wreq/src/client/layer/timeout/future.rs +90 -0
  100. data/vendor/wreq/src/client/layer/timeout.rs +177 -0
  101. data/vendor/wreq/src/client/layer.rs +15 -0
  102. data/vendor/wreq/src/client/multipart.rs +717 -0
  103. data/vendor/wreq/src/client/request.rs +818 -0
  104. data/vendor/wreq/src/client/response.rs +534 -0
  105. data/vendor/wreq/src/client/ws/json.rs +99 -0
  106. data/vendor/wreq/src/client/ws/message.rs +453 -0
  107. data/vendor/wreq/src/client/ws.rs +714 -0
  108. data/vendor/wreq/src/client.rs +27 -0
  109. data/vendor/wreq/src/config.rs +140 -0
  110. data/vendor/wreq/src/cookie.rs +579 -0
  111. data/vendor/wreq/src/dns/gai.rs +249 -0
  112. data/vendor/wreq/src/dns/hickory.rs +78 -0
  113. data/vendor/wreq/src/dns/resolve.rs +180 -0
  114. data/vendor/wreq/src/dns.rs +69 -0
  115. data/vendor/wreq/src/error.rs +502 -0
  116. data/vendor/wreq/src/ext.rs +398 -0
  117. data/vendor/wreq/src/hash.rs +143 -0
  118. data/vendor/wreq/src/header.rs +506 -0
  119. data/vendor/wreq/src/into_uri.rs +187 -0
  120. data/vendor/wreq/src/lib.rs +586 -0
  121. data/vendor/wreq/src/proxy/mac.rs +82 -0
  122. data/vendor/wreq/src/proxy/matcher.rs +806 -0
  123. data/vendor/wreq/src/proxy/uds.rs +66 -0
  124. data/vendor/wreq/src/proxy/win.rs +31 -0
  125. data/vendor/wreq/src/proxy.rs +569 -0
  126. data/vendor/wreq/src/redirect.rs +575 -0
  127. data/vendor/wreq/src/retry.rs +198 -0
  128. data/vendor/wreq/src/sync.rs +129 -0
  129. data/vendor/wreq/src/tls/conn/cache.rs +123 -0
  130. data/vendor/wreq/src/tls/conn/cert_compression.rs +125 -0
  131. data/vendor/wreq/src/tls/conn/ext.rs +82 -0
  132. data/vendor/wreq/src/tls/conn/macros.rs +34 -0
  133. data/vendor/wreq/src/tls/conn/service.rs +138 -0
  134. data/vendor/wreq/src/tls/conn.rs +681 -0
  135. data/vendor/wreq/src/tls/keylog/handle.rs +64 -0
  136. data/vendor/wreq/src/tls/keylog.rs +99 -0
  137. data/vendor/wreq/src/tls/options.rs +464 -0
  138. data/vendor/wreq/src/tls/x509/identity.rs +122 -0
  139. data/vendor/wreq/src/tls/x509/parser.rs +71 -0
  140. data/vendor/wreq/src/tls/x509/store.rs +228 -0
  141. data/vendor/wreq/src/tls/x509.rs +68 -0
  142. data/vendor/wreq/src/tls.rs +154 -0
  143. data/vendor/wreq/src/trace.rs +55 -0
  144. data/vendor/wreq/src/util.rs +122 -0
  145. data/vendor/wreq/tests/badssl.rs +228 -0
  146. data/vendor/wreq/tests/brotli.rs +350 -0
  147. data/vendor/wreq/tests/client.rs +1098 -0
  148. data/vendor/wreq/tests/connector_layers.rs +227 -0
  149. data/vendor/wreq/tests/cookie.rs +306 -0
  150. data/vendor/wreq/tests/deflate.rs +347 -0
  151. data/vendor/wreq/tests/emulation.rs +260 -0
  152. data/vendor/wreq/tests/gzip.rs +347 -0
  153. data/vendor/wreq/tests/layers.rs +261 -0
  154. data/vendor/wreq/tests/multipart.rs +165 -0
  155. data/vendor/wreq/tests/proxy.rs +438 -0
  156. data/vendor/wreq/tests/redirect.rs +629 -0
  157. data/vendor/wreq/tests/retry.rs +135 -0
  158. data/vendor/wreq/tests/support/delay_server.rs +117 -0
  159. data/vendor/wreq/tests/support/error.rs +16 -0
  160. data/vendor/wreq/tests/support/layer.rs +183 -0
  161. data/vendor/wreq/tests/support/mod.rs +9 -0
  162. data/vendor/wreq/tests/support/server.rs +232 -0
  163. data/vendor/wreq/tests/timeouts.rs +281 -0
  164. data/vendor/wreq/tests/unix_socket.rs +135 -0
  165. data/vendor/wreq/tests/upgrade.rs +98 -0
  166. data/vendor/wreq/tests/zstd.rs +559 -0
  167. 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
+ }