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.
- checksums.yaml +4 -4
- data/.cargo/config.toml +4 -0
- data/Cargo.lock +135 -119
- data/Cargo.toml +11 -3
- data/Rakefile +6 -0
- data/crates/wreq-util/README.md +1 -1
- data/crates/wreq-util/examples/emulate.rs +3 -3
- data/crates/wreq-util/src/emulate/macros.rs +13 -11
- data/crates/wreq-util/src/emulate/profile/chrome/header.rs +18 -3
- data/crates/wreq-util/src/emulate/profile/firefox/header.rs +16 -0
- data/crates/wreq-util/src/emulate/profile/opera/header.rs +6 -7
- data/crates/wreq-util/tests/client.rs +103 -1
- data/docs/windows-gnu-tokio-crash.md +49 -3
- data/extconf.rb +4 -0
- data/lib/wreq.rb +70 -45
- data/lib/wreq_ruby/body.rb +29 -11
- data/lib/wreq_ruby/client.rb +88 -55
- data/lib/wreq_ruby/cookie.rb +79 -19
- data/lib/wreq_ruby/emulate.rb +74 -6
- data/lib/wreq_ruby/error.rb +5 -7
- data/lib/wreq_ruby/http.rb +74 -0
- data/lib/wreq_ruby/response.rb +3 -0
- data/script/rust_env.rb +85 -0
- data/src/arch.rs +22 -0
- data/src/client/body/form.rs +2 -0
- data/src/client/body/json.rs +47 -14
- data/src/client/body/stream.rs +147 -43
- data/src/client/body.rs +11 -15
- data/src/client/param.rs +7 -7
- data/src/client/req.rs +87 -47
- data/src/client/resp.rs +23 -24
- data/src/client.rs +310 -230
- data/src/cookie.rs +280 -87
- data/src/emulate.rs +85 -50
- data/src/error.rs +198 -41
- data/src/extractor.rs +16 -76
- data/src/header.rs +146 -23
- data/src/http.rs +62 -33
- data/src/lib.rs +26 -20
- data/src/macros.rs +71 -46
- data/src/options.rs +284 -0
- data/src/rt.rs +22 -11
- data/src/serde/de/array_deserializer.rs +48 -0
- data/src/serde/de/array_enumerator.rs +59 -0
- data/src/serde/de/deserializer.rs +307 -0
- data/src/serde/de/enum_deserializer.rs +47 -0
- data/src/serde/de/hash_deserializer.rs +89 -0
- data/src/serde/de/number_deserializer.rs +51 -0
- data/src/serde/de/variant_deserializer.rs +101 -0
- data/src/serde/de.rs +33 -0
- data/src/serde/error.rs +146 -0
- data/src/serde/ser/enums.rs +14 -0
- data/src/serde/ser/map_serializer.rs +56 -0
- data/src/serde/ser/seq_serializer.rs +71 -0
- data/src/serde/ser/serializer.rs +194 -0
- data/src/serde/ser/struct_serializer.rs +106 -0
- data/src/serde/ser/struct_variant_serializer.rs +44 -0
- data/src/serde/ser/tuple_variant_serializer.rs +41 -0
- data/src/serde/ser.rs +18 -0
- data/src/serde/tests.rs +237 -0
- data/src/serde.rs +202 -0
- data/test/body_sender_test.rb +246 -0
- data/test/cookie_test.rb +211 -10
- data/test/json_precision_test.rb +209 -0
- data/test/option_validation_test.rb +311 -0
- data/test/value_semantics_test.rb +238 -0
- data/wreq.gemspec +1 -1
- metadata +28 -4
- data/script/build_windows_gnu.ps1 +0 -264
- 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
|
-
|
|
9
|
-
version = "1.
|
|
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
|
-
|
|
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"
|
data/crates/wreq-util/README.md
CHANGED
|
@@ -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://
|
|
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://
|
|
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://
|
|
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://
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
22
|
-
HeaderValue::from_static("
|
|
17
|
+
HeaderName::from_static("upgrade-insecure-requests"),
|
|
18
|
+
HeaderValue::from_static("1"),
|
|
23
19
|
);
|
|
24
|
-
headers
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
114
|
+
254 runs, 1198 assertions, 0 failures, 0 errors
|
|
115
|
+
2 Rust tests passed
|
|
70
116
|
```
|
data/extconf.rb
CHANGED