wreq 1.2.5 → 1.2.6

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 +20 -13
  3. data/Cargo.toml +10 -2
  4. data/crates/wreq-util/src/emulate/macros.rs +12 -10
  5. data/crates/wreq-util/src/emulate/profile/chrome/header.rs +18 -3
  6. data/crates/wreq-util/src/emulate/profile/firefox/header.rs +16 -0
  7. data/crates/wreq-util/src/emulate/profile/opera/header.rs +6 -7
  8. data/crates/wreq-util/tests/client.rs +103 -1
  9. data/lib/wreq.rb +70 -45
  10. data/lib/wreq_ruby/body.rb +29 -11
  11. data/lib/wreq_ruby/client.rb +88 -55
  12. data/lib/wreq_ruby/cookie.rb +79 -19
  13. data/lib/wreq_ruby/emulate.rb +74 -6
  14. data/lib/wreq_ruby/error.rb +5 -7
  15. data/lib/wreq_ruby/http.rb +74 -0
  16. data/lib/wreq_ruby/response.rb +3 -0
  17. data/script/build_windows_gnu.ps1 +6 -0
  18. data/src/arch.rs +22 -0
  19. data/src/client/body/form.rs +2 -0
  20. data/src/client/body/json.rs +47 -14
  21. data/src/client/body/stream.rs +147 -43
  22. data/src/client/body.rs +11 -15
  23. data/src/client/param.rs +7 -7
  24. data/src/client/req.rs +87 -47
  25. data/src/client/resp.rs +23 -24
  26. data/src/client.rs +310 -230
  27. data/src/cookie.rs +280 -87
  28. data/src/emulate.rs +85 -50
  29. data/src/error.rs +198 -41
  30. data/src/extractor.rs +16 -76
  31. data/src/header.rs +146 -23
  32. data/src/http.rs +62 -33
  33. data/src/lib.rs +26 -20
  34. data/src/macros.rs +71 -46
  35. data/src/options.rs +284 -0
  36. data/src/rt.rs +22 -11
  37. data/src/serde/de/array_deserializer.rs +48 -0
  38. data/src/serde/de/array_enumerator.rs +59 -0
  39. data/src/serde/de/deserializer.rs +307 -0
  40. data/src/serde/de/enum_deserializer.rs +47 -0
  41. data/src/serde/de/hash_deserializer.rs +89 -0
  42. data/src/serde/de/number_deserializer.rs +51 -0
  43. data/src/serde/de/variant_deserializer.rs +101 -0
  44. data/src/serde/de.rs +33 -0
  45. data/src/serde/error.rs +146 -0
  46. data/src/serde/ser/enums.rs +14 -0
  47. data/src/serde/ser/map_serializer.rs +56 -0
  48. data/src/serde/ser/seq_serializer.rs +71 -0
  49. data/src/serde/ser/serializer.rs +194 -0
  50. data/src/serde/ser/struct_serializer.rs +106 -0
  51. data/src/serde/ser/struct_variant_serializer.rs +44 -0
  52. data/src/serde/ser/tuple_variant_serializer.rs +41 -0
  53. data/src/serde/ser.rs +18 -0
  54. data/src/serde/tests.rs +237 -0
  55. data/src/serde.rs +202 -0
  56. data/test/body_sender_test.rb +246 -0
  57. data/test/cookie_test.rb +211 -10
  58. data/test/json_precision_test.rb +209 -0
  59. data/test/option_validation_test.rb +311 -0
  60. data/test/value_semantics_test.rb +238 -0
  61. metadata +25 -2
  62. data/src/header/helper.rs +0 -112
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32fccd5de0a2dc902b5ff76a4354b5271f30151718388715d9563c72d702fce3
4
- data.tar.gz: 6623c40db0fbe229026c4214b0c183e700b595329583d96b19aa3858d6a07943
3
+ metadata.gz: 87d989f8582c97e03c95ef1fd90d1f089eb35c787da5d9527942548483c1dd55
4
+ data.tar.gz: 413a4656384561df504e9b6a175c2f82c3373693df41bb88cc2ba78c2d319cb4
5
5
  SHA512:
6
- metadata.gz: b17c6b0586311dc5144cba1ac348a7ac6754028ad51d9727b451f213fa77ab341a7ece9969ba62bd4eb6762de2a8940c12e4c0210e64016b39be72cf2bb63ada
7
- data.tar.gz: bff84ec0a74f02523966d3f28d4772db404e142a7f9b4b16f3e74e62f322120d18750431c5dbc81db5489da75e7145219c39d13d7b6534955fc250b0c9b3b78e
6
+ metadata.gz: 2c0b23be854a1bdf4421ec7e32118a41e3c209bded0a32cde470614bf487fdaf48082ad432913a597ef176d14b12eeabcf976ccbddf49d99446ed3f08b5e3710
7
+ data.tar.gz: 53190348795c05829f6119753c6402a6c64a662a72c37ab88616275bbfce47292577348c8f53665d7abf8004d626ded649ff7b7d31d31f99fbc87e7caddef8e7
data/Cargo.lock CHANGED
@@ -999,12 +999,23 @@ dependencies = [
999
999
  "zmij",
1000
1000
  ]
1001
1001
 
1002
+ [[package]]
1003
+ name = "serde_ignored"
1004
+ version = "0.1.14"
1005
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1006
+ checksum = "115dffd5f3853e06e746965a20dcbae6ee747ae30b543d91b0e089668bb07798"
1007
+ dependencies = [
1008
+ "serde",
1009
+ "serde_core",
1010
+ ]
1011
+
1002
1012
  [[package]]
1003
1013
  name = "serde_json"
1004
1014
  version = "1.0.150"
1005
1015
  source = "registry+https://github.com/rust-lang/crates.io-index"
1006
1016
  checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
1007
1017
  dependencies = [
1018
+ "indexmap",
1008
1019
  "itoa",
1009
1020
  "memchr",
1010
1021
  "serde",
@@ -1013,14 +1024,14 @@ dependencies = [
1013
1024
  ]
1014
1025
 
1015
1026
  [[package]]
1016
- name = "serde_magnus"
1017
- version = "0.11.0"
1027
+ name = "serde_path_to_error"
1028
+ version = "0.1.20"
1018
1029
  source = "registry+https://github.com/rust-lang/crates.io-index"
1019
- checksum = "8ff64c88ddd26acdcad5a501f18bcc339927b77b69f4a03bfaf2a6fc5ba2ac4b"
1030
+ checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
1020
1031
  dependencies = [
1021
- "magnus",
1032
+ "itoa",
1022
1033
  "serde",
1023
- "tap",
1034
+ "serde_core",
1024
1035
  ]
1025
1036
 
1026
1037
  [[package]]
@@ -1137,12 +1148,6 @@ dependencies = [
1137
1148
  "libc",
1138
1149
  ]
1139
1150
 
1140
- [[package]]
1141
- name = "tap"
1142
- version = "1.0.1"
1143
- source = "registry+https://github.com/rust-lang/crates.io-index"
1144
- checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
1145
-
1146
1151
  [[package]]
1147
1152
  name = "thiserror"
1148
1153
  version = "1.0.69"
@@ -1535,7 +1540,7 @@ dependencies = [
1535
1540
 
1536
1541
  [[package]]
1537
1542
  name = "wreq-ruby"
1538
- version = "1.2.5"
1543
+ version = "1.2.6"
1539
1544
  dependencies = [
1540
1545
  "arc-swap",
1541
1546
  "bytes",
@@ -1548,7 +1553,9 @@ dependencies = [
1548
1553
  "rb-sys",
1549
1554
  "rb-sys-env",
1550
1555
  "serde",
1551
- "serde_magnus",
1556
+ "serde_ignored",
1557
+ "serde_json",
1558
+ "serde_path_to_error",
1552
1559
  "tokio",
1553
1560
  "wreq",
1554
1561
  "wreq-util",
data/Cargo.toml CHANGED
@@ -6,7 +6,7 @@ homepage = "https://github.com/SearchApi/wreq-ruby"
6
6
  repository = "https://github.com/SearchApi/wreq-ruby"
7
7
  edition = "2024"
8
8
  rust-version = "1.85"
9
- version = "1.2.5"
9
+ version = "1.2.6"
10
10
 
11
11
  [lib]
12
12
  crate-type = ["cdylib"]
@@ -33,7 +33,12 @@ wreq = { version = "6.0.0-rc", features = [
33
33
  ] }
34
34
  wreq-util = { version = "3.0.0-rc", features = ["emulation-compression"] }
35
35
  serde = { version = "1.0.228", features = ["derive"] }
36
- serde_magnus = "0.11.0"
36
+ serde_ignored = "0.1.14"
37
+ serde_json = { version = "1.0.150", features = [
38
+ "arbitrary_precision",
39
+ "preserve_order",
40
+ ] }
41
+ serde_path_to_error = "0.1.20"
37
42
  indexmap = { version = "2.14.0", features = ["serde"] }
38
43
  cookie = "0.18.1"
39
44
  bytes = "1.12.1"
@@ -42,6 +47,9 @@ http = "1.4.1"
42
47
  http-body-util = "0.1.3"
43
48
  futures-util = { version = "0.3.32", default-features = false }
44
49
 
50
+ [dev-dependencies]
51
+ magnus = { version = "0.8.2", features = ["embed"] }
52
+
45
53
  [build-dependencies]
46
54
  rb-sys-env = "0.2.2"
47
55
 
@@ -95,9 +95,10 @@ macro_rules! header_chrome_sec_ch_ua {
95
95
 
96
96
  macro_rules! header_chrome_sec_fetch {
97
97
  ($headers:expr) => {
98
- $headers.insert("sec-fetch-dest", HeaderValue::from_static("document"));
99
- $headers.insert("sec-fetch-mode", HeaderValue::from_static("navigate"));
100
98
  $headers.insert("sec-fetch-site", HeaderValue::from_static("none"));
99
+ $headers.insert("sec-fetch-mode", HeaderValue::from_static("navigate"));
100
+ $headers.insert("sec-fetch-user", HeaderValue::from_static("?1"));
101
+ $headers.insert("sec-fetch-dest", HeaderValue::from_static("document"));
101
102
  };
102
103
  }
103
104
 
@@ -110,6 +111,11 @@ macro_rules! header_chrome_ua {
110
111
  macro_rules! header_chrome_accept {
111
112
  ($headers:expr) => {
112
113
  $headers.insert(ACCEPT, HeaderValue::from_static("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"));
114
+ };
115
+ }
116
+
117
+ macro_rules! header_chrome_accept_encoding {
118
+ ($headers:expr) => {
113
119
  #[cfg(feature = "emulation-compression")]
114
120
  $headers.insert(
115
121
  ACCEPT_ENCODING,
@@ -118,14 +124,13 @@ macro_rules! header_chrome_accept {
118
124
  $headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.9"));
119
125
  };
120
126
  (zstd, $headers:expr) => {
121
- $headers.insert(ACCEPT, HeaderValue::from_static("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"));
122
127
  #[cfg(feature = "emulation-compression")]
123
128
  $headers.insert(
124
129
  ACCEPT_ENCODING,
125
130
  HeaderValue::from_static("gzip, deflate, br, zstd"),
126
131
  );
127
132
  $headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.9"));
128
- }
133
+ };
129
134
  }
130
135
 
131
136
  macro_rules! header_firefox_sec_fetch {
@@ -133,6 +138,7 @@ macro_rules! header_firefox_sec_fetch {
133
138
  $headers.insert("sec-fetch-dest", HeaderValue::from_static("document"));
134
139
  $headers.insert("sec-fetch-mode", HeaderValue::from_static("navigate"));
135
140
  $headers.insert("sec-fetch-site", HeaderValue::from_static("none"));
141
+ $headers.insert("sec-fetch-user", HeaderValue::from_static("?1"));
136
142
  };
137
143
  }
138
144
 
@@ -144,12 +150,12 @@ macro_rules! header_firefox_accept {
144
150
  "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
145
151
  ),
146
152
  );
153
+ $headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.5"));
147
154
  #[cfg(feature = "emulation-compression")]
148
155
  $headers.insert(
149
156
  ACCEPT_ENCODING,
150
157
  HeaderValue::from_static("gzip, deflate, br"),
151
158
  );
152
- $headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.5"));
153
159
  };
154
160
  (zstd, $headers:expr) => {
155
161
  $headers.insert(
@@ -158,21 +164,17 @@ macro_rules! header_firefox_accept {
158
164
  "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
159
165
  ),
160
166
  );
167
+ $headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.5"));
161
168
  #[cfg(feature = "emulation-compression")]
162
169
  $headers.insert(
163
170
  ACCEPT_ENCODING,
164
171
  HeaderValue::from_static("gzip, deflate, br, zstd"),
165
172
  );
166
- $headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.5"));
167
173
  };
168
174
  }
169
175
 
170
176
  macro_rules! header_firefox_ua {
171
177
  ($headers:expr, $ua:expr) => {
172
- $headers.insert(
173
- HeaderName::from_static("te"),
174
- HeaderValue::from_static("trailers"),
175
- );
176
178
  $headers.insert(USER_AGENT, HeaderValue::from_static($ua));
177
179
  };
178
180
  }
@@ -12,9 +12,14 @@ pub fn header_initializer(
12
12
  emulation_os.platform(),
13
13
  emulation_os.is_mobile()
14
14
  );
15
+ headers.insert(
16
+ HeaderName::from_static("upgrade-insecure-requests"),
17
+ HeaderValue::from_static("1"),
18
+ );
15
19
  header_chrome_ua!(headers, ua);
16
- header_chrome_sec_fetch!(headers);
17
20
  header_chrome_accept!(headers);
21
+ header_chrome_sec_fetch!(headers);
22
+ header_chrome_accept_encoding!(headers);
18
23
  headers
19
24
  }
20
25
 
@@ -30,9 +35,14 @@ pub fn header_initializer_with_zstd(
30
35
  emulation_os.platform(),
31
36
  emulation_os.is_mobile()
32
37
  );
38
+ headers.insert(
39
+ HeaderName::from_static("upgrade-insecure-requests"),
40
+ HeaderValue::from_static("1"),
41
+ );
33
42
  header_chrome_ua!(headers, ua);
43
+ header_chrome_accept!(headers);
34
44
  header_chrome_sec_fetch!(headers);
35
- header_chrome_accept!(zstd, headers);
45
+ header_chrome_accept_encoding!(zstd, headers);
36
46
  headers
37
47
  }
38
48
 
@@ -48,9 +58,14 @@ pub fn header_initializer_with_zstd_priority(
48
58
  emulation_os.platform(),
49
59
  emulation_os.is_mobile()
50
60
  );
61
+ headers.insert(
62
+ HeaderName::from_static("upgrade-insecure-requests"),
63
+ HeaderValue::from_static("1"),
64
+ );
51
65
  header_chrome_ua!(headers, ua);
66
+ header_chrome_accept!(headers);
52
67
  header_chrome_sec_fetch!(headers);
53
- header_chrome_accept!(zstd, headers);
68
+ header_chrome_accept_encoding!(zstd, headers);
54
69
  headers.insert(
55
70
  HeaderName::from_static("priority"),
56
71
  HeaderValue::from_static("u=0, i"),
@@ -4,7 +4,15 @@ pub fn header_initializer(ua: &'static str) -> HeaderMap {
4
4
  let mut headers = HeaderMap::new();
5
5
  header_firefox_ua!(headers, ua);
6
6
  header_firefox_accept!(headers);
7
+ headers.insert(
8
+ HeaderName::from_static("upgrade-insecure-requests"),
9
+ HeaderValue::from_static("1"),
10
+ );
7
11
  header_firefox_sec_fetch!(headers);
12
+ headers.insert(
13
+ HeaderName::from_static("te"),
14
+ HeaderValue::from_static("trailers"),
15
+ );
8
16
  headers
9
17
  }
10
18
 
@@ -12,10 +20,18 @@ pub fn header_initializer_with_zstd(ua: &'static str) -> HeaderMap {
12
20
  let mut headers = HeaderMap::new();
13
21
  header_firefox_ua!(headers, ua);
14
22
  header_firefox_accept!(zstd, headers);
23
+ headers.insert(
24
+ HeaderName::from_static("upgrade-insecure-requests"),
25
+ HeaderValue::from_static("1"),
26
+ );
15
27
  header_firefox_sec_fetch!(headers);
16
28
  headers.insert(
17
29
  HeaderName::from_static("priority"),
18
30
  HeaderValue::from_static("u=0, i"),
19
31
  );
32
+ headers.insert(
33
+ HeaderName::from_static("te"),
34
+ HeaderValue::from_static("trailers"),
35
+ );
20
36
  headers
21
37
  }
@@ -13,15 +13,14 @@ pub fn header_initializer_with_zstd_priority(
13
13
  emulation_os.platform(),
14
14
  emulation_os.is_mobile()
15
15
  );
16
- header_chrome_ua!(headers, ua);
17
-
18
- headers.insert(ACCEPT, HeaderValue::from_static("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"));
19
- #[cfg(feature = "emulation-compression")]
20
16
  headers.insert(
21
- ACCEPT_ENCODING,
22
- HeaderValue::from_static("gzip, deflate, br, zstd"),
17
+ HeaderName::from_static("upgrade-insecure-requests"),
18
+ HeaderValue::from_static("1"),
23
19
  );
24
- headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.9"));
20
+ header_chrome_ua!(headers, ua);
21
+ header_chrome_accept!(headers);
22
+ header_chrome_sec_fetch!(headers);
23
+ header_chrome_accept_encoding!(zstd, headers);
25
24
  headers.insert(
26
25
  HeaderName::from_static("priority"),
27
26
  HeaderValue::from_static("u=0, i"),
@@ -1,9 +1,96 @@
1
1
  #![cfg(not(target_arch = "wasm32"))]
2
2
  mod support;
3
3
 
4
+ use std::future::Future;
5
+
4
6
  use support::server;
7
+ use tokio::{io::AsyncWriteExt, net::TcpStream};
5
8
  use wreq::Client;
6
- use wreq_util::{Emulation, Platform};
9
+ use wreq_util::{Emulation, Platform, Profile};
10
+
11
+ const CHROMIUM_HEADER_ORDER: &[&str] = &[
12
+ "sec-ch-ua",
13
+ "sec-ch-ua-mobile",
14
+ "sec-ch-ua-platform",
15
+ "upgrade-insecure-requests",
16
+ "user-agent",
17
+ "accept",
18
+ "sec-fetch-site",
19
+ "sec-fetch-mode",
20
+ "sec-fetch-user",
21
+ "sec-fetch-dest",
22
+ #[cfg(feature = "emulation-compression")]
23
+ "accept-encoding",
24
+ "accept-language",
25
+ "priority",
26
+ ];
27
+
28
+ const FIREFOX_HEADER_ORDER: &[&str] = &[
29
+ "user-agent",
30
+ "accept",
31
+ "accept-language",
32
+ #[cfg(feature = "emulation-compression")]
33
+ "accept-encoding",
34
+ "upgrade-insecure-requests",
35
+ "sec-fetch-dest",
36
+ "sec-fetch-mode",
37
+ "sec-fetch-site",
38
+ "sec-fetch-user",
39
+ "te",
40
+ ];
41
+
42
+ fn check_header_order<'a>(
43
+ request: &'a [u8],
44
+ stream: &'a mut TcpStream,
45
+ expected: &'static [&'static str],
46
+ ) -> Box<dyn Future<Output = ()> + Send + 'a> {
47
+ Box::new(async move {
48
+ let request = std::str::from_utf8(request)
49
+ .expect("request should be valid UTF-8")
50
+ .to_ascii_lowercase();
51
+ let mut previous = None;
52
+
53
+ for name in expected {
54
+ let marker = format!("\r\n{name}:");
55
+ let position = request
56
+ .find(&marker)
57
+ .unwrap_or_else(|| panic!("missing `{name}` header:\n{request}"));
58
+
59
+ if let Some(previous) = previous {
60
+ assert!(
61
+ position > previous,
62
+ "`{name}` header is out of order:\n{request}"
63
+ );
64
+ }
65
+
66
+ previous = Some(position);
67
+ }
68
+
69
+ assert!(request.contains("\r\nupgrade-insecure-requests: 1\r\n"));
70
+ assert!(request.contains("\r\nsec-fetch-user: ?1\r\n"));
71
+
72
+ stream
73
+ .write_all(b"HTTP/1.1 200 OK\r\ncontent-length: 0\r\nconnection: close\r\n\r\n")
74
+ .await
75
+ .expect("response");
76
+ })
77
+ }
78
+
79
+ async fn assert_emulation_headers(profile: Profile, expected: &'static [&'static str]) {
80
+ let server = server::low_level_with_response(move |request, stream| {
81
+ check_header_order(request, stream, expected)
82
+ });
83
+ let response = Client::builder()
84
+ .emulation(profile)
85
+ .build()
86
+ .expect("client")
87
+ .get(format!("http://{}/headers", server.addr()))
88
+ .send()
89
+ .await
90
+ .expect("request");
91
+
92
+ assert_eq!(response.status(), wreq::StatusCode::OK);
93
+ }
7
94
 
8
95
  #[tokio::test]
9
96
  async fn test_client_emulation_device() {
@@ -49,3 +136,18 @@ async fn test_client_emulation_device() {
49
136
 
50
137
  assert_eq!(res.status(), wreq::StatusCode::OK);
51
138
  }
139
+
140
+ #[tokio::test]
141
+ async fn test_chrome_default_header_order() {
142
+ assert_emulation_headers(Emulation::Chrome133, CHROMIUM_HEADER_ORDER).await;
143
+ }
144
+
145
+ #[tokio::test]
146
+ async fn test_firefox_default_header_order() {
147
+ assert_emulation_headers(Emulation::Firefox109, FIREFOX_HEADER_ORDER).await;
148
+ }
149
+
150
+ #[tokio::test]
151
+ async fn test_opera_default_header_order() {
152
+ assert_emulation_headers(Emulation::Opera116, CHROMIUM_HEADER_ORDER).await;
153
+ }