wreq-rb 0.6.0 → 0.6.2

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +257 -102
  3. data/ext/wreq_rb/Cargo.toml +7 -4
  4. data/ext/wreq_rb/src/client.rs +105 -15
  5. data/ext/wreq_rb/src/response.rs +28 -3
  6. data/lib/wreq-rb/version.rb +1 -1
  7. data/patches/0001-add-transfer-size-tracking.patch +11 -15
  8. data/vendor/wreq/Cargo.toml +9 -8
  9. data/vendor/wreq/README.md +5 -5
  10. data/vendor/wreq/bench/support/bench.rs +6 -2
  11. data/vendor/wreq/bench/support/client.rs +88 -1
  12. data/vendor/wreq/bench/support/exec.rs +0 -0
  13. data/vendor/wreq/bench/support/rt.rs +34 -0
  14. data/vendor/wreq/bench/support/server.rs +1 -1
  15. data/vendor/wreq/bench/support.rs +1 -15
  16. data/vendor/wreq/examples/cert_store.rs +13 -13
  17. data/vendor/wreq/examples/request_with_emulate.rs +1 -1
  18. data/vendor/wreq/examples/tcp_linger.rs +22 -0
  19. data/vendor/wreq/src/client/layer/client/pool.rs +17 -17
  20. data/vendor/wreq/src/client/layer/client.rs +2 -0
  21. data/vendor/wreq/src/client/layer/decoder.rs +71 -17
  22. data/vendor/wreq/src/client/layer/redirect/future.rs +49 -63
  23. data/vendor/wreq/src/client/layer/redirect/policy.rs +2 -26
  24. data/vendor/wreq/src/client/layer/redirect.rs +48 -60
  25. data/vendor/wreq/src/client/layer/retry.rs +12 -15
  26. data/vendor/wreq/src/client/layer/timeout/body.rs +27 -21
  27. data/vendor/wreq/src/client/layer/timeout/future.rs +33 -58
  28. data/vendor/wreq/src/client/layer/timeout.rs +8 -14
  29. data/vendor/wreq/src/client/request.rs +4 -0
  30. data/vendor/wreq/src/client.rs +53 -31
  31. data/vendor/wreq/src/conn/connector.rs +99 -129
  32. data/vendor/wreq/src/conn/http.rs +25 -18
  33. data/vendor/wreq/src/conn/net/tcp.rs +601 -107
  34. data/vendor/wreq/src/conn/proxy/socks.rs +6 -6
  35. data/vendor/wreq/src/conn/timeout.rs +166 -0
  36. data/vendor/wreq/src/conn.rs +5 -4
  37. data/vendor/wreq/src/cookie/jar.rs +1225 -0
  38. data/vendor/wreq/src/cookie/store.rs +321 -0
  39. data/vendor/wreq/src/cookie.rs +108 -612
  40. data/vendor/wreq/src/dns/resolve.rs +8 -2
  41. data/vendor/wreq/src/dns.rs +4 -4
  42. data/vendor/wreq/src/error.rs +53 -20
  43. data/vendor/wreq/src/lib.rs +1 -0
  44. data/vendor/wreq/src/proxy/matcher.rs +26 -12
  45. data/vendor/wreq/src/proxy/win.rs +39 -9
  46. data/vendor/wreq/src/redirect.rs +515 -100
  47. data/vendor/wreq/src/tls/conn.rs +3 -11
  48. data/vendor/wreq/src/tls/session.rs +7 -8
  49. data/vendor/wreq/src/tls/trust/store.rs +4 -4
  50. data/vendor/wreq/src/util.rs +23 -0
  51. data/vendor/wreq/tests/badssl.rs +72 -7
  52. data/vendor/wreq/tests/brotli.rs +1 -1
  53. data/vendor/wreq/tests/client.rs +24 -0
  54. data/vendor/wreq/tests/connector_layers.rs +8 -4
  55. data/vendor/wreq/tests/cookie.rs +59 -0
  56. data/vendor/wreq/tests/deflate.rs +1 -1
  57. data/vendor/wreq/tests/gzip.rs +53 -1
  58. data/vendor/wreq/tests/layers.rs +8 -4
  59. data/vendor/wreq/tests/redirect.rs +180 -97
  60. data/vendor/wreq/tests/timeouts.rs +47 -12
  61. data/vendor/wreq/tests/zstd.rs +1 -1
  62. metadata +8 -2
@@ -9,8 +9,11 @@ use std::{
9
9
  task::{Context, Poll},
10
10
  };
11
11
 
12
+ use futures_util::{TryFutureExt, future::MapErr};
12
13
  use tower::{BoxError, Service};
13
14
 
15
+ use crate::error::DnsError;
16
+
14
17
  /// A domain name to resolve into IP addresses.
15
18
  #[derive(Clone, Hash, Eq, PartialEq)]
16
19
  pub struct Name {
@@ -99,14 +102,17 @@ impl DynResolver {
99
102
  impl Service<Name> for DynResolver {
100
103
  type Response = Addrs;
101
104
  type Error = BoxError;
102
- type Future = Resolving;
105
+ type Future = MapErr<MapErr<Resolving, fn(BoxError) -> DnsError>, fn(DnsError) -> Self::Error>;
103
106
 
104
107
  fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
105
108
  Poll::Ready(Ok(()))
106
109
  }
107
110
 
108
111
  fn call(&mut self, name: Name) -> Self::Future {
109
- self.resolver.resolve(name)
112
+ self.resolver
113
+ .resolve(name)
114
+ .map_err(DnsError as _)
115
+ .map_err(Into::into)
110
116
  }
111
117
  }
112
118
 
@@ -17,7 +17,7 @@ pub use self::{
17
17
  };
18
18
  pub(crate) use self::{
19
19
  resolve::{DnsResolverWithOverrides, DynResolver},
20
- sealed::{InternalResolve, resolve},
20
+ sealed::{DnsResolver, resolve},
21
21
  };
22
22
 
23
23
  /// A wrapper around `Vec<SocketAddr>` to implement the `Iterator` trait.
@@ -113,7 +113,7 @@ mod sealed {
113
113
  /// This trait provides a unified interface for different resolver implementations,
114
114
  /// allowing both custom [`super::Resolve`] types and Tower [`Service`] implementations
115
115
  /// to be used interchangeably within the connector.
116
- pub trait InternalResolve {
116
+ pub trait DnsResolver {
117
117
  type Addrs: Iterator<Item = SocketAddr>;
118
118
  type Error: Into<BoxError>;
119
119
  type Future: Future<Output = Result<Self::Addrs, Self::Error>>;
@@ -123,7 +123,7 @@ mod sealed {
123
123
  }
124
124
 
125
125
  /// Automatic implementation for any Tower [`Service`] that resolves names to socket addresses.
126
- impl<S> InternalResolve for S
126
+ impl<S> DnsResolver for S
127
127
  where
128
128
  S: Service<Name>,
129
129
  S::Response: Iterator<Item = SocketAddr>,
@@ -144,7 +144,7 @@ mod sealed {
144
144
 
145
145
  pub async fn resolve<R>(resolver: &mut R, name: Name) -> Result<R::Addrs, R::Error>
146
146
  where
147
- R: InternalResolve,
147
+ R: DnsResolver,
148
148
  {
149
149
  std::future::poll_fn(|cx| resolver.poll_ready(cx)).await?;
150
150
  resolver.resolve(name).await
@@ -183,16 +183,16 @@ impl Error {
183
183
  return true;
184
184
  }
185
185
 
186
- if let Some(core_err) = err.downcast_ref::<wreq_proto::Error>() {
187
- if core_err.is_timeout() {
188
- return true;
189
- }
186
+ if let Some(core_err) = err.downcast_ref::<wreq_proto::Error>()
187
+ && core_err.is_timeout()
188
+ {
189
+ return true;
190
190
  }
191
191
 
192
- if let Some(io) = err.downcast_ref::<io::Error>() {
193
- if io.kind() == io::ErrorKind::TimedOut {
194
- return true;
195
- }
192
+ if let Some(io) = err.downcast_ref::<io::Error>()
193
+ && io.kind() == io::ErrorKind::TimedOut
194
+ {
195
+ return true;
196
196
  }
197
197
 
198
198
  source = err.source();
@@ -214,10 +214,10 @@ impl Error {
214
214
  let mut source = self.source();
215
215
 
216
216
  while let Some(err) = source {
217
- if let Some(err) = err.downcast_ref::<Error>() {
218
- if err.is_connect() {
219
- return true;
220
- }
217
+ if let Some(err) = err.downcast_ref::<Error>()
218
+ && err.is_connect()
219
+ {
220
+ return true;
221
221
  }
222
222
 
223
223
  source = err.source();
@@ -233,10 +233,10 @@ impl Error {
233
233
  let mut source = self.source();
234
234
 
235
235
  while let Some(err) = source {
236
- if let Some(err) = err.downcast_ref::<Error>() {
237
- if err.is_proxy_connect() {
238
- return true;
239
- }
236
+ if let Some(err) = err.downcast_ref::<Error>()
237
+ && err.is_proxy_connect()
238
+ {
239
+ return true;
240
240
  }
241
241
 
242
242
  source = err.source();
@@ -250,10 +250,10 @@ impl Error {
250
250
  let mut source = self.source();
251
251
 
252
252
  while let Some(err) = source {
253
- if let Some(io) = err.downcast_ref::<io::Error>() {
254
- if io.kind() == io::ErrorKind::ConnectionReset {
255
- return true;
256
- }
253
+ if let Some(io) = err.downcast_ref::<io::Error>()
254
+ && io.kind() == io::ErrorKind::ConnectionReset
255
+ {
256
+ return true;
257
257
  }
258
258
  source = err.source();
259
259
  }
@@ -261,6 +261,21 @@ impl Error {
261
261
  false
262
262
  }
263
263
 
264
+ /// Returns true if the error is related to DNS resolution.
265
+ pub fn is_dns(&self) -> bool {
266
+ let mut source = self.source();
267
+
268
+ while let Some(err) = source {
269
+ if err.is::<DnsError>() {
270
+ return true;
271
+ }
272
+
273
+ source = err.source();
274
+ }
275
+
276
+ false
277
+ }
278
+
264
279
  /// Returns true if the error is related to the request or response body
265
280
  #[inline]
266
281
  pub fn is_body(&self) -> bool {
@@ -403,6 +418,9 @@ pub(crate) struct BadScheme;
403
418
  #[derive(Debug)]
404
419
  pub(crate) struct ProxyConnect(pub(crate) BoxError);
405
420
 
421
+ #[derive(Debug)]
422
+ pub(crate) struct DnsError(pub(crate) BoxError);
423
+
406
424
  // ==== impl TimedOut ====
407
425
 
408
426
  impl StdError for TimedOut {}
@@ -438,6 +456,21 @@ impl fmt::Display for ProxyConnect {
438
456
  }
439
457
  }
440
458
 
459
+ // ==== impl DnsError ====
460
+
461
+ impl StdError for DnsError {
462
+ #[inline]
463
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
464
+ Some(&*self.0)
465
+ }
466
+ }
467
+
468
+ impl fmt::Display for DnsError {
469
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
470
+ write!(f, "dns resolution error: {}", self.0)
471
+ }
472
+ }
473
+
441
474
  #[cfg(test)]
442
475
  mod tests {
443
476
  use super::*;
@@ -2,6 +2,7 @@
2
2
  #![deny(unsafe_code)]
3
3
  #![deny(missing_docs)]
4
4
  #![cfg_attr(test, deny(warnings))]
5
+ #![cfg_attr(docsrs, feature(doc_cfg))]
5
6
 
6
7
  //! # wreq
7
8
  //!
@@ -288,10 +288,10 @@ impl Builder {
288
288
  if let Some(https) = https.as_mut() {
289
289
  https.extra = extra.clone();
290
290
  }
291
- if http.is_none() || https.is_none() {
292
- if let Some(all) = all.as_mut() {
293
- all.extra = extra;
294
- }
291
+ if (http.is_none() || https.is_none())
292
+ && let Some(all) = all.as_mut()
293
+ {
294
+ all.extra = extra;
295
295
  }
296
296
 
297
297
  Matcher {
@@ -437,14 +437,7 @@ impl NoProxy {
437
437
 
438
438
  /// Return true if this matches the host (domain or IP).
439
439
  pub fn contains(&self, host: &str) -> bool {
440
- // According to RFC3986, raw IPv6 hosts will be wrapped in []. So we need to strip those off
441
- // the end in order to parse correctly
442
- let host = if host.starts_with('[') {
443
- let x: &[_] = &['[', ']'];
444
- host.trim_matches(x)
445
- } else {
446
- host
447
- };
440
+ let host = crate::util::strip_ipv6_brackets(host);
448
441
  match host.parse::<IpAddr>() {
449
442
  // If we can parse an IP addr, then use it, otherwise, assume it is a domain
450
443
  Ok(ip) => self.ips.contains(ip),
@@ -544,6 +537,8 @@ mod builder {
544
537
 
545
538
  #[cfg(test)]
546
539
  mod tests {
540
+ #[cfg(all(feature = "system-proxy", windows))]
541
+ use super::super::win;
547
542
  use super::*;
548
543
 
549
544
  #[test]
@@ -627,6 +622,25 @@ mod tests {
627
622
  }
628
623
  }
629
624
 
625
+ #[cfg(all(feature = "system-proxy", windows))]
626
+ #[test]
627
+ fn test_windows_proxy_override_ip_wildcard() {
628
+ let normalized =
629
+ win::normalize_proxy_override("127.*; 10.*.*.*; 192.168.*; 192.168.1.*; *.example.com");
630
+ let no_proxy = NoProxy::from_string(&normalized);
631
+
632
+ assert!(no_proxy.contains("127.0.0.1"));
633
+ assert!(no_proxy.contains("10.12.34.56"));
634
+ assert!(no_proxy.contains("192.168.42.1"));
635
+ assert!(no_proxy.contains("192.168.1.42"));
636
+ assert!(no_proxy.contains("www.example.com"));
637
+ assert!(!no_proxy.contains("128.0.0.1"));
638
+ assert!(!no_proxy.contains("192.169.42.1"));
639
+
640
+ let subnet = NoProxy::from_string(&win::normalize_proxy_override("192.168.1.*"));
641
+ assert!(!subnet.contains("192.168.2.42"));
642
+ }
643
+
630
644
  macro_rules! p {
631
645
  ($($n:ident = $v:expr,)*) => ({Builder {
632
646
  $($n: $v.into(),)*
@@ -1,3 +1,38 @@
1
+ fn ipv4_wildcard_to_cidr(value: &str) -> Option<String> {
2
+ let parts = value.split('.').collect::<Vec<_>>();
3
+ let wildcard = parts.iter().position(|part| *part == "*")?;
4
+
5
+ if wildcard == 0 || wildcard > 3 || parts[wildcard..].iter().any(|part| *part != "*") {
6
+ return None;
7
+ }
8
+
9
+ let mut octets = [0; 4];
10
+ for (index, part) in parts[..wildcard].iter().enumerate() {
11
+ octets[index] = part.parse().ok()?;
12
+ }
13
+
14
+ Some(format!(
15
+ "{}.{}.{}.{}/{}",
16
+ octets[0],
17
+ octets[1],
18
+ octets[2],
19
+ octets[3],
20
+ wildcard * 8
21
+ ))
22
+ }
23
+
24
+ pub(super) fn normalize_proxy_override(value: &str) -> String {
25
+ value
26
+ .split(';')
27
+ .map(|entry| {
28
+ let entry = entry.trim();
29
+ ipv4_wildcard_to_cidr(entry).unwrap_or_else(|| entry.to_string())
30
+ })
31
+ .collect::<Vec<_>>()
32
+ .join(",")
33
+ .replace("*.", "")
34
+ }
35
+
1
36
  pub(super) fn with_system(builder: &mut super::matcher::Builder) {
2
37
  let Ok(settings) = windows_registry::CURRENT_USER
3
38
  .open("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")
@@ -18,14 +53,9 @@ pub(super) fn with_system(builder: &mut super::matcher::Builder) {
18
53
  }
19
54
  }
20
55
 
21
- if builder.no.is_empty() {
22
- if let Ok(val) = settings.get_string("ProxyOverride") {
23
- builder.no = val
24
- .split(';')
25
- .map(|s| s.trim())
26
- .collect::<Vec<&str>>()
27
- .join(",")
28
- .replace("*.", "");
29
- }
56
+ if builder.no.is_empty()
57
+ && let Ok(val) = settings.get_string("ProxyOverride")
58
+ {
59
+ builder.no = normalize_proxy_override(&val);
30
60
  }
31
61
  }