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,66 @@
1
+ use std::{
2
+ path::{Path, PathBuf},
3
+ sync::Arc,
4
+ };
5
+
6
+ /// Trait for converting various types into a shared Unix Domain Socket path (`Arc<Path>`).
7
+ ///
8
+ /// This trait is sealed to allow future extension while controlling which types can implement it.
9
+ /// It enables ergonomic conversion from common path types such as `String`, `&str`, `PathBuf`,
10
+ /// `&Path`, and `Arc<Path>` into a unified `Arc<Path>` representation for Unix socket usage.
11
+ ///
12
+ /// # Supported types
13
+ /// - `String`
14
+ /// - `&str`
15
+ /// - `PathBuf`
16
+ /// - `&Path`
17
+ /// - `Arc<Path>`
18
+ pub trait IntoUnixSocket: sealed::Sealed {
19
+ /// Returns the Unix Domain Socket path as an [`Arc<Path>`].
20
+ fn unix_socket(self) -> Arc<Path>;
21
+ }
22
+
23
+ impl IntoUnixSocket for String {
24
+ fn unix_socket(self) -> Arc<Path> {
25
+ Arc::from(PathBuf::from(self))
26
+ }
27
+ }
28
+
29
+ impl IntoUnixSocket for &'_ str {
30
+ fn unix_socket(self) -> Arc<Path> {
31
+ Arc::from(PathBuf::from(self))
32
+ }
33
+ }
34
+
35
+ impl IntoUnixSocket for &'_ Path {
36
+ fn unix_socket(self) -> Arc<Path> {
37
+ Arc::from(self)
38
+ }
39
+ }
40
+ impl IntoUnixSocket for PathBuf {
41
+ fn unix_socket(self) -> Arc<Path> {
42
+ Arc::from(self)
43
+ }
44
+ }
45
+
46
+ impl IntoUnixSocket for Arc<Path> {
47
+ fn unix_socket(self) -> Arc<Path> {
48
+ self
49
+ }
50
+ }
51
+
52
+ mod sealed {
53
+ use std::{
54
+ path::{Path, PathBuf},
55
+ sync::Arc,
56
+ };
57
+
58
+ /// Sealed trait to prevent external implementations of `IntoUnixSocket`.
59
+ pub trait Sealed {}
60
+
61
+ impl Sealed for String {}
62
+ impl Sealed for &'_ str {}
63
+ impl Sealed for &'_ Path {}
64
+ impl Sealed for PathBuf {}
65
+ impl Sealed for Arc<Path> {}
66
+ }
@@ -0,0 +1,31 @@
1
+ pub(super) fn with_system(builder: &mut super::matcher::Builder) {
2
+ let Ok(settings) = windows_registry::CURRENT_USER
3
+ .open("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings")
4
+ else {
5
+ return;
6
+ };
7
+
8
+ if settings.get_u32("ProxyEnable").unwrap_or(0) == 0 {
9
+ return;
10
+ }
11
+
12
+ if let Ok(val) = settings.get_string("ProxyServer") {
13
+ if builder.http.is_empty() {
14
+ builder.http = val.clone();
15
+ }
16
+ if builder.https.is_empty() {
17
+ builder.https = val;
18
+ }
19
+ }
20
+
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
+ }
30
+ }
31
+ }
@@ -0,0 +1,569 @@
1
+ #[cfg(all(target_os = "macos", feature = "system-proxy"))]
2
+ mod mac;
3
+ #[cfg(unix)]
4
+ mod uds;
5
+ #[cfg(all(windows, feature = "system-proxy"))]
6
+ mod win;
7
+
8
+ pub(crate) mod matcher;
9
+
10
+ use std::hash::{Hash, Hasher};
11
+ #[cfg(unix)]
12
+ use std::{path::Path, sync::Arc};
13
+
14
+ use http::{HeaderMap, Uri, header::HeaderValue};
15
+
16
+ use crate::{IntoUri, ext::UriExt};
17
+
18
+ // # Internals
19
+ //
20
+ // This module is a couple pieces:
21
+ //
22
+ // - The public builder API
23
+ // - The internal built types that our Connector knows how to use.
24
+ //
25
+ // The user creates a builder (`wreq::Proxy`), and configures any extras.
26
+ // Once that type is passed to the `ClientBuilder`, we convert it into the
27
+ // built matcher types, making use of `core`'s matchers.
28
+
29
+ /// Configuration of a proxy that a `Client` should pass requests to.
30
+ ///
31
+ /// A `Proxy` has a couple pieces to it:
32
+ ///
33
+ /// - a URI of how to talk to the proxy
34
+ /// - rules on what `Client` requests should be directed to the proxy
35
+ ///
36
+ /// For instance, let's look at `Proxy::http`:
37
+ ///
38
+ /// ```rust
39
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
40
+ /// let proxy = wreq::Proxy::http("https://secure.example")?;
41
+ /// # Ok(())
42
+ /// # }
43
+ /// ```
44
+ ///
45
+ /// This proxy will intercept all HTTP requests, and make use of the proxy
46
+ /// at `https://secure.example`. A request to `http://hyper.rs` will talk
47
+ /// to your proxy. A request to `https://hyper.rs` will not.
48
+ ///
49
+ /// Multiple `Proxy` rules can be configured for a `Client`. The `Client` will
50
+ /// check each `Proxy` in the order it was added. This could mean that a
51
+ /// `Proxy` added first with eager intercept rules, such as `Proxy::all`,
52
+ /// would prevent a `Proxy` later in the list from ever working, so take care.
53
+ ///
54
+ /// By enabling the `"socks"` feature it is possible to use a socks proxy:
55
+ /// ```rust
56
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
57
+ /// let proxy = wreq::Proxy::http("socks5://192.168.1.1:9000")?;
58
+ /// # Ok(())
59
+ /// # }
60
+ /// ```
61
+ #[derive(Clone, Debug)]
62
+ pub struct Proxy {
63
+ extra: Extra,
64
+ scheme: ProxyScheme,
65
+ no_proxy: Option<NoProxy>,
66
+ }
67
+
68
+ /// A configuration for filtering out requests that shouldn't be proxied
69
+ #[derive(Clone, Debug, Default)]
70
+ pub struct NoProxy {
71
+ inner: String,
72
+ }
73
+
74
+ // ===== Internal =====
75
+
76
+ #[allow(clippy::large_enum_variant)]
77
+ #[derive(Clone, PartialEq, Eq)]
78
+ pub(crate) enum Intercepted {
79
+ Proxy(matcher::Intercept),
80
+ #[cfg(unix)]
81
+ Unix(Arc<Path>),
82
+ }
83
+
84
+ #[derive(Debug, Clone, PartialEq, Eq, Hash)]
85
+ pub(crate) struct Matcher {
86
+ inner: Box<matcher::Matcher>,
87
+ }
88
+
89
+ #[derive(Clone, Debug)]
90
+ enum ProxyScheme {
91
+ All(Uri),
92
+ Http(Uri),
93
+ Https(Uri),
94
+ #[cfg(unix)]
95
+ Unix(Arc<Path>),
96
+ }
97
+
98
+ #[derive(Debug, Clone, Default, PartialEq, Eq)]
99
+ struct Extra {
100
+ auth: Option<HeaderValue>,
101
+ misc: Option<HeaderMap>,
102
+ }
103
+
104
+ // ===== impl Proxy =====
105
+
106
+ impl Proxy {
107
+ /// Proxy all HTTP traffic to the passed URI.
108
+ ///
109
+ /// # Example
110
+ ///
111
+ /// ```
112
+ /// # extern crate wreq;
113
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
114
+ /// let client = wreq::Client::builder()
115
+ /// .proxy(wreq::Proxy::http("https://my.prox")?)
116
+ /// .build()?;
117
+ /// # Ok(())
118
+ /// # }
119
+ /// # fn main() {}
120
+ /// ```
121
+ pub fn http<U: IntoUri>(uri: U) -> crate::Result<Proxy> {
122
+ uri.into_uri().map(ProxyScheme::Http).map(Proxy::new)
123
+ }
124
+
125
+ /// Proxy all HTTPS traffic to the passed URI.
126
+ ///
127
+ /// # Example
128
+ ///
129
+ /// ```
130
+ /// # extern crate wreq;
131
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
132
+ /// let client = wreq::Client::builder()
133
+ /// .proxy(wreq::Proxy::https("https://example.prox:4545")?)
134
+ /// .build()?;
135
+ /// # Ok(())
136
+ /// # }
137
+ /// # fn main() {}
138
+ /// ```
139
+ pub fn https<U: IntoUri>(uri: U) -> crate::Result<Proxy> {
140
+ uri.into_uri().map(ProxyScheme::Https).map(Proxy::new)
141
+ }
142
+
143
+ /// Proxy **all** traffic to the passed URI.
144
+ ///
145
+ /// "All" refers to `https` and `http` URIs. Other schemes are not
146
+ /// recognized by wreq.
147
+ ///
148
+ /// # Example
149
+ ///
150
+ /// ```
151
+ /// # extern crate wreq;
152
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
153
+ /// let client = wreq::Client::builder()
154
+ /// .proxy(wreq::Proxy::all("http://pro.xy")?)
155
+ /// .build()?;
156
+ /// # Ok(())
157
+ /// # }
158
+ /// # fn main() {}
159
+ /// ```
160
+ pub fn all<U: IntoUri>(uri: U) -> crate::Result<Proxy> {
161
+ uri.into_uri().map(ProxyScheme::All).map(Proxy::new)
162
+ }
163
+
164
+ /// Proxy all traffic to the passed Unix Domain Socket path.
165
+ ///
166
+ /// # Example
167
+ ///
168
+ /// ```
169
+ /// # extern crate wreq;
170
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
171
+ /// let client = wreq::Client::builder()
172
+ /// .proxy(wreq::Proxy::unix("/var/run/docker.sock")?)
173
+ /// .build()?;
174
+ /// # Ok(())
175
+ /// # }
176
+ /// # fn main() {}
177
+ /// ```
178
+ #[cfg(unix)]
179
+ pub fn unix<P: uds::IntoUnixSocket>(unix: P) -> crate::Result<Proxy> {
180
+ Ok(Proxy::new(ProxyScheme::Unix(unix.unix_socket())))
181
+ }
182
+
183
+ fn new(scheme: ProxyScheme) -> Proxy {
184
+ Proxy {
185
+ extra: Extra {
186
+ auth: None,
187
+ misc: None,
188
+ },
189
+ scheme,
190
+ no_proxy: None,
191
+ }
192
+ }
193
+
194
+ /// Set the `Proxy-Authorization` header using Basic auth.
195
+ ///
196
+ /// # Example
197
+ ///
198
+ /// ```
199
+ /// # extern crate wreq;
200
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
201
+ /// let proxy = wreq::Proxy::https("http://localhost:1234")?.basic_auth("Aladdin", "open sesame");
202
+ /// # Ok(())
203
+ /// # }
204
+ /// # fn main() {}
205
+ /// ```
206
+ pub fn basic_auth(mut self, username: &str, password: &str) -> Proxy {
207
+ match self.scheme {
208
+ ProxyScheme::All(ref mut uri)
209
+ | ProxyScheme::Http(ref mut uri)
210
+ | ProxyScheme::Https(ref mut uri) => {
211
+ let header = crate::util::basic_auth(username, Some(password));
212
+ uri.set_userinfo(username, Some(password));
213
+ self.extra.auth = Some(header);
214
+ }
215
+ #[cfg(unix)]
216
+ ProxyScheme::Unix(_) => {
217
+ // For Unix sockets, we don't set the auth header.
218
+ // This is a no-op, but keeps the API consistent.
219
+ }
220
+ }
221
+
222
+ self
223
+ }
224
+
225
+ /// Set the `Proxy-Authorization` header to a specified value.
226
+ ///
227
+ /// # Example
228
+ ///
229
+ /// ```
230
+ /// # extern crate wreq;
231
+ /// # use wreq::header::*;
232
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
233
+ /// let proxy = wreq::Proxy::https("http://localhost:1234")?
234
+ /// .custom_http_auth(HeaderValue::from_static("justletmeinalreadyplease"));
235
+ /// # Ok(())
236
+ /// # }
237
+ /// # fn main() {}
238
+ /// ```
239
+ pub fn custom_http_auth(mut self, header_value: HeaderValue) -> Proxy {
240
+ self.extra.auth = Some(header_value);
241
+ self
242
+ }
243
+
244
+ /// Adds a Custom Headers to Proxy
245
+ /// Adds custom headers to this Proxy
246
+ ///
247
+ /// # Example
248
+ /// ```
249
+ /// # extern crate wreq;
250
+ /// # use wreq::header::*;
251
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
252
+ /// let mut headers = HeaderMap::new();
253
+ /// headers.insert(USER_AGENT, "wreq".parse().unwrap());
254
+ /// let proxy = wreq::Proxy::https("http://localhost:1234")?.custom_http_headers(headers);
255
+ /// # Ok(())
256
+ /// # }
257
+ /// # fn main() {}
258
+ /// ```
259
+ pub fn custom_http_headers(mut self, headers: HeaderMap) -> Proxy {
260
+ match self.scheme {
261
+ ProxyScheme::All(_) | ProxyScheme::Http(_) | ProxyScheme::Https(_) => {
262
+ self.extra.misc = Some(headers);
263
+ }
264
+ #[cfg(unix)]
265
+ ProxyScheme::Unix(_) => {
266
+ // For Unix sockets, we don't set custom headers.
267
+ // This is a no-op, but keeps the API consistent.
268
+ }
269
+ }
270
+
271
+ self
272
+ }
273
+
274
+ /// Adds a `No Proxy` exclusion list to this Proxy
275
+ ///
276
+ /// # Example
277
+ ///
278
+ /// ```
279
+ /// # extern crate wreq;
280
+ /// # fn run() -> Result<(), Box<dyn std::error::Error>> {
281
+ /// let proxy = wreq::Proxy::https("http://localhost:1234")?
282
+ /// .no_proxy(wreq::NoProxy::from_string("direct.tld, sub.direct2.tld"));
283
+ /// # Ok(())
284
+ /// # }
285
+ /// # fn main() {}
286
+ /// ```
287
+ pub fn no_proxy(mut self, no_proxy: Option<NoProxy>) -> Proxy {
288
+ self.no_proxy = no_proxy;
289
+ self
290
+ }
291
+
292
+ pub(crate) fn into_matcher(self) -> Matcher {
293
+ let Proxy {
294
+ scheme,
295
+ extra,
296
+ no_proxy,
297
+ } = self;
298
+
299
+ let no_proxy = no_proxy.as_ref().map_or("", |n| n.inner.as_ref());
300
+
301
+ let inner = match scheme {
302
+ ProxyScheme::All(uri) => matcher::Matcher::builder()
303
+ .all(uri.to_string())
304
+ .no(no_proxy)
305
+ .build(extra),
306
+ ProxyScheme::Http(uri) => matcher::Matcher::builder()
307
+ .http(uri.to_string())
308
+ .no(no_proxy)
309
+ .build(extra),
310
+ ProxyScheme::Https(uri) => matcher::Matcher::builder()
311
+ .https(uri.to_string())
312
+ .no(no_proxy)
313
+ .build(extra),
314
+ #[cfg(unix)]
315
+ ProxyScheme::Unix(unix) => matcher::Matcher::builder()
316
+ .unix(unix)
317
+ .no(no_proxy)
318
+ .build(extra),
319
+ };
320
+
321
+ Matcher {
322
+ inner: Box::new(inner),
323
+ }
324
+ }
325
+ }
326
+
327
+ // ===== impl NoProxy =====
328
+
329
+ impl NoProxy {
330
+ /// Returns a new no-proxy configuration based on environment variables (or `None` if no
331
+ /// variables are set) see [self::NoProxy::from_string()] for the string format
332
+ pub fn from_env() -> Option<NoProxy> {
333
+ let raw = std::env::var("NO_PROXY")
334
+ .or_else(|_| std::env::var("no_proxy"))
335
+ .ok()?;
336
+
337
+ // Per the docs, this returns `None` if no environment variable is set. We can only reach
338
+ // here if an env var is set, so we return `Some(NoProxy::default)` if `from_string`
339
+ // returns None, which occurs with an empty string.
340
+ Some(Self::from_string(&raw).unwrap_or_default())
341
+ }
342
+
343
+ /// Returns a new no-proxy configuration based on a `no_proxy` string (or `None` if no variables
344
+ /// are set)
345
+ /// The rules are as follows:
346
+ /// * The environment variable `NO_PROXY` is checked, if it is not set, `no_proxy` is checked
347
+ /// * If neither environment variable is set, `None` is returned
348
+ /// * Entries are expected to be comma-separated (whitespace between entries is ignored)
349
+ /// * IP addresses (both IPv4 and IPv6) are allowed, as are optional subnet masks (by adding
350
+ /// /size, for example "`192.168.1.0/24`").
351
+ /// * An entry "`*`" matches all hostnames (this is the only wildcard allowed)
352
+ /// * Any other entry is considered a domain name (and may contain a leading dot, for example
353
+ /// `google.com` and `.google.com` are equivalent) and would match both that domain AND all
354
+ /// subdomains.
355
+ ///
356
+ /// For example, if `"NO_PROXY=google.com, 192.168.1.0/24"` was set, all the following would
357
+ /// match (and therefore would bypass the proxy):
358
+ /// * `http://google.com/`
359
+ /// * `http://www.google.com/`
360
+ /// * `http://192.168.1.42/`
361
+ ///
362
+ /// The URI `http://notgoogle.com/` would not match.
363
+ pub fn from_string(no_proxy_list: &str) -> Option<Self> {
364
+ Some(NoProxy {
365
+ inner: no_proxy_list.into(),
366
+ })
367
+ }
368
+ }
369
+
370
+ // ===== impl Matcher =====
371
+
372
+ impl Matcher {
373
+ pub(crate) fn system() -> Self {
374
+ Self {
375
+ inner: Box::new(matcher::Matcher::from_system()),
376
+ }
377
+ }
378
+
379
+ /// Intercept the given destination URI, returning the intercepted
380
+ /// proxy configuration if there is a match.
381
+ #[inline]
382
+ pub(crate) fn intercept(&self, dst: &Uri) -> Option<Intercepted> {
383
+ self.inner.intercept(dst)
384
+ }
385
+ }
386
+
387
+ // ===== impl Extra =====
388
+
389
+ impl Hash for Extra {
390
+ fn hash<H: Hasher>(&self, state: &mut H) {
391
+ self.auth.hash(state);
392
+ if let Some(ref misc) = self.misc {
393
+ for (k, v) in misc.iter() {
394
+ k.as_str().hash(state);
395
+ v.as_bytes().hash(state);
396
+ }
397
+ } else {
398
+ 1u8.hash(state);
399
+ }
400
+ }
401
+ }
402
+
403
+ #[cfg(test)]
404
+ mod tests {
405
+ use super::*;
406
+
407
+ fn uri(s: &str) -> Uri {
408
+ s.parse().unwrap()
409
+ }
410
+
411
+ fn intercept(p: &Matcher, s: &Uri) -> matcher::Intercept {
412
+ match p.intercept(s).unwrap() {
413
+ Intercepted::Proxy(proxy) => proxy,
414
+ #[cfg(unix)]
415
+ _ => {
416
+ unreachable!("intercepted_port should only be called with a Proxy matcher")
417
+ }
418
+ }
419
+ }
420
+
421
+ fn intercepted_uri(p: &Matcher, s: &str) -> Uri {
422
+ match p.intercept(&s.parse().unwrap()).unwrap() {
423
+ Intercepted::Proxy(proxy) => proxy.uri().clone(),
424
+ #[cfg(unix)]
425
+ _ => {
426
+ unreachable!("intercepted_uri should only be called with a Proxy matcher")
427
+ }
428
+ }
429
+ }
430
+
431
+ #[test]
432
+ fn test_http() {
433
+ let target = "http://example.domain/";
434
+ let p = Proxy::http(target).unwrap().into_matcher();
435
+
436
+ let http = "http://hyper.rs";
437
+ let other = "https://hyper.rs";
438
+
439
+ assert_eq!(intercepted_uri(&p, http), target);
440
+ assert!(p.intercept(&uri(other)).is_none());
441
+ }
442
+
443
+ #[test]
444
+ fn test_https() {
445
+ let target = "http://example.domain/";
446
+ let p = Proxy::https(target).unwrap().into_matcher();
447
+
448
+ let http = "http://hyper.rs";
449
+ let other = "https://hyper.rs";
450
+
451
+ assert!(p.intercept(&uri(http)).is_none());
452
+ assert_eq!(intercepted_uri(&p, other), target);
453
+ }
454
+
455
+ #[test]
456
+ fn test_all() {
457
+ let target = "http://example.domain/";
458
+ let p = Proxy::all(target).unwrap().into_matcher();
459
+
460
+ let http = "http://hyper.rs";
461
+ let https = "https://hyper.rs";
462
+ // no longer supported
463
+ //let other = "x-youve-never-heard-of-me-mr-proxy://hyper.rs";
464
+
465
+ assert_eq!(intercepted_uri(&p, http), target);
466
+ assert_eq!(intercepted_uri(&p, https), target);
467
+ //assert_eq!(intercepted_uri(&p, other), target);
468
+ }
469
+
470
+ #[test]
471
+ fn test_standard_with_custom_auth_header() {
472
+ let target = "http://example.domain/";
473
+ let p = Proxy::all(target)
474
+ .unwrap()
475
+ .custom_http_auth(http::HeaderValue::from_static("testme"))
476
+ .into_matcher();
477
+
478
+ let got = intercept(&p, &uri("http://anywhere.local"));
479
+ let auth = got.basic_auth().unwrap();
480
+ assert_eq!(auth, "testme");
481
+ }
482
+
483
+ #[test]
484
+ fn test_maybe_has_http_auth() {
485
+ let uri = uri("http://example.domain/");
486
+
487
+ let m = Proxy::all("https://letme:in@yo.local")
488
+ .unwrap()
489
+ .into_matcher();
490
+
491
+ let got = intercept(&m, &uri);
492
+ assert!(got.basic_auth().is_some(), "https forwards");
493
+
494
+ let m = Proxy::all("http://letme:in@yo.local")
495
+ .unwrap()
496
+ .into_matcher();
497
+
498
+ let got = intercept(&m, &uri);
499
+ assert!(got.basic_auth().is_some(), "http forwards");
500
+ }
501
+
502
+ #[test]
503
+ fn test_maybe_has_http_custom_headers() {
504
+ let uri = uri("http://example.domain/");
505
+
506
+ let mut headers = HeaderMap::new();
507
+ headers.insert("x-custom-header", HeaderValue::from_static("custom-value"));
508
+
509
+ let m = Proxy::all("https://yo.local")
510
+ .unwrap()
511
+ .custom_http_headers(headers.clone())
512
+ .into_matcher();
513
+
514
+ match m.intercept(&uri).unwrap() {
515
+ Intercepted::Proxy(proxy) => {
516
+ let got_headers = proxy.custom_headers().unwrap();
517
+ assert_eq!(got_headers, &headers, "https forwards");
518
+ }
519
+ #[cfg(unix)]
520
+ _ => {
521
+ unreachable!("Expected a Proxy Intercepted");
522
+ }
523
+ }
524
+
525
+ let m = Proxy::all("http://yo.local")
526
+ .unwrap()
527
+ .custom_http_headers(headers.clone())
528
+ .into_matcher();
529
+
530
+ match m.intercept(&uri).unwrap() {
531
+ Intercepted::Proxy(proxy) => {
532
+ let got_headers = proxy.custom_headers().unwrap();
533
+ assert_eq!(got_headers, &headers, "http forwards");
534
+ }
535
+ #[cfg(unix)]
536
+ _ => {
537
+ unreachable!("Expected a Proxy Intercepted");
538
+ }
539
+ }
540
+ }
541
+
542
+ fn test_socks_proxy_default_port(uri: &str, url2: &str, port: u16) {
543
+ let m = Proxy::all(uri).unwrap().into_matcher();
544
+
545
+ let http = "http://hyper.rs";
546
+ let https = "https://hyper.rs";
547
+
548
+ assert_eq!(intercepted_uri(&m, http).port_u16(), Some(1080));
549
+ assert_eq!(intercepted_uri(&m, https).port_u16(), Some(1080));
550
+
551
+ // custom port
552
+ let m = Proxy::all(url2).unwrap().into_matcher();
553
+
554
+ assert_eq!(intercepted_uri(&m, http).port_u16(), Some(port));
555
+ assert_eq!(intercepted_uri(&m, https).port_u16(), Some(port));
556
+ }
557
+
558
+ #[test]
559
+ fn test_socks4_proxy_default_port() {
560
+ test_socks_proxy_default_port("socks4://example.com", "socks4://example.com:1234", 1234);
561
+ test_socks_proxy_default_port("socks4a://example.com", "socks4a://example.com:1234", 1234);
562
+ }
563
+
564
+ #[test]
565
+ fn test_socks5_proxy_default_port() {
566
+ test_socks_proxy_default_port("socks5://example.com", "socks5://example.com:1234", 1234);
567
+ test_socks_proxy_default_port("socks5h://example.com", "socks5h://example.com:1234", 1234);
568
+ }
569
+ }