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,502 @@
1
+ use std::{error::Error as StdError, fmt, io};
2
+
3
+ use http::Uri;
4
+
5
+ use crate::{StatusCode, client::ext::ReasonPhrase, util::Escape};
6
+
7
+ /// A `Result` alias where the `Err` case is `wreq::Error`.
8
+ pub type Result<T> = std::result::Result<T, Error>;
9
+
10
+ /// A boxed error type that can be used for dynamic error handling.
11
+ pub type BoxError = Box<dyn StdError + Send + Sync>;
12
+
13
+ /// The Errors that may occur when processing a `Request`.
14
+ ///
15
+ /// Note: Errors may include the full URI used to make the `Request`. If the URI
16
+ /// contains sensitive information (e.g. an API key as a query parameter), be
17
+ /// sure to remove it ([`without_uri`](Error::without_uri))
18
+ pub struct Error {
19
+ inner: Box<Inner>,
20
+ }
21
+
22
+ struct Inner {
23
+ kind: Kind,
24
+ source: Option<BoxError>,
25
+ uri: Option<Uri>,
26
+ }
27
+
28
+ impl Error {
29
+ pub(crate) fn new<E>(kind: Kind, source: Option<E>) -> Error
30
+ where
31
+ E: Into<BoxError>,
32
+ {
33
+ Error {
34
+ inner: Box::new(Inner {
35
+ kind,
36
+ source: source.map(Into::into),
37
+ uri: None,
38
+ }),
39
+ }
40
+ }
41
+
42
+ pub(crate) fn builder<E: Into<BoxError>>(e: E) -> Error {
43
+ Error::new(Kind::Builder, Some(e))
44
+ }
45
+
46
+ pub(crate) fn body<E: Into<BoxError>>(e: E) -> Error {
47
+ Error::new(Kind::Body, Some(e))
48
+ }
49
+
50
+ pub(crate) fn tls<E: Into<BoxError>>(e: E) -> Error {
51
+ Error::new(Kind::Tls, Some(e))
52
+ }
53
+
54
+ pub(crate) fn decode<E: Into<BoxError>>(e: E) -> Error {
55
+ Error::new(Kind::Decode, Some(e))
56
+ }
57
+
58
+ pub(crate) fn request<E: Into<BoxError>>(e: E) -> Error {
59
+ Error::new(Kind::Request, Some(e))
60
+ }
61
+
62
+ pub(crate) fn redirect<E: Into<BoxError>>(e: E, uri: Uri) -> Error {
63
+ Error::new(Kind::Redirect, Some(e)).with_uri(uri)
64
+ }
65
+
66
+ pub(crate) fn upgrade<E: Into<BoxError>>(e: E) -> Error {
67
+ Error::new(Kind::Upgrade, Some(e))
68
+ }
69
+
70
+ #[cfg(feature = "ws")]
71
+ pub(crate) fn websocket<E: Into<BoxError>>(e: E) -> Error {
72
+ Error::new(Kind::WebSocket, Some(e))
73
+ }
74
+
75
+ pub(crate) fn status_code(uri: Uri, status: StatusCode, reason: Option<ReasonPhrase>) -> Error {
76
+ Error::new(Kind::Status(status, reason), None::<Error>).with_uri(uri)
77
+ }
78
+
79
+ pub(crate) fn uri_bad_scheme(uri: Uri) -> Error {
80
+ Error::new(Kind::Builder, Some(BadScheme)).with_uri(uri)
81
+ }
82
+ }
83
+
84
+ impl Error {
85
+ /// Returns a possible URI related to this error.
86
+ ///
87
+ /// # Examples
88
+ ///
89
+ /// ```
90
+ /// # async fn run() {
91
+ /// // displays last stop of a redirect loop
92
+ /// let response = wreq::get("http://site.with.redirect.loop")
93
+ /// .send()
94
+ /// .await;
95
+ /// if let Err(e) = response {
96
+ /// if e.is_redirect() {
97
+ /// if let Some(final_stop) = e.uri() {
98
+ /// println!("redirect loop at {}", final_stop);
99
+ /// }
100
+ /// }
101
+ /// }
102
+ /// # }
103
+ /// ```
104
+ pub fn uri(&self) -> Option<&Uri> {
105
+ self.inner.uri.as_ref()
106
+ }
107
+
108
+ /// Returns a mutable reference to the URI related to this error
109
+ ///
110
+ /// This is useful if you need to remove sensitive information from the URI
111
+ /// (e.g. an API key in the query), but do not want to remove the URI
112
+ /// entirely.
113
+ pub fn uri_mut(&mut self) -> Option<&mut Uri> {
114
+ self.inner.uri.as_mut()
115
+ }
116
+
117
+ /// Add a uri related to this error (overwriting any existing)
118
+ pub fn with_uri(mut self, uri: Uri) -> Self {
119
+ self.inner.uri = Some(uri);
120
+ self
121
+ }
122
+
123
+ /// Strip the related uri from this error (if, for example, it contains
124
+ /// sensitive information)
125
+ pub fn without_uri(mut self) -> Self {
126
+ self.inner.uri = None;
127
+ self
128
+ }
129
+
130
+ /// Returns true if the error is from a type Builder.
131
+ pub fn is_builder(&self) -> bool {
132
+ matches!(self.inner.kind, Kind::Builder)
133
+ }
134
+
135
+ /// Returns true if the error is from a `RedirectPolicy`.
136
+ pub fn is_redirect(&self) -> bool {
137
+ matches!(self.inner.kind, Kind::Redirect)
138
+ }
139
+
140
+ /// Returns true if the error is from `Response::error_for_status`.
141
+ pub fn is_status(&self) -> bool {
142
+ matches!(self.inner.kind, Kind::Status(_, _))
143
+ }
144
+
145
+ /// Returns true if the error is related to a timeout.
146
+ pub fn is_timeout(&self) -> bool {
147
+ let mut source = self.source();
148
+
149
+ while let Some(err) = source {
150
+ if err.is::<TimedOut>() {
151
+ return true;
152
+ }
153
+
154
+ if let Some(core_err) = err.downcast_ref::<crate::client::CoreError>() {
155
+ if core_err.is_timeout() {
156
+ return true;
157
+ }
158
+ }
159
+
160
+ if let Some(io) = err.downcast_ref::<io::Error>() {
161
+ if io.kind() == io::ErrorKind::TimedOut {
162
+ return true;
163
+ }
164
+ }
165
+
166
+ source = err.source();
167
+ }
168
+
169
+ false
170
+ }
171
+
172
+ /// Returns true if the error is related to the request
173
+ pub fn is_request(&self) -> bool {
174
+ matches!(self.inner.kind, Kind::Request)
175
+ }
176
+
177
+ /// Returns true if the error is related to connect
178
+ pub fn is_connect(&self) -> bool {
179
+ use crate::client::Error;
180
+
181
+ let mut source = self.source();
182
+
183
+ while let Some(err) = source {
184
+ if let Some(err) = err.downcast_ref::<Error>() {
185
+ if err.is_connect() {
186
+ return true;
187
+ }
188
+ }
189
+
190
+ source = err.source();
191
+ }
192
+
193
+ false
194
+ }
195
+
196
+ /// Returns true if the error is related to proxy connect
197
+ pub fn is_proxy_connect(&self) -> bool {
198
+ use crate::client::Error;
199
+
200
+ let mut source = self.source();
201
+
202
+ while let Some(err) = source {
203
+ if let Some(err) = err.downcast_ref::<Error>() {
204
+ if err.is_proxy_connect() {
205
+ return true;
206
+ }
207
+ }
208
+
209
+ source = err.source();
210
+ }
211
+
212
+ false
213
+ }
214
+
215
+ /// Returns true if the error is related to a connection reset.
216
+ pub fn is_connection_reset(&self) -> bool {
217
+ let mut source = self.source();
218
+
219
+ while let Some(err) = source {
220
+ if let Some(io) = err.downcast_ref::<io::Error>() {
221
+ if io.kind() == io::ErrorKind::ConnectionReset {
222
+ return true;
223
+ }
224
+ }
225
+ source = err.source();
226
+ }
227
+
228
+ false
229
+ }
230
+
231
+ /// Returns true if the error is related to the request or response body
232
+ pub fn is_body(&self) -> bool {
233
+ matches!(self.inner.kind, Kind::Body)
234
+ }
235
+
236
+ /// Returns true if the error is related to TLS
237
+ pub fn is_tls(&self) -> bool {
238
+ matches!(self.inner.kind, Kind::Tls)
239
+ }
240
+
241
+ /// Returns true if the error is related to decoding the response's body
242
+ pub fn is_decode(&self) -> bool {
243
+ matches!(self.inner.kind, Kind::Decode)
244
+ }
245
+
246
+ /// Returns true if the error is related to upgrading the connection
247
+ pub fn is_upgrade(&self) -> bool {
248
+ matches!(self.inner.kind, Kind::Upgrade)
249
+ }
250
+
251
+ #[cfg(feature = "ws")]
252
+ /// Returns true if the error is related to WebSocket operations
253
+ pub fn is_websocket(&self) -> bool {
254
+ matches!(self.inner.kind, Kind::WebSocket)
255
+ }
256
+
257
+ /// Returns the status code, if the error was generated from a response.
258
+ pub fn status(&self) -> Option<StatusCode> {
259
+ match self.inner.kind {
260
+ Kind::Status(code, _) => Some(code),
261
+ _ => None,
262
+ }
263
+ }
264
+ }
265
+
266
+ /// Maps external timeout errors (such as `tower::timeout::error::Elapsed`)
267
+ /// to the internal `TimedOut` error type used for connector operations.
268
+ /// Returns the original error if it is not a timeout.
269
+ #[inline]
270
+ pub(crate) fn map_timeout_to_connector_error(error: BoxError) -> BoxError {
271
+ if error.is::<tower::timeout::error::Elapsed>() {
272
+ Box::new(TimedOut)
273
+ } else {
274
+ error
275
+ }
276
+ }
277
+
278
+ /// Maps external timeout errors (such as `tower::timeout::error::Elapsed`)
279
+ /// to the internal request-level `Error` type.
280
+ /// Returns the original error if it is not a timeout.
281
+ #[inline]
282
+ pub(crate) fn map_timeout_to_request_error(error: BoxError) -> BoxError {
283
+ if error.is::<tower::timeout::error::Elapsed>() {
284
+ Box::new(Error::request(TimedOut))
285
+ } else {
286
+ error
287
+ }
288
+ }
289
+
290
+ impl fmt::Debug for Error {
291
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
292
+ let mut builder = f.debug_struct("wreq::Error");
293
+
294
+ builder.field("kind", &self.inner.kind);
295
+
296
+ if let Some(ref uri) = self.inner.uri {
297
+ builder.field("uri", uri);
298
+ }
299
+
300
+ if let Some(ref source) = self.inner.source {
301
+ builder.field("source", source);
302
+ }
303
+
304
+ builder.finish()
305
+ }
306
+ }
307
+
308
+ impl fmt::Display for Error {
309
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
310
+ match self.inner.kind {
311
+ Kind::Builder => f.write_str("builder error")?,
312
+ Kind::Request => f.write_str("error sending request")?,
313
+ Kind::Body => f.write_str("request or response body error")?,
314
+ Kind::Tls => f.write_str("tls error")?,
315
+ Kind::Decode => f.write_str("error decoding response body")?,
316
+ Kind::Redirect => f.write_str("error following redirect")?,
317
+ Kind::Upgrade => f.write_str("error upgrading connection")?,
318
+ #[cfg(feature = "ws")]
319
+ Kind::WebSocket => f.write_str("websocket error")?,
320
+ Kind::Status(ref code, ref reason) => {
321
+ let prefix = if code.is_client_error() {
322
+ "HTTP status client error"
323
+ } else {
324
+ debug_assert!(code.is_server_error());
325
+ "HTTP status server error"
326
+ };
327
+ if let Some(reason) = reason {
328
+ write!(
329
+ f,
330
+ "{prefix} ({} {})",
331
+ code.as_str(),
332
+ Escape::new(reason.as_bytes())
333
+ )?;
334
+ } else {
335
+ write!(f, "{prefix} ({code})")?;
336
+ }
337
+ }
338
+ };
339
+
340
+ if let Some(uri) = &self.inner.uri {
341
+ write!(f, " for uri ({})", uri)?;
342
+ }
343
+
344
+ if let Some(e) = &self.inner.source {
345
+ write!(f, ": {e}")?;
346
+ }
347
+
348
+ Ok(())
349
+ }
350
+ }
351
+
352
+ impl StdError for Error {
353
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
354
+ self.inner.source.as_ref().map(|e| &**e as _)
355
+ }
356
+ }
357
+
358
+ #[derive(Debug)]
359
+ pub(crate) enum Kind {
360
+ Builder,
361
+ Request,
362
+ Tls,
363
+ Redirect,
364
+ Status(StatusCode, Option<ReasonPhrase>),
365
+ Body,
366
+ Decode,
367
+ Upgrade,
368
+ #[cfg(feature = "ws")]
369
+ WebSocket,
370
+ }
371
+
372
+ #[derive(Debug)]
373
+ pub(crate) struct TimedOut;
374
+
375
+ #[derive(Debug)]
376
+ pub(crate) struct BadScheme;
377
+
378
+ #[derive(Debug)]
379
+ pub(crate) struct ProxyConnect(pub(crate) BoxError);
380
+
381
+ // ==== impl TimedOut ====
382
+
383
+ impl fmt::Display for TimedOut {
384
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
385
+ f.write_str("operation timed out")
386
+ }
387
+ }
388
+
389
+ impl StdError for TimedOut {}
390
+
391
+ // ==== impl BadScheme ====
392
+
393
+ impl fmt::Display for BadScheme {
394
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
395
+ f.write_str("URI scheme is not allowed")
396
+ }
397
+ }
398
+
399
+ impl StdError for BadScheme {}
400
+
401
+ // ==== impl ProxyConnect ====
402
+
403
+ impl fmt::Display for ProxyConnect {
404
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
405
+ write!(f, "proxy connect error: {}", self.0)
406
+ }
407
+ }
408
+
409
+ impl StdError for ProxyConnect {
410
+ fn source(&self) -> Option<&(dyn StdError + 'static)> {
411
+ Some(&*self.0)
412
+ }
413
+ }
414
+
415
+ #[cfg(test)]
416
+ mod tests {
417
+ use super::*;
418
+
419
+ fn assert_send<T: Send>() {}
420
+ fn assert_sync<T: Sync>() {}
421
+
422
+ impl super::Error {
423
+ fn into_io(self) -> io::Error {
424
+ io::Error::other(self)
425
+ }
426
+ }
427
+
428
+ fn decode_io(e: io::Error) -> Error {
429
+ if e.get_ref().map(|r| r.is::<Error>()).unwrap_or(false) {
430
+ *e.into_inner()
431
+ .expect("io::Error::get_ref was Some(_)")
432
+ .downcast::<Error>()
433
+ .expect("StdError::is() was true")
434
+ } else {
435
+ Error::decode(e)
436
+ }
437
+ }
438
+
439
+ #[test]
440
+ fn test_source_chain() {
441
+ let root = Error::new(Kind::Request, None::<Error>);
442
+ assert!(root.source().is_none());
443
+
444
+ let link = Error::body(root);
445
+ assert!(link.source().is_some());
446
+ assert_send::<Error>();
447
+ assert_sync::<Error>();
448
+ }
449
+
450
+ #[test]
451
+ fn mem_size_of() {
452
+ use std::mem::size_of;
453
+ assert_eq!(size_of::<Error>(), size_of::<usize>());
454
+ }
455
+
456
+ #[test]
457
+ fn roundtrip_io_error() {
458
+ let orig = Error::request("orig");
459
+ // Convert wreq::Error into an io::Error...
460
+ let io = orig.into_io();
461
+ // Convert that io::Error back into a wreq::Error...
462
+ let err = decode_io(io);
463
+ // It should have pulled out the original, not nested it...
464
+ match err.inner.kind {
465
+ Kind::Request => (),
466
+ _ => panic!("{err:?}"),
467
+ }
468
+ }
469
+
470
+ #[test]
471
+ fn from_unknown_io_error() {
472
+ let orig = io::Error::other("orly");
473
+ let err = decode_io(orig);
474
+ match err.inner.kind {
475
+ Kind::Decode => (),
476
+ _ => panic!("{err:?}"),
477
+ }
478
+ }
479
+
480
+ #[test]
481
+ fn is_timeout() {
482
+ let err = Error::request(super::TimedOut);
483
+ assert!(err.is_timeout());
484
+
485
+ let io = io::Error::from(io::ErrorKind::TimedOut);
486
+ let nested = Error::request(io);
487
+ assert!(nested.is_timeout());
488
+ }
489
+
490
+ #[test]
491
+ fn is_connection_reset() {
492
+ let err = Error::request(io::Error::new(
493
+ io::ErrorKind::ConnectionReset,
494
+ "connection reset",
495
+ ));
496
+ assert!(err.is_connection_reset());
497
+
498
+ let io = io::Error::other(err);
499
+ let nested = Error::request(io);
500
+ assert!(nested.is_connection_reset());
501
+ }
502
+ }