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
@@ -1,13 +1,14 @@
1
1
  //! HTTP header types
2
2
  //!
3
- //! This module provides [`HeaderName`], [`HeaderMap`], [`OrigHeaderMap`], [`OrigHeaderName`], and a
3
+ //! This module provides [`HeaderName`], [`HeaderMap`], [`OrigHeaderMap`], [`HeaderCaseName`], and a
4
4
  //! number of types used for interacting with `HeaderMap`. These types allow representing both
5
5
  //! HTTP/1 and HTTP/2 headers.
6
6
 
7
+ use bytes::Bytes;
7
8
  pub use http::header::*;
8
- pub use name::OrigHeaderName;
9
+ use wreq_proto::ext::OnPreserveHeaderCallback;
9
10
 
10
- /// Trait for types that can be converted into an [`OrigHeaderName`] (case-preserved header).
11
+ /// Trait for types that can be converted into an [`HeaderCaseName`] (case-preserved header).
11
12
  ///
12
13
  /// This trait is sealed, so only known types can implement it.
13
14
  /// Supported types:
@@ -16,11 +17,11 @@ pub use name::OrigHeaderName;
16
17
  /// - `Bytes`
17
18
  /// - `HeaderName`
18
19
  /// - `&HeaderName`
19
- /// - `OrigHeaderName`
20
- /// - `&OrigHeaderName`
21
- pub trait IntoOrigHeaderName: sealed::Sealed {
22
- /// Converts the type into an [`OrigHeaderName`].
23
- fn into_orig_header_name(self) -> OrigHeaderName;
20
+ /// - `HeaderCaseName`
21
+ /// - `&HeaderCaseName`
22
+ pub trait IntoHeaderCaseName: sealed::Sealed {
23
+ /// Converts the type into an [`HeaderCaseName`].
24
+ fn into_header_case_name(self) -> HeaderCaseName;
24
25
  }
25
26
 
26
27
  /// A map from header names to their original casing as received in an HTTP message.
@@ -29,8 +30,8 @@ pub trait IntoOrigHeaderName: sealed::Sealed {
29
30
  /// in the request or response, but also maintains the insertion order of headers. This makes
30
31
  /// it suitable for use cases where the order of headers matters, such as HTTP/1.x message
31
32
  /// serialization, proxying, or reproducing requests/responses exactly as received.
32
- #[derive(Debug, Clone, Default)]
33
- pub struct OrigHeaderMap(HeaderMap<OrigHeaderName>);
33
+ #[derive(Debug, Clone, Default, PartialEq, Eq)]
34
+ pub struct OrigHeaderMap(HeaderMap<HeaderCaseName>);
34
35
 
35
36
  // ===== impl OrigHeaderMap =====
36
37
 
@@ -59,16 +60,14 @@ impl OrigHeaderMap {
59
60
  #[inline]
60
61
  pub fn insert<N>(&mut self, orig: N) -> bool
61
62
  where
62
- N: IntoOrigHeaderName,
63
+ N: IntoHeaderCaseName,
63
64
  {
64
- let orig_header_name = orig.into_orig_header_name();
65
- match &orig_header_name.kind {
66
- name::Kind::Cased(bytes) => HeaderName::from_bytes(bytes)
67
- .map(|name| self.0.append(name, orig_header_name))
65
+ let header_case_name = orig.into_header_case_name();
66
+ match &header_case_name.inner {
67
+ Repr::Cased(bytes) => HeaderName::from_bytes(bytes)
68
+ .map(|header_name| self.0.append(header_name, header_case_name))
68
69
  .unwrap_or(false),
69
- name::Kind::Standard(header_name) => {
70
- self.0.append(header_name.clone(), orig_header_name)
71
- }
70
+ Repr::Standard(header_name) => self.0.append(header_name.clone(), header_case_name),
72
71
  }
73
72
  }
74
73
 
@@ -96,15 +95,13 @@ impl OrigHeaderMap {
96
95
 
97
96
  /// Returns an iterator over all header names and their original spellings, in insertion order.
98
97
  #[inline]
99
- pub fn iter(&self) -> impl Iterator<Item = (&HeaderName, &OrigHeaderName)> {
98
+ pub fn iter(&self) -> impl Iterator<Item = (&HeaderName, &HeaderCaseName)> {
100
99
  self.0.iter()
101
100
  }
102
101
  }
103
102
 
104
- impl OrigHeaderMap {
105
- /// Sorts headers by this map, preserving original casing.
106
- /// Headers in the map come first, others follow.
107
- pub(crate) fn sort_headers(&self, headers: &mut HeaderMap) {
103
+ impl OnPreserveHeaderCallback for OrigHeaderMap {
104
+ fn call(&self, headers: &mut HeaderMap) {
108
105
  if headers.len() <= 1 || self.0.is_empty() {
109
106
  return;
110
107
  }
@@ -138,31 +135,30 @@ impl OrigHeaderMap {
138
135
  std::mem::swap(headers, &mut sorted_headers);
139
136
  }
140
137
 
141
- /// Calls the given function for each header in this map's order, preserving original casing.
142
- /// Headers in the map are processed first, others follow.
143
- pub(crate) fn sort_headers_for_each<F>(&self, headers: &mut HeaderMap, mut dst: F)
144
- where
145
- F: FnMut(&[u8], &HeaderValue),
146
- {
138
+ fn call_visit(
139
+ &self,
140
+ headers: &mut HeaderMap,
141
+ dst: &mut dyn FnMut(&dyn AsRef<[u8]>, &http::HeaderValue),
142
+ ) {
147
143
  // First, sort headers according to the order defined in this map
148
- for (name, orig_name) in self.iter() {
144
+ for (name, case_name) in self.iter() {
149
145
  for value in headers.get_all(name) {
150
- dst(orig_name.as_ref(), value);
146
+ dst(case_name, value);
151
147
  }
152
148
 
153
149
  headers.remove(name);
154
150
  }
155
151
 
156
152
  // After processing all ordered headers, append any remaining headers
157
- let mut prev_name: Option<OrigHeaderName> = None;
153
+ let mut prev_name: Option<HeaderCaseName> = None;
158
154
  for (name, value) in headers.drain() {
159
155
  match (name, &prev_name) {
160
156
  (Some(name), _) => {
161
- dst(name.as_ref(), &value);
162
- prev_name.replace(name.into_orig_header_name());
157
+ dst(&name, &value);
158
+ prev_name.replace(name.into_header_case_name());
163
159
  }
164
160
  (None, Some(prev_name)) => {
165
- dst(prev_name.as_ref(), &value);
161
+ dst(prev_name, &value);
166
162
  }
167
163
  _ => (),
168
164
  };
@@ -171,8 +167,8 @@ impl OrigHeaderMap {
171
167
  }
172
168
 
173
169
  impl<'a> IntoIterator for &'a OrigHeaderMap {
174
- type Item = (&'a HeaderName, &'a OrigHeaderName);
175
- type IntoIter = <&'a HeaderMap<OrigHeaderName> as IntoIterator>::IntoIter;
170
+ type Item = (&'a HeaderName, &'a HeaderCaseName);
171
+ type IntoIter = <&'a HeaderMap<HeaderCaseName> as IntoIterator>::IntoIter;
176
172
 
177
173
  #[inline]
178
174
  fn into_iter(self) -> Self::IntoIter {
@@ -181,8 +177,8 @@ impl<'a> IntoIterator for &'a OrigHeaderMap {
181
177
  }
182
178
 
183
179
  impl IntoIterator for OrigHeaderMap {
184
- type Item = (Option<HeaderName>, OrigHeaderName);
185
- type IntoIter = <HeaderMap<OrigHeaderName> as IntoIterator>::IntoIter;
180
+ type Item = (Option<HeaderName>, HeaderCaseName);
181
+ type IntoIter = <HeaderMap<HeaderCaseName> as IntoIterator>::IntoIter;
186
182
 
187
183
  #[inline]
188
184
  fn into_iter(self) -> Self::IntoIter {
@@ -192,94 +188,85 @@ impl IntoIterator for OrigHeaderMap {
192
188
 
193
189
  impl_request_config_value!(OrigHeaderMap);
194
190
 
195
- mod name {
196
- use bytes::Bytes;
197
- use http::HeaderName;
198
-
199
- use super::IntoOrigHeaderName;
200
-
201
- /// An HTTP header name with both normalized and original casing.
202
- ///
203
- /// While HTTP headers are case-insensitive, this type stores both
204
- /// the canonical `HeaderName` and the original casing as received,
205
- /// useful for preserving header order and formatting in proxies,
206
- /// debugging, or exact HTTP message reproduction.
207
- #[derive(Debug, Clone, PartialEq, Eq)]
208
- pub struct OrigHeaderName {
209
- pub(super) kind: Kind,
210
- }
191
+ /// An HTTP header name with both normalized and original casing.
192
+ ///
193
+ /// While HTTP headers are case-insensitive, this type stores both
194
+ /// the canonical [`HeaderName`] and the original casing as received,
195
+ /// useful for preserving header order and formatting in proxies,
196
+ /// debugging, or exact HTTP message reproduction.
197
+ #[derive(Debug, Clone, Hash, PartialEq, Eq)]
198
+ pub struct HeaderCaseName {
199
+ inner: Repr,
200
+ }
211
201
 
212
- #[derive(Debug, Clone, PartialEq, Eq)]
213
- pub(super) enum Kind {
214
- /// The original casing of the header name as received.
215
- Cased(Bytes),
216
- /// The canonical (normalized, lowercased) header name.
217
- Standard(HeaderName),
218
- }
202
+ #[derive(Debug, Clone, Hash, PartialEq, Eq)]
203
+ enum Repr {
204
+ Cased(Bytes),
205
+ Standard(HeaderName),
206
+ }
219
207
 
220
- impl AsRef<[u8]> for OrigHeaderName {
221
- #[inline]
222
- fn as_ref(&self) -> &[u8] {
223
- match &self.kind {
224
- Kind::Standard(name) => name.as_ref(),
225
- Kind::Cased(orig) => orig.as_ref(),
226
- }
208
+ impl AsRef<[u8]> for HeaderCaseName {
209
+ #[inline]
210
+ fn as_ref(&self) -> &[u8] {
211
+ match &self.inner {
212
+ Repr::Standard(name) => name.as_ref(),
213
+ Repr::Cased(orig) => orig.as_ref(),
227
214
  }
228
215
  }
216
+ }
229
217
 
230
- impl IntoOrigHeaderName for &'static str {
231
- #[inline]
232
- fn into_orig_header_name(self) -> OrigHeaderName {
233
- Bytes::from_static(self.as_bytes()).into_orig_header_name()
234
- }
218
+ impl IntoHeaderCaseName for &'static str {
219
+ #[inline]
220
+ fn into_header_case_name(self) -> HeaderCaseName {
221
+ Bytes::from_static(self.as_bytes()).into_header_case_name()
235
222
  }
223
+ }
236
224
 
237
- impl IntoOrigHeaderName for String {
238
- #[inline]
239
- fn into_orig_header_name(self) -> OrigHeaderName {
240
- Bytes::from(self).into_orig_header_name()
241
- }
225
+ impl IntoHeaderCaseName for String {
226
+ #[inline]
227
+ fn into_header_case_name(self) -> HeaderCaseName {
228
+ Bytes::from(self).into_header_case_name()
242
229
  }
230
+ }
243
231
 
244
- impl IntoOrigHeaderName for Bytes {
245
- #[inline]
246
- fn into_orig_header_name(self) -> OrigHeaderName {
247
- OrigHeaderName {
248
- kind: Kind::Cased(self),
249
- }
232
+ impl IntoHeaderCaseName for Bytes {
233
+ #[inline]
234
+ fn into_header_case_name(self) -> HeaderCaseName {
235
+ HeaderCaseName {
236
+ inner: Repr::Cased(self),
250
237
  }
251
238
  }
239
+ }
252
240
 
253
- impl IntoOrigHeaderName for &HeaderName {
254
- #[inline]
255
- fn into_orig_header_name(self) -> OrigHeaderName {
256
- OrigHeaderName {
257
- kind: Kind::Standard(self.clone()),
258
- }
241
+ impl IntoHeaderCaseName for &HeaderName {
242
+ #[inline]
243
+ fn into_header_case_name(self) -> HeaderCaseName {
244
+ HeaderCaseName {
245
+ inner: Repr::Standard(self.clone()),
259
246
  }
260
247
  }
248
+ }
261
249
 
262
- impl IntoOrigHeaderName for HeaderName {
263
- #[inline]
264
- fn into_orig_header_name(self) -> OrigHeaderName {
265
- OrigHeaderName {
266
- kind: Kind::Standard(self),
267
- }
250
+ impl IntoHeaderCaseName for HeaderName {
251
+ #[inline]
252
+ fn into_header_case_name(self) -> HeaderCaseName {
253
+ HeaderCaseName {
254
+ inner: Repr::Standard(self),
268
255
  }
269
256
  }
257
+ }
270
258
 
271
- impl IntoOrigHeaderName for OrigHeaderName {
272
- #[inline]
273
- fn into_orig_header_name(self) -> OrigHeaderName {
274
- self
275
- }
259
+ impl IntoHeaderCaseName for HeaderCaseName {
260
+ #[inline]
261
+ fn into_header_case_name(self) -> HeaderCaseName {
262
+ self
276
263
  }
264
+ }
277
265
 
278
- impl IntoOrigHeaderName for &OrigHeaderName {
279
- #[inline]
280
- fn into_orig_header_name(self) -> OrigHeaderName {
281
- self.clone()
282
- }
266
+ impl IntoHeaderCaseName for &HeaderCaseName {
267
+ #[inline]
268
+ fn into_header_case_name(self) -> HeaderCaseName {
269
+ self.clone()
283
270
  }
284
271
  }
285
272
 
@@ -288,7 +275,7 @@ mod sealed {
288
275
  use bytes::Bytes;
289
276
  use http::HeaderName;
290
277
 
291
- use crate::header::OrigHeaderName;
278
+ use crate::header::HeaderCaseName;
292
279
 
293
280
  pub trait Sealed {}
294
281
 
@@ -297,13 +284,14 @@ mod sealed {
297
284
  impl Sealed for Bytes {}
298
285
  impl Sealed for &HeaderName {}
299
286
  impl Sealed for HeaderName {}
300
- impl Sealed for &OrigHeaderName {}
301
- impl Sealed for OrigHeaderName {}
287
+ impl Sealed for &HeaderCaseName {}
288
+ impl Sealed for HeaderCaseName {}
302
289
  }
303
290
 
304
291
  #[cfg(test)]
305
292
  mod test {
306
293
  use http::{HeaderMap, HeaderName, HeaderValue};
294
+ use wreq_proto::ext::OnPreserveHeaderCallback;
307
295
 
308
296
  use super::OrigHeaderMap;
309
297
 
@@ -415,7 +403,7 @@ mod test {
415
403
  .collect();
416
404
 
417
405
  // Sort headers according to orig_headers order
418
- orig_headers.sort_headers(&mut headers);
406
+ orig_headers.call(&mut headers);
419
407
 
420
408
  // Verify all cookie values are preserved
421
409
  let sorted_cookies: Vec<_> = headers
@@ -479,7 +467,7 @@ mod test {
479
467
 
480
468
  let total_before = headers.len();
481
469
 
482
- orig_headers.sort_headers(&mut headers);
470
+ orig_headers.call(&mut headers);
483
471
 
484
472
  // Verify all values preserved
485
473
  assert_eq!(
@@ -1,88 +1,30 @@
1
1
  #![deny(unused)]
2
2
  #![deny(unsafe_code)]
3
3
  #![deny(missing_docs)]
4
- #![cfg_attr(docsrs, feature(doc_cfg))]
5
4
  #![cfg_attr(test, deny(warnings))]
6
- #![cfg_attr(not(test), warn(unused_crate_dependencies))]
7
5
 
8
6
  //! # wreq
9
7
  //!
10
- //! An ergonomic all-in-one HTTP client for browser emulation with TLS, JA3/JA4, and HTTP/2
11
- //! fingerprints.
8
+ //! An ergonomic and modular Rust HTTP Client for high-fidelity protocol matching, featuring
9
+ //! customizable TLS, JA3/JA4, and HTTP/2 signature capabilities.
12
10
  //!
13
11
  //! - Plain bodies, [JSON](#json), [urlencoded](#forms), [multipart]
14
- //! - Cookies Store
12
+ //! - HTTP Trailer
13
+ //! - Cookie Store
15
14
  //! - [Redirect Policy](#redirect-policies)
16
15
  //! - Original Header
17
16
  //! - Rotating [Proxies](#proxies)
18
- //! - [Certificate Store](#certificate-store)
19
17
  //! - [Tower](https://docs.rs/tower/latest/tower) Middleware
20
18
  //! - [WebSocket](#websocket) Upgrade
21
19
  //! - HTTPS via [BoringSSL](#tls)
22
- //! - HTTP/2 over TLS [Emulation](#emulation)
20
+ //! - HTTP/2 over TLS Parity
21
+ //! - [Certificate Store (CAs & mTLS)](#certificate-store)
23
22
  //!
24
23
  //! Additional learning resources include:
25
24
  //!
26
25
  //! - [The Rust Cookbook](https://doc.rust-lang.org/stable/book/ch00-00-introduction.html)
27
26
  //! - [Repository Examples](https://github.com/0x676e67/wreq/tree/main/examples)
28
27
  //!
29
- //! ## Emulation
30
- //!
31
- //! The `emulation` module provides a way to simulate various browser TLS/HTTP2 fingerprints.
32
- //!
33
- //! ```rust,no_run
34
- //! use wreq_util::Emulation;
35
- //!
36
- //! #[tokio::main]
37
- //! async fn main() -> wreq::Result<()> {
38
- //! // Use the API you're already familiar with
39
- //! let resp = wreq::get("https://tls.peet.ws/api/all")
40
- //! .emulation(Emulation::Firefox136)
41
- //! .send().await?;
42
- //! println!("{}", resp.text().await?);
43
- //!
44
- //! Ok(())
45
- //! }
46
- //! ```
47
- //!
48
- //! ## Websocket
49
- //!
50
- //! The `websocket` module provides a way to upgrade a connection to a websocket.
51
- //!
52
- //! ```rust,no_run
53
- //! use futures_util::{SinkExt, StreamExt, TryStreamExt};
54
- //! use wreq::{header, ws::message::Message};
55
- //!
56
- //! #[tokio::main]
57
- //! async fn main() -> wreq::Result<()> {
58
- //! // Use the API you're already familiar with
59
- //! let websocket = wreq::websocket("wss://echo.websocket.org")
60
- //! .header(header::USER_AGENT, env!("CARGO_PKG_NAME"))
61
- //! .send()
62
- //! .await?;
63
- //!
64
- //! assert_eq!(websocket.version(), http::Version::HTTP_11);
65
- //!
66
- //! let (mut tx, mut rx) = websocket.into_websocket().await?.split();
67
- //!
68
- //! tokio::spawn(async move {
69
- //! for i in 1..11 {
70
- //! if let Err(err) = tx.send(Message::text(format!("Hello, World! {i}"))).await {
71
- //! eprintln!("failed to send message: {err}");
72
- //! }
73
- //! }
74
- //! });
75
- //!
76
- //! while let Some(message) = rx.try_next().await? {
77
- //! if let Message::Text(text) = message {
78
- //! println!("received: {text}");
79
- //! }
80
- //! }
81
- //!
82
- //! Ok(())
83
- //! }
84
- //! ```
85
- //!
86
28
  //! ## Making a GET request
87
29
  //!
88
30
  //! Making a GET request is simple.
@@ -179,6 +121,44 @@
179
121
  //! # }
180
122
  //! ```
181
123
  //!
124
+ //! ## Websocket
125
+ //!
126
+ //! The `websocket` module provides a way to upgrade a connection to a websocket.
127
+ //!
128
+ //! ```rust,no_run
129
+ //! use futures_util::{SinkExt, StreamExt, TryStreamExt};
130
+ //! use wreq::{header, ws::message::Message};
131
+ //!
132
+ //! #[tokio::main]
133
+ //! async fn main() -> wreq::Result<()> {
134
+ //! // Use the API you're already familiar with
135
+ //! let websocket = wreq::websocket("wss://echo.websocket.org")
136
+ //! .header(header::USER_AGENT, env!("CARGO_PKG_NAME"))
137
+ //! .send()
138
+ //! .await?;
139
+ //!
140
+ //! assert_eq!(websocket.version(), http::Version::HTTP_11);
141
+ //!
142
+ //! let (mut tx, mut rx) = websocket.into_websocket().await?.split();
143
+ //!
144
+ //! tokio::spawn(async move {
145
+ //! for i in 1..11 {
146
+ //! if let Err(err) = tx.send(Message::text(format!("Hello, World! {i}"))).await {
147
+ //! eprintln!("failed to send message: {err}");
148
+ //! }
149
+ //! }
150
+ //! });
151
+ //!
152
+ //! while let Some(message) = rx.try_next().await? {
153
+ //! if let Message::Text(text) = message {
154
+ //! println!("received: {text}");
155
+ //! }
156
+ //! }
157
+ //!
158
+ //! Ok(())
159
+ //! }
160
+ //! ```
161
+ //!
182
162
  //! ## Redirect Policies
183
163
  //!
184
164
  //! By default, the client does not handle HTTP redirects.
@@ -258,7 +238,7 @@
258
238
  //! - **webpki-roots** *(enabled by default)*: Use the webpki-roots crate for root certificates.
259
239
  //! - **system-proxy**: Enable system proxy support.
260
240
  //! - **tracing**: Enable tracing logging support.
261
- //! - **prefix-symbols**: Prefix BoringSSL symbols to avoid linker conflicts.
241
+ //! - **prefix-symbols**: Prefix BoringSSL symbols to avoid OpenSSL conflicts.
262
242
  //!
263
243
  //! [client]: ./struct.Client.html
264
244
  //! [response]: ./struct.Response.html
@@ -269,16 +249,66 @@
269
249
  //! [Proxy]: ./struct.Proxy.html
270
250
  //! [cargo-features]: https://doc.rust-lang.org/stable/cargo/reference/manifest.html#the-features-section
271
251
 
252
+ macro_rules! if_tokio_rt {
253
+ (block: { $($tt:tt)* }) => {
254
+ #[cfg(all(feature = "tokio-rt", not(feature = "compio-rt")))]
255
+ $($tt)*
256
+ };
257
+ ($($item:item)*) => {$(
258
+ #[cfg(all(feature = "tokio-rt", not(feature = "compio-rt")))]
259
+ $item
260
+ )*};
261
+ }
262
+
263
+ macro_rules! if_compio_rt {
264
+ (block: { $($tt:tt)* }) => {
265
+ #[cfg(all(feature = "compio-rt", not(feature = "tokio-rt")))]
266
+ $($tt)*
267
+ };
268
+ ($($item:item)*) => {$(
269
+ #[cfg(all(feature = "compio-rt", not(feature = "tokio-rt")))]
270
+ $item
271
+ )*};
272
+ }
273
+
274
+ macro_rules! if_all_rt {
275
+ (block: { $($tt:tt)* }) => {
276
+ #[cfg(all(feature = "tokio-rt", feature = "compio-rt"))]
277
+ $($tt)*
278
+ };
279
+ ($($item:item)*) => {$(
280
+ #[cfg(all(feature = "tokio-rt", feature = "compio-rt"))]
281
+ $item
282
+ )*};
283
+ }
284
+
285
+ macro_rules! if_any_rt {
286
+ ($($item:item)*) => {$(
287
+ #[cfg(any(feature = "tokio-rt", feature = "compio-rt"))]
288
+ $item
289
+ )*};
290
+ }
291
+
292
+ macro_rules! if_no_rt {
293
+ (block: { $($tt:tt)* }) => {
294
+ #[cfg(not(any(feature = "tokio-rt", feature = "compio-rt")))]
295
+ $($tt)*
296
+ };
297
+ }
298
+
272
299
  #[macro_use]
273
300
  mod trace;
274
301
  #[macro_use]
302
+ mod ext;
303
+ #[macro_use]
275
304
  mod config;
276
305
  mod client;
306
+ mod conn;
277
307
  mod error;
278
- mod ext;
279
- mod hash;
308
+ mod group;
280
309
  mod into_uri;
281
310
  mod proxy;
311
+ mod rt;
282
312
  mod sync;
283
313
  mod util;
284
314
 
@@ -290,25 +320,46 @@ pub mod redirect;
290
320
  pub mod retry;
291
321
  pub mod tls;
292
322
 
293
- pub use http::{Method, StatusCode, Uri, Version};
294
- #[cfg(unix)]
295
- use libc as _;
296
-
297
323
  #[cfg(feature = "multipart")]
298
324
  pub use self::client::multipart;
299
325
  #[cfg(feature = "ws")]
300
326
  pub use self::client::ws;
301
327
  pub use self::{
302
328
  client::{
303
- Body, Client, ClientBuilder, Emulation, EmulationBuilder, EmulationFactory, Request,
304
- RequestBuilder, Response, Upgraded, http1, http2,
329
+ Client, ClientBuilder,
330
+ body::Body,
331
+ emulate::{Emulation, EmulationBuilder, IntoEmulation},
332
+ request::{Request, RequestBuilder},
333
+ response::Response,
334
+ upgrade::Upgraded,
305
335
  },
306
336
  error::{Error, Result},
307
337
  ext::{ResponseBuilderExt, ResponseExt},
338
+ group::Group,
308
339
  into_uri::IntoUri,
309
340
  proxy::{NoProxy, Proxy},
310
341
  };
311
342
 
343
+ pub mod http1 {
344
+ //! HTTP/1 protocol implementation and utilities.
345
+
346
+ pub use wreq_proto::http1::{Http1Options, Http1OptionsBuilder};
347
+ }
348
+
349
+ pub mod http2 {
350
+ //! HTTP/2 protocol implementation and utilities.
351
+
352
+ pub use http2::frame::{
353
+ Priorities, PrioritiesBuilder, Priority, PseudoId, PseudoOrder, Setting, SettingId,
354
+ SettingsOrder, SettingsOrderBuilder, StreamDependency, StreamId,
355
+ };
356
+ pub use wreq_proto::http2::{Http2Options, Http2OptionsBuilder};
357
+ }
358
+
359
+ pub use http::{Method, StatusCode, Uri, Version};
360
+ #[cfg(unix)]
361
+ use libc as _;
362
+
312
363
  fn _assert_impls() {
313
364
  fn assert_send<T: Send>() {}
314
365
  fn assert_sync<T: Sync>() {}
@@ -511,32 +511,18 @@ mod tests {
511
511
  .custom_http_headers(headers.clone())
512
512
  .into_matcher();
513
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
- }
514
+ let proxy = intercept(&m, &uri);
515
+ let got_headers = proxy.custom_headers().unwrap();
516
+ assert_eq!(got_headers, &headers, "https forwards");
524
517
 
525
518
  let m = Proxy::all("http://yo.local")
526
519
  .unwrap()
527
520
  .custom_http_headers(headers.clone())
528
521
  .into_matcher();
529
522
 
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
- }
523
+ let proxy = intercept(&m, &uri);
524
+ let got_headers = proxy.custom_headers().unwrap();
525
+ assert_eq!(got_headers, &headers, "http forwards");
540
526
  }
541
527
 
542
528
  fn test_socks_proxy_default_port(uri: &str, url2: &str, port: u16) {
@@ -11,7 +11,7 @@ use futures_util::FutureExt;
11
11
  use http::{HeaderMap, HeaderName, HeaderValue, StatusCode, Uri};
12
12
 
13
13
  use crate::{
14
- client::{Body, layer::redirect},
14
+ client::{body::Body, layer::redirect},
15
15
  config::RequestConfig,
16
16
  error::{BoxError, Error},
17
17
  ext::UriExt,