wreq 1.2.5 → 1.2.7

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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/.cargo/config.toml +4 -0
  3. data/Cargo.lock +135 -119
  4. data/Cargo.toml +11 -3
  5. data/Rakefile +6 -0
  6. data/crates/wreq-util/README.md +1 -1
  7. data/crates/wreq-util/examples/emulate.rs +3 -3
  8. data/crates/wreq-util/src/emulate/macros.rs +13 -11
  9. data/crates/wreq-util/src/emulate/profile/chrome/header.rs +18 -3
  10. data/crates/wreq-util/src/emulate/profile/firefox/header.rs +16 -0
  11. data/crates/wreq-util/src/emulate/profile/opera/header.rs +6 -7
  12. data/crates/wreq-util/tests/client.rs +103 -1
  13. data/docs/windows-gnu-tokio-crash.md +49 -3
  14. data/extconf.rb +4 -0
  15. data/lib/wreq.rb +70 -45
  16. data/lib/wreq_ruby/body.rb +29 -11
  17. data/lib/wreq_ruby/client.rb +88 -55
  18. data/lib/wreq_ruby/cookie.rb +79 -19
  19. data/lib/wreq_ruby/emulate.rb +74 -6
  20. data/lib/wreq_ruby/error.rb +5 -7
  21. data/lib/wreq_ruby/http.rb +74 -0
  22. data/lib/wreq_ruby/response.rb +3 -0
  23. data/script/rust_env.rb +85 -0
  24. data/src/arch.rs +22 -0
  25. data/src/client/body/form.rs +2 -0
  26. data/src/client/body/json.rs +47 -14
  27. data/src/client/body/stream.rs +147 -43
  28. data/src/client/body.rs +11 -15
  29. data/src/client/param.rs +7 -7
  30. data/src/client/req.rs +87 -47
  31. data/src/client/resp.rs +23 -24
  32. data/src/client.rs +310 -230
  33. data/src/cookie.rs +280 -87
  34. data/src/emulate.rs +85 -50
  35. data/src/error.rs +198 -41
  36. data/src/extractor.rs +16 -76
  37. data/src/header.rs +146 -23
  38. data/src/http.rs +62 -33
  39. data/src/lib.rs +26 -20
  40. data/src/macros.rs +71 -46
  41. data/src/options.rs +284 -0
  42. data/src/rt.rs +22 -11
  43. data/src/serde/de/array_deserializer.rs +48 -0
  44. data/src/serde/de/array_enumerator.rs +59 -0
  45. data/src/serde/de/deserializer.rs +307 -0
  46. data/src/serde/de/enum_deserializer.rs +47 -0
  47. data/src/serde/de/hash_deserializer.rs +89 -0
  48. data/src/serde/de/number_deserializer.rs +51 -0
  49. data/src/serde/de/variant_deserializer.rs +101 -0
  50. data/src/serde/de.rs +33 -0
  51. data/src/serde/error.rs +146 -0
  52. data/src/serde/ser/enums.rs +14 -0
  53. data/src/serde/ser/map_serializer.rs +56 -0
  54. data/src/serde/ser/seq_serializer.rs +71 -0
  55. data/src/serde/ser/serializer.rs +194 -0
  56. data/src/serde/ser/struct_serializer.rs +106 -0
  57. data/src/serde/ser/struct_variant_serializer.rs +44 -0
  58. data/src/serde/ser/tuple_variant_serializer.rs +41 -0
  59. data/src/serde/ser.rs +18 -0
  60. data/src/serde/tests.rs +237 -0
  61. data/src/serde.rs +202 -0
  62. data/test/body_sender_test.rb +246 -0
  63. data/test/cookie_test.rb +211 -10
  64. data/test/json_precision_test.rb +209 -0
  65. data/test/option_validation_test.rb +311 -0
  66. data/test/value_semantics_test.rb +238 -0
  67. data/wreq.gemspec +1 -1
  68. metadata +28 -4
  69. data/script/build_windows_gnu.ps1 +0 -264
  70. data/src/header/helper.rs +0 -112
data/Cargo.toml CHANGED
@@ -5,8 +5,8 @@ authors = ["SearchApi <support@searchapi.io>"]
5
5
  homepage = "https://github.com/SearchApi/wreq-ruby"
6
6
  repository = "https://github.com/SearchApi/wreq-ruby"
7
7
  edition = "2024"
8
- rust-version = "1.85"
9
- version = "1.2.5"
8
+ version = "1.2.7"
9
+ rust-version = "1.95"
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
 
data/Rakefile CHANGED
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "script/rust_env"
4
+
5
+ # Cargo needs RubyInstaller's UCRT tools when Rake builds the native extension
6
+ # on Windows. Other platforms keep their existing native Cargo environment.
7
+ Wreq::RustEnv.activate
8
+
3
9
  require "bundler/gem_tasks"
4
10
  require "rake/testtask"
5
11
  require "rb_sys/extensiontask"
@@ -43,7 +43,7 @@ async fn main() -> wreq::Result<()> {
43
43
  .build()?;
44
44
 
45
45
  // Use the API you're already familiar with
46
- let resp = client.get("https://www.google.com").send().await?;
46
+ let resp = client.get("https://pingly.us.kg/api/all").send().await?;
47
47
  println!("{}", resp.text().await?);
48
48
  Ok(())
49
49
  }
@@ -3,7 +3,7 @@ use wreq_util::{Emulation, Platform, Profile};
3
3
  #[tokio::main]
4
4
  async fn main() -> Result<(), wreq::Error> {
5
5
  // Example 1: Basic emulation - Safari26
6
- let text = wreq::get("https://tls.browserleaks.com/")
6
+ let text = wreq::get("https://pingly.us.kg/api/all")
7
7
  .emulation(Emulation::Safari26)
8
8
  .send()
9
9
  .await?
@@ -12,7 +12,7 @@ async fn main() -> Result<(), wreq::Error> {
12
12
  println!("{}\n", text);
13
13
 
14
14
  // Example 2: Advanced emulation with options - OkHttp5
15
- let text = wreq::get("https://tls.peet.ws/api/all")
15
+ let text = wreq::get("https://pingly.us.kg/api/all")
16
16
  .emulation(
17
17
  Emulation::builder()
18
18
  .profile(Profile::OkHttp5)
@@ -27,7 +27,7 @@ async fn main() -> Result<(), wreq::Error> {
27
27
  println!("{}\n", text);
28
28
 
29
29
  // Example 3: Random device emulation
30
- let text = wreq::get("https://tls.peet.ws/api/all")
30
+ let text = wreq::get("https://pingly.us.kg/api/all")
31
31
  .emulation(Emulation::random())
32
32
  .send()
33
33
  .await?
@@ -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
 
@@ -109,7 +110,12 @@ macro_rules! header_chrome_ua {
109
110
 
110
111
  macro_rules! header_chrome_accept {
111
112
  ($headers:expr) => {
112
- $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"));
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.7"));
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
+ }
@@ -57,14 +57,60 @@ DLL Name: KERNEL32.dll
57
57
  problematic `Sleep` reference can come from Rust std, MinGW, or pthread-related
58
58
  linking paths, not only from `windows-sys`.
59
59
 
60
- Verified with:
60
+ Windows builds use the `x86_64-pc-windows-gnu` target and the RubyInstaller
61
+ UCRT toolchain. The Rakefile configures that environment automatically, so the
62
+ extension and tests can be built with:
61
63
 
62
64
  ```powershell
63
- .\script\build_windows_gnu.ps1 -SkipBundleInstall -SkipToolInstall -RunTests
65
+ rustup target add x86_64-pc-windows-gnu
66
+ ridk exec pacman -S --needed --noconfirm `
67
+ mingw-w64-ucrt-x86_64-gcc `
68
+ mingw-w64-ucrt-x86_64-clang `
69
+ mingw-w64-ucrt-x86_64-cmake `
70
+ mingw-w64-ucrt-x86_64-pkgconf
71
+ bundle exec rake test
64
72
  ```
65
73
 
74
+ The first Rake invocation also writes a machine-local `.cargo/windows.toml`.
75
+ The checked-in `.cargo/config.toml` loads it automatically, so Cargo and Rust
76
+ language servers use the same GNU target and RubyInstaller tools without
77
+ editor-specific settings.
78
+
79
+ ## RubyInstaller development tools
80
+
81
+ RubyInstaller adds Ruby itself to `PATH`, but it does not enable the bundled
82
+ MSYS2 development environment globally. Running `ridk enable` adds tools such
83
+ as GCC, CMake, and Make to the current terminal only. This is normally useful
84
+ because it avoids conflicts with other Windows toolchains.
85
+
86
+ Rust language servers start Cargo directly and do not run `ridk enable` or the
87
+ Rakefile first. Add RubyInstaller's `ucrt64\bin` and `usr\bin` directories to
88
+ the user `PATH` so Cargo can load GCC, libclang, and their dependent DLLs from
89
+ any editor:
90
+
91
+ ```powershell
92
+ $rubyRoot = ruby -rrbconfig -e "print RbConfig::CONFIG.fetch('prefix')"
93
+ $required = @(
94
+ (Join-Path $rubyRoot "msys64\ucrt64\bin"),
95
+ (Join-Path $rubyRoot "msys64\usr\bin")
96
+ )
97
+ $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
98
+ $entries = @($userPath -split ";" | Where-Object {
99
+ $_ -and $_ -notin $required
100
+ })
101
+ $entries = $required + $entries
102
+ [Environment]::SetEnvironmentVariable("Path", ($entries -join ";"), "User")
103
+ ```
104
+
105
+ Restart the editor after changing `PATH` so its language server inherits the
106
+ updated environment. Run `bundle exec rake compile` once after installing or
107
+ switching Ruby so `.cargo/windows.toml` points to the active RubyInstaller.
108
+ Run a Rake command after switching the same checkout between Windows and WSL;
109
+ Windows generates this local configuration, while other platforms remove it.
110
+
66
111
  Result:
67
112
 
68
113
  ```text
69
- 160 runs, 775 assertions, 0 failures, 0 errors
114
+ 254 runs, 1198 assertions, 0 failures, 0 errors
115
+ 2 Rust tests passed
70
116
  ```
data/extconf.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  require "mkmf"
2
+ require_relative "script/rust_env"
3
+
4
+ Wreq::RustEnv.activate
5
+
2
6
  # We use rb_sys for makefile generation only.
3
7
  # We can use `RB_SYS_CARGO_PROFILE` to choose Cargo profile
4
8
  # Read more https://github.com/oxidize-rb/rb-sys/blob/main/gem/README.md