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.
Files changed (150) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1922 -397
  3. data/LICENSE +203 -0
  4. data/README.md +19 -15
  5. data/ext/wreq_rb/Cargo.toml +4 -6
  6. data/ext/wreq_rb/src/client.rs +41 -48
  7. data/lib/wreq-rb/version.rb +1 -1
  8. data/patches/0001-add-transfer-size-tracking.patch +76 -67
  9. data/vendor/wreq/Cargo.toml +119 -71
  10. data/vendor/wreq/README.md +25 -20
  11. data/vendor/wreq/bench/http1.rs +25 -0
  12. data/vendor/wreq/bench/http1_over_tls.rs +25 -0
  13. data/vendor/wreq/bench/http2.rs +25 -0
  14. data/vendor/wreq/bench/http2_over_tls.rs +25 -0
  15. data/vendor/wreq/bench/support/bench.rs +91 -0
  16. data/vendor/wreq/bench/support/client.rs +217 -0
  17. data/vendor/wreq/bench/support/server.rs +188 -0
  18. data/vendor/wreq/bench/support.rs +56 -0
  19. data/vendor/wreq/examples/cert_store.rs +4 -4
  20. data/vendor/wreq/examples/{emulation.rs → emulate.rs} +2 -2
  21. data/vendor/wreq/examples/http2_websocket.rs +2 -2
  22. data/vendor/wreq/examples/keylog.rs +3 -3
  23. data/vendor/wreq/examples/{request_with_emulation.rs → request_with_emulate.rs} +2 -2
  24. data/vendor/wreq/examples/rt.rs +23 -0
  25. data/vendor/wreq/src/client/body.rs +23 -61
  26. data/vendor/wreq/src/client/emulate.rs +119 -0
  27. data/vendor/wreq/src/client/{http/future.rs → future.rs} +11 -32
  28. data/vendor/wreq/src/client/{http → layer}/client/pool.rs +66 -61
  29. data/vendor/wreq/src/client/{http → layer}/client.rs +416 -270
  30. data/vendor/wreq/src/client/layer/config.rs +27 -6
  31. data/vendor/wreq/src/client/layer/decoder.rs +9 -4
  32. data/vendor/wreq/src/client/layer/redirect/future.rs +6 -3
  33. data/vendor/wreq/src/client/layer/redirect.rs +4 -5
  34. data/vendor/wreq/src/client/layer/retry.rs +8 -5
  35. data/vendor/wreq/src/client/layer/timeout/body.rs +15 -6
  36. data/vendor/wreq/src/client/layer/timeout/future.rs +23 -18
  37. data/vendor/wreq/src/client/layer/timeout.rs +24 -74
  38. data/vendor/wreq/src/client/layer.rs +1 -2
  39. data/vendor/wreq/src/client/multipart.rs +137 -154
  40. data/vendor/wreq/src/client/request.rs +202 -118
  41. data/vendor/wreq/src/client/response.rs +46 -45
  42. data/vendor/wreq/src/client/upgrade.rs +15 -0
  43. data/vendor/wreq/src/client/ws.rs +73 -25
  44. data/vendor/wreq/src/client.rs +1655 -17
  45. data/vendor/wreq/src/config.rs +11 -11
  46. data/vendor/wreq/src/{client/conn → conn}/connector.rs +139 -137
  47. data/vendor/wreq/src/conn/descriptor.rs +143 -0
  48. data/vendor/wreq/src/conn/http.rs +484 -0
  49. data/vendor/wreq/src/conn/net/io.rs +75 -0
  50. data/vendor/wreq/src/conn/net/tcp/compio.rs +71 -0
  51. data/vendor/wreq/src/conn/net/tcp/tokio.rs +57 -0
  52. data/vendor/wreq/src/conn/net/tcp.rs +561 -0
  53. data/vendor/wreq/src/conn/net/uds/compio.rs +60 -0
  54. data/vendor/wreq/src/{client/conn/uds.rs → conn/net/uds/tokio.rs} +18 -12
  55. data/vendor/wreq/src/conn/net/uds.rs +11 -0
  56. data/vendor/wreq/src/conn/net.rs +130 -0
  57. data/vendor/wreq/src/{client/conn → conn}/proxy/socks.rs +2 -9
  58. data/vendor/wreq/src/{client/conn → conn}/proxy/tunnel.rs +21 -56
  59. data/vendor/wreq/src/conn/tls_info.rs +47 -0
  60. data/vendor/wreq/src/{client/conn.rs → conn.rs} +202 -54
  61. data/vendor/wreq/src/cookie.rs +302 -142
  62. data/vendor/wreq/src/dns/gai/compio.rs +77 -0
  63. data/vendor/wreq/src/dns/gai/tokio.rs +90 -0
  64. data/vendor/wreq/src/dns/gai.rs +14 -164
  65. data/vendor/wreq/src/dns/hickory.rs +16 -23
  66. data/vendor/wreq/src/dns/resolve.rs +7 -41
  67. data/vendor/wreq/src/dns.rs +90 -7
  68. data/vendor/wreq/src/error.rs +57 -31
  69. data/vendor/wreq/src/ext.rs +25 -0
  70. data/vendor/wreq/src/group.rs +211 -0
  71. data/vendor/wreq/src/header.rs +100 -112
  72. data/vendor/wreq/src/lib.rs +124 -73
  73. data/vendor/wreq/src/proxy.rs +6 -20
  74. data/vendor/wreq/src/redirect.rs +1 -1
  75. data/vendor/wreq/src/rt.rs +208 -0
  76. data/vendor/wreq/src/sync.rs +97 -98
  77. data/vendor/wreq/src/tls/compress.rs +124 -0
  78. data/vendor/wreq/src/tls/conn/ext.rs +54 -45
  79. data/vendor/wreq/src/tls/conn/service.rs +14 -18
  80. data/vendor/wreq/src/tls/conn.rs +169 -241
  81. data/vendor/wreq/src/tls/keylog.rs +68 -5
  82. data/vendor/wreq/src/tls/session.rs +205 -0
  83. data/vendor/wreq/src/tls/{x509 → trust}/identity.rs +4 -21
  84. data/vendor/wreq/src/tls/{x509/parser.rs → trust/parse.rs} +1 -1
  85. data/vendor/wreq/src/tls/{x509 → trust}/store.rs +42 -81
  86. data/vendor/wreq/src/tls/{x509.rs → trust.rs} +8 -2
  87. data/vendor/wreq/src/tls.rs +489 -25
  88. data/vendor/wreq/src/trace.rs +0 -12
  89. data/vendor/wreq/src/util.rs +1 -1
  90. data/vendor/wreq/tests/badssl.rs +10 -10
  91. data/vendor/wreq/tests/client.rs +3 -9
  92. data/vendor/wreq/tests/cookie.rs +6 -8
  93. data/vendor/wreq/tests/{emulation.rs → emulate.rs} +130 -22
  94. data/vendor/wreq/tests/multipart.rs +43 -1
  95. data/vendor/wreq/tests/proxy.rs +1 -1
  96. data/vendor/wreq/tests/support/layer.rs +1 -0
  97. metadata +49 -71
  98. data/patches/0002-add-cancel-connections.patch +0 -181
  99. data/vendor/wreq/src/client/conn/conn.rs +0 -231
  100. data/vendor/wreq/src/client/conn/http.rs +0 -1023
  101. data/vendor/wreq/src/client/conn/tls_info.rs +0 -98
  102. data/vendor/wreq/src/client/core/body/incoming.rs +0 -485
  103. data/vendor/wreq/src/client/core/body/length.rs +0 -118
  104. data/vendor/wreq/src/client/core/body.rs +0 -34
  105. data/vendor/wreq/src/client/core/common/buf.rs +0 -149
  106. data/vendor/wreq/src/client/core/common/rewind.rs +0 -141
  107. data/vendor/wreq/src/client/core/common/watch.rs +0 -76
  108. data/vendor/wreq/src/client/core/common.rs +0 -3
  109. data/vendor/wreq/src/client/core/conn/http1.rs +0 -342
  110. data/vendor/wreq/src/client/core/conn/http2.rs +0 -307
  111. data/vendor/wreq/src/client/core/conn.rs +0 -11
  112. data/vendor/wreq/src/client/core/dispatch.rs +0 -299
  113. data/vendor/wreq/src/client/core/error.rs +0 -435
  114. data/vendor/wreq/src/client/core/ext.rs +0 -201
  115. data/vendor/wreq/src/client/core/http1.rs +0 -178
  116. data/vendor/wreq/src/client/core/http2.rs +0 -483
  117. data/vendor/wreq/src/client/core/proto/h1/conn.rs +0 -988
  118. data/vendor/wreq/src/client/core/proto/h1/decode.rs +0 -1170
  119. data/vendor/wreq/src/client/core/proto/h1/dispatch.rs +0 -684
  120. data/vendor/wreq/src/client/core/proto/h1/encode.rs +0 -580
  121. data/vendor/wreq/src/client/core/proto/h1/io.rs +0 -879
  122. data/vendor/wreq/src/client/core/proto/h1/role.rs +0 -694
  123. data/vendor/wreq/src/client/core/proto/h1.rs +0 -104
  124. data/vendor/wreq/src/client/core/proto/h2/client.rs +0 -650
  125. data/vendor/wreq/src/client/core/proto/h2/ping.rs +0 -539
  126. data/vendor/wreq/src/client/core/proto/h2.rs +0 -379
  127. data/vendor/wreq/src/client/core/proto/headers.rs +0 -138
  128. data/vendor/wreq/src/client/core/proto.rs +0 -58
  129. data/vendor/wreq/src/client/core/rt/bounds.rs +0 -57
  130. data/vendor/wreq/src/client/core/rt/timer.rs +0 -150
  131. data/vendor/wreq/src/client/core/rt/tokio.rs +0 -99
  132. data/vendor/wreq/src/client/core/rt.rs +0 -25
  133. data/vendor/wreq/src/client/core/upgrade.rs +0 -267
  134. data/vendor/wreq/src/client/core.rs +0 -16
  135. data/vendor/wreq/src/client/emulation.rs +0 -161
  136. data/vendor/wreq/src/client/http/client/error.rs +0 -142
  137. data/vendor/wreq/src/client/http/client/exec.rs +0 -29
  138. data/vendor/wreq/src/client/http/client/extra.rs +0 -77
  139. data/vendor/wreq/src/client/http/client/util.rs +0 -104
  140. data/vendor/wreq/src/client/http.rs +0 -1629
  141. data/vendor/wreq/src/client/layer/config/options.rs +0 -156
  142. data/vendor/wreq/src/client/layer/cookie.rs +0 -161
  143. data/vendor/wreq/src/hash.rs +0 -143
  144. data/vendor/wreq/src/tls/conn/cache.rs +0 -123
  145. data/vendor/wreq/src/tls/conn/cert_compression.rs +0 -125
  146. data/vendor/wreq/src/tls/keylog/handle.rs +0 -64
  147. data/vendor/wreq/src/tls/options.rs +0 -464
  148. /data/vendor/wreq/src/client/{http → layer}/client/lazy.rs +0 -0
  149. /data/vendor/wreq/src/{client/conn → conn}/proxy.rs +0 -0
  150. /data/vendor/wreq/src/{client/conn → conn}/verbose.rs +0 -0
@@ -0,0 +1,90 @@
1
+ // This module contains the `GaiResolver` implementation for the `tokio` runtime.
2
+
3
+ use std::{
4
+ future::Future,
5
+ io,
6
+ net::ToSocketAddrs,
7
+ pin::Pin,
8
+ task::{self, Poll},
9
+ };
10
+
11
+ use tower::Service;
12
+
13
+ use super::{GaiAddrs, GaiResolver};
14
+ use crate::dns::{Addrs, Name, Resolve, Resolving, SocketAddrs};
15
+
16
+ /// A future to resolve a name returned by `GaiResolver`.
17
+ pub struct GaiFuture {
18
+ inner: tokio::task::JoinHandle<Result<SocketAddrs, io::Error>>,
19
+ }
20
+
21
+ // ==== impl GaiResolver ====
22
+
23
+ impl GaiResolver {
24
+ /// Creates a new [`GaiResolver`].
25
+ pub fn new() -> Self {
26
+ GaiResolver { _priv: () }
27
+ }
28
+ }
29
+
30
+ impl Service<Name> for GaiResolver {
31
+ type Response = GaiAddrs;
32
+ type Error = io::Error;
33
+ type Future = GaiFuture;
34
+
35
+ #[inline]
36
+ fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), io::Error>> {
37
+ Poll::Ready(Ok(()))
38
+ }
39
+
40
+ fn call(&mut self, name: Name) -> Self::Future {
41
+ let blocking = tokio::task::spawn_blocking(move || {
42
+ debug!("resolving {}", name);
43
+ (name.as_str(), 0)
44
+ .to_socket_addrs()
45
+ .map(|i| SocketAddrs { iter: i })
46
+ });
47
+ GaiFuture { inner: blocking }
48
+ }
49
+ }
50
+
51
+ impl Resolve for GaiResolver {
52
+ fn resolve(&self, name: Name) -> Resolving {
53
+ let mut this = self.clone();
54
+ Box::pin(async move {
55
+ this.call(name)
56
+ .await
57
+ .map(|addrs| Box::new(addrs) as Addrs)
58
+ .map_err(Into::into)
59
+ })
60
+ }
61
+ }
62
+
63
+ // ==== impl GaiFuture ====
64
+
65
+ impl Future for GaiFuture {
66
+ type Output = Result<GaiAddrs, io::Error>;
67
+
68
+ fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
69
+ Pin::new(&mut self.inner).poll(cx).map(|res| match res {
70
+ Ok(Ok(addrs)) => Ok(GaiAddrs { inner: addrs }),
71
+ Ok(Err(err)) => Err(err),
72
+ Err(join_err) => {
73
+ #[cfg(feature = "tokio-rt")]
74
+ if join_err.is_cancelled() {
75
+ return Err(io::Error::new(io::ErrorKind::Interrupted, join_err));
76
+ }
77
+
78
+ Err(io::Error::other(format!(
79
+ "DNS resolution blocked task panicked: {join_err}"
80
+ )))
81
+ }
82
+ })
83
+ }
84
+ }
85
+
86
+ impl Drop for GaiFuture {
87
+ fn drop(&mut self) {
88
+ self.inner.abort();
89
+ }
90
+ }
@@ -1,16 +1,18 @@
1
- use std::{
2
- future::Future,
3
- io,
4
- net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs},
5
- pin::Pin,
6
- task::{self, Poll},
7
- vec,
8
- };
1
+ if_tokio_rt! {
2
+ mod tokio;
3
+ }
4
+
5
+ if_compio_rt!(
6
+ mod compio;
7
+ );
9
8
 
10
- use tokio::task::JoinHandle;
11
- use tower::Service;
9
+ if_all_rt!(
10
+ mod tokio;
11
+ );
12
12
 
13
- use super::{Addrs, Name, Resolve, Resolving};
13
+ use std::net::SocketAddr;
14
+
15
+ use crate::dns::SocketAddrs;
14
16
 
15
17
  /// A resolver using blocking `getaddrinfo` calls in a threadpool.
16
18
  #[derive(Clone, Default)]
@@ -23,86 +25,6 @@ pub struct GaiAddrs {
23
25
  inner: SocketAddrs,
24
26
  }
25
27
 
26
- /// A future to resolve a name returned by `GaiResolver`.
27
- pub struct GaiFuture {
28
- inner: JoinHandle<Result<SocketAddrs, io::Error>>,
29
- }
30
-
31
- /// A wrapper around `SocketAddrs` to implement the `Iterator` trait.
32
- pub(crate) struct SocketAddrs {
33
- iter: vec::IntoIter<SocketAddr>,
34
- }
35
-
36
- // ==== impl GaiResolver ====
37
-
38
- impl GaiResolver {
39
- /// Creates a new [`GaiResolver`].
40
- pub fn new() -> Self {
41
- GaiResolver { _priv: () }
42
- }
43
- }
44
-
45
- impl Service<Name> for GaiResolver {
46
- type Response = GaiAddrs;
47
- type Error = io::Error;
48
- type Future = GaiFuture;
49
-
50
- fn poll_ready(&mut self, _cx: &mut task::Context<'_>) -> Poll<Result<(), io::Error>> {
51
- Poll::Ready(Ok(()))
52
- }
53
-
54
- fn call(&mut self, name: Name) -> Self::Future {
55
- let blocking = tokio::task::spawn_blocking(move || {
56
- debug!("resolving {}", name);
57
- (name.as_str(), 0)
58
- .to_socket_addrs()
59
- .map(|i| SocketAddrs { iter: i })
60
- });
61
-
62
- GaiFuture { inner: blocking }
63
- }
64
- }
65
-
66
- impl Resolve for GaiResolver {
67
- fn resolve(&self, name: Name) -> Resolving {
68
- let mut this = self.clone();
69
- Box::pin(async move {
70
- this.call(name)
71
- .await
72
- .map(|addrs| Box::new(addrs) as Addrs)
73
- .map_err(Into::into)
74
- })
75
- }
76
- }
77
-
78
- // ==== impl GaiFuture ====
79
-
80
- impl Future for GaiFuture {
81
- type Output = Result<GaiAddrs, io::Error>;
82
-
83
- fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
84
- Pin::new(&mut self.inner).poll(cx).map(|res| match res {
85
- Ok(Ok(addrs)) => Ok(GaiAddrs { inner: addrs }),
86
- Ok(Err(err)) => Err(err),
87
- Err(join_err) => {
88
- if join_err.is_cancelled() {
89
- Err(io::Error::new(io::ErrorKind::Interrupted, join_err))
90
- } else {
91
- panic!("gai background task failed: {join_err:?}")
92
- }
93
- }
94
- })
95
- }
96
- }
97
-
98
- impl Drop for GaiFuture {
99
- fn drop(&mut self) {
100
- self.inner.abort();
101
- }
102
- }
103
-
104
- // ==== impl GaiAddrs ====
105
-
106
28
  impl Iterator for GaiAddrs {
107
29
  type Item = SocketAddr;
108
30
 
@@ -111,83 +33,11 @@ impl Iterator for GaiAddrs {
111
33
  }
112
34
  }
113
35
 
114
- // ==== impl SocketAddrs ====
115
-
116
- impl SocketAddrs {
117
- pub(crate) fn new(addrs: Vec<SocketAddr>) -> Self {
118
- SocketAddrs {
119
- iter: addrs.into_iter(),
120
- }
121
- }
122
-
123
- pub(crate) fn try_parse(host: &str, port: u16) -> Option<SocketAddrs> {
124
- if let Ok(addr) = host.parse::<Ipv4Addr>() {
125
- let addr = SocketAddrV4::new(addr, port);
126
- return Some(SocketAddrs {
127
- iter: vec![SocketAddr::V4(addr)].into_iter(),
128
- });
129
- }
130
- if let Ok(addr) = host.parse::<Ipv6Addr>() {
131
- let addr = SocketAddrV6::new(addr, port, 0, 0);
132
- return Some(SocketAddrs {
133
- iter: vec![SocketAddr::V6(addr)].into_iter(),
134
- });
135
- }
136
- None
137
- }
138
-
139
- #[inline]
140
- fn filter(self, predicate: impl FnMut(&SocketAddr) -> bool) -> SocketAddrs {
141
- SocketAddrs::new(self.iter.filter(predicate).collect())
142
- }
143
-
144
- pub(crate) fn split_by_preference(
145
- self,
146
- local_addr_ipv4: Option<Ipv4Addr>,
147
- local_addr_ipv6: Option<Ipv6Addr>,
148
- ) -> (SocketAddrs, SocketAddrs) {
149
- match (local_addr_ipv4, local_addr_ipv6) {
150
- (Some(_), None) => (self.filter(SocketAddr::is_ipv4), SocketAddrs::new(vec![])),
151
- (None, Some(_)) => (self.filter(SocketAddr::is_ipv6), SocketAddrs::new(vec![])),
152
- _ => {
153
- let preferring_v6 = self
154
- .iter
155
- .as_slice()
156
- .first()
157
- .map(SocketAddr::is_ipv6)
158
- .unwrap_or(false);
159
-
160
- let (preferred, fallback) = self
161
- .iter
162
- .partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6);
163
-
164
- (SocketAddrs::new(preferred), SocketAddrs::new(fallback))
165
- }
166
- }
167
- }
168
-
169
- pub(crate) fn is_empty(&self) -> bool {
170
- self.iter.as_slice().is_empty()
171
- }
172
-
173
- pub(crate) fn len(&self) -> usize {
174
- self.iter.as_slice().len()
175
- }
176
- }
177
-
178
- impl Iterator for SocketAddrs {
179
- type Item = SocketAddr;
180
- #[inline]
181
- fn next(&mut self) -> Option<SocketAddr> {
182
- self.iter.next()
183
- }
184
- }
185
-
186
36
  #[cfg(test)]
187
37
  mod tests {
188
38
  use std::net::{Ipv4Addr, Ipv6Addr};
189
39
 
190
- use super::*;
40
+ use crate::dns::{Name, SocketAddrs};
191
41
 
192
42
  #[test]
193
43
  fn test_ip_addrs_split_by_preference() {
@@ -4,9 +4,8 @@ use std::{net::SocketAddr, sync::LazyLock};
4
4
 
5
5
  use hickory_resolver::{
6
6
  TokioResolver,
7
- config::{LookupIpStrategy, ResolverConfig},
8
- lookup_ip::LookupIpIntoIter,
9
- name_server::TokioConnectionProvider,
7
+ config::{self, LookupIpStrategy, ResolverConfig},
8
+ net::runtime::TokioRuntimeProvider,
10
9
  };
11
10
 
12
11
  use super::{Addrs, Name, Resolve, Resolving};
@@ -25,8 +24,10 @@ pub struct HickoryDnsResolver {
25
24
  impl HickoryDnsResolver {
26
25
  /// Create a new resolver with the default configuration,
27
26
  /// which reads from `/etc/resolve.conf`. The options are
28
- /// overriden to look up for both IPv4 and IPv6 addresses
29
- /// to work with "happy eyeballs" algorithm.
27
+ /// overridden to look up both IPv4 and IPv6 addresses
28
+ /// to support the "happy eyeballs" algorithm.
29
+ ///
30
+ /// SAFETY: `build` only fails if DNS-over-TLS is enabled and default TLS config creation fails.
30
31
  pub fn new() -> HickoryDnsResolver {
31
32
  static RESOLVER: LazyLock<TokioResolver> = LazyLock::new(|| {
32
33
  let mut builder = match TokioResolver::builder_tokio() {
@@ -37,13 +38,13 @@ impl HickoryDnsResolver {
37
38
  Err(_err) => {
38
39
  debug!("error reading DNS system conf: {}, using defaults", _err);
39
40
  TokioResolver::builder_with_config(
40
- ResolverConfig::default(),
41
- TokioConnectionProvider::default(),
41
+ ResolverConfig::udp_and_tcp(&config::GOOGLE),
42
+ TokioRuntimeProvider::default(),
42
43
  )
43
44
  }
44
45
  };
45
46
  builder.options_mut().ip_strategy = LookupIpStrategy::Ipv4AndIpv6;
46
- builder.build()
47
+ builder.build().expect("failed to create DNS resolver")
47
48
  });
48
49
 
49
50
  HickoryDnsResolver {
@@ -52,27 +53,19 @@ impl HickoryDnsResolver {
52
53
  }
53
54
  }
54
55
 
55
- struct SocketAddrs {
56
- iter: LookupIpIntoIter,
57
- }
58
-
59
56
  impl Resolve for HickoryDnsResolver {
60
57
  fn resolve(&self, name: Name) -> Resolving {
61
58
  let resolver = self.clone();
62
59
  Box::pin(async move {
63
60
  let lookup = resolver.resolver.lookup_ip(name.as_str()).await?;
64
- let addrs: Addrs = Box::new(SocketAddrs {
65
- iter: lookup.into_iter(),
66
- });
61
+ let addrs: Addrs = Box::new(
62
+ lookup
63
+ .iter()
64
+ .map(|ip_addr| SocketAddr::new(ip_addr, 0))
65
+ .collect::<Vec<_>>()
66
+ .into_iter(),
67
+ );
67
68
  Ok(addrs)
68
69
  })
69
70
  }
70
71
  }
71
-
72
- impl Iterator for SocketAddrs {
73
- type Item = SocketAddr;
74
-
75
- fn next(&mut self) -> Option<Self::Item> {
76
- self.iter.next().map(|ip_addr| SocketAddr::new(ip_addr, 0))
77
- }
78
- }
@@ -9,9 +9,7 @@ use std::{
9
9
  task::{Context, Poll},
10
10
  };
11
11
 
12
- use tower::Service;
13
-
14
- use crate::error::BoxError;
12
+ use tower::{BoxError, Service};
15
13
 
16
14
  /// A domain name to resolve into IP addresses.
17
15
  #[derive(Clone, Hash, Eq, PartialEq)]
@@ -74,45 +72,13 @@ pub trait Resolve: Send + Sync {
74
72
  fn resolve(&self, name: Name) -> Resolving;
75
73
  }
76
74
 
77
- /// Trait for converting types into a shared DNS resolver ([`Arc<dyn Resolve>`]).
78
- ///
79
- /// Implemented for any [`Resolve`] type, [`Arc<T>`] where `T: Resolve`, and [`Arc<dyn Resolve>`].
80
- /// Enables ergonomic conversion to a trait object for use in APIs without manual Arc wrapping.
81
- pub trait IntoResolve {
82
- /// Converts the implementor into an [`Arc<dyn Resolve>`].
75
+ impl_into_shared!(
76
+ /// Trait for converting types into a shared DNS resolver ([`Arc<dyn Resolve>`]).
83
77
  ///
84
- /// This method enables ergonomic conversion of concrete resolvers, [`Arc<T>`], or
85
- /// existing [`Arc<dyn Resolve>`] into a trait object suitable for APIs that expect
86
- /// a shared DNS resolver.
87
- fn into_resolve(self) -> Arc<dyn Resolve>;
88
- }
89
-
90
- impl IntoResolve for Arc<dyn Resolve> {
91
- #[inline]
92
- fn into_resolve(self) -> Arc<dyn Resolve> {
93
- self
94
- }
95
- }
96
-
97
- impl<R> IntoResolve for Arc<R>
98
- where
99
- R: Resolve + 'static,
100
- {
101
- #[inline]
102
- fn into_resolve(self) -> Arc<dyn Resolve> {
103
- self
104
- }
105
- }
106
-
107
- impl<R> IntoResolve for R
108
- where
109
- R: Resolve + 'static,
110
- {
111
- #[inline]
112
- fn into_resolve(self) -> Arc<dyn Resolve> {
113
- Arc::new(self)
114
- }
115
- }
78
+ /// Implemented for any [`Resolve`] type, [`Arc<T>`] where `T: Resolve`, and [`Arc<dyn Resolve>`].
79
+ /// Enables ergonomic conversion to a trait object for use in APIs without manual Arc wrapping.
80
+ pub trait IntoResolve => Resolve
81
+ );
116
82
 
117
83
  /// Adapter that wraps a [`Resolve`] trait object to work with Tower's `Service` trait.
118
84
  ///
@@ -1,18 +1,102 @@
1
1
  //! DNS resolution
2
2
 
3
- pub(crate) mod gai;
3
+ use std::{
4
+ net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
5
+ vec,
6
+ };
7
+
8
+ mod gai;
9
+ mod resolve;
10
+
4
11
  #[cfg(feature = "hickory-dns")]
5
12
  pub(crate) mod hickory;
6
- pub(crate) mod resolve;
7
-
8
- pub use resolve::{Addrs, IntoResolve, Name, Resolve, Resolving};
9
13
 
14
+ pub use self::{
15
+ gai::GaiResolver,
16
+ resolve::{Addrs, IntoResolve, Name, Resolve, Resolving},
17
+ };
10
18
  pub(crate) use self::{
11
- gai::{GaiResolver, SocketAddrs},
12
19
  resolve::{DnsResolverWithOverrides, DynResolver},
13
20
  sealed::{InternalResolve, resolve},
14
21
  };
15
22
 
23
+ /// A wrapper around `Vec<SocketAddr>` to implement the `Iterator` trait.
24
+ pub(crate) struct SocketAddrs {
25
+ iter: vec::IntoIter<SocketAddr>,
26
+ }
27
+
28
+ impl SocketAddrs {
29
+ pub(crate) fn new(addrs: Vec<SocketAddr>) -> Self {
30
+ SocketAddrs {
31
+ iter: addrs.into_iter(),
32
+ }
33
+ }
34
+
35
+ pub(crate) fn try_parse(host: &str, port: u16) -> Option<SocketAddrs> {
36
+ if let Ok(addr) = host.parse::<Ipv4Addr>() {
37
+ let addr = SocketAddrV4::new(addr, port);
38
+ return Some(SocketAddrs {
39
+ iter: vec![SocketAddr::V4(addr)].into_iter(),
40
+ });
41
+ }
42
+ if let Ok(addr) = host.parse::<Ipv6Addr>() {
43
+ let addr = SocketAddrV6::new(addr, port, 0, 0);
44
+ return Some(SocketAddrs {
45
+ iter: vec![SocketAddr::V6(addr)].into_iter(),
46
+ });
47
+ }
48
+ None
49
+ }
50
+
51
+ pub(crate) fn split_by_preference(
52
+ self,
53
+ local_addr_ipv4: Option<Ipv4Addr>,
54
+ local_addr_ipv6: Option<Ipv6Addr>,
55
+ ) -> (SocketAddrs, SocketAddrs) {
56
+ match (local_addr_ipv4, local_addr_ipv6) {
57
+ (Some(_), None) => (self.filter(SocketAddr::is_ipv4), SocketAddrs::new(vec![])),
58
+ (None, Some(_)) => (self.filter(SocketAddr::is_ipv6), SocketAddrs::new(vec![])),
59
+ _ => {
60
+ let preferring_v6 = self
61
+ .iter
62
+ .as_slice()
63
+ .first()
64
+ .map(SocketAddr::is_ipv6)
65
+ .unwrap_or(false);
66
+
67
+ let (preferred, fallback) = self
68
+ .iter
69
+ .partition::<Vec<_>, _>(|addr| addr.is_ipv6() == preferring_v6);
70
+
71
+ (SocketAddrs::new(preferred), SocketAddrs::new(fallback))
72
+ }
73
+ }
74
+ }
75
+
76
+ #[inline]
77
+ fn filter(self, predicate: impl FnMut(&SocketAddr) -> bool) -> SocketAddrs {
78
+ SocketAddrs::new(self.iter.filter(predicate).collect())
79
+ }
80
+
81
+ #[inline]
82
+ pub(crate) fn is_empty(&self) -> bool {
83
+ self.iter.as_slice().is_empty()
84
+ }
85
+
86
+ #[inline]
87
+ pub(crate) fn len(&self) -> usize {
88
+ self.iter.as_slice().len()
89
+ }
90
+ }
91
+
92
+ impl Iterator for SocketAddrs {
93
+ type Item = SocketAddr;
94
+ #[inline]
95
+ fn next(&mut self) -> Option<SocketAddr> {
96
+ self.iter.next()
97
+ }
98
+ }
99
+
16
100
  mod sealed {
17
101
  use std::{
18
102
  future::Future,
@@ -20,10 +104,9 @@ mod sealed {
20
104
  task::{self, Poll},
21
105
  };
22
106
 
23
- use tower::Service;
107
+ use tower::{BoxError, Service};
24
108
 
25
109
  use super::Name;
26
- use crate::error::BoxError;
27
110
 
28
111
  /// Internal adapter trait for DNS resolvers.
29
112
  ///