Skip to content

Commit e0b76a8

Browse files
authored
test(emulation): Add tests for additional emulation options (#823)
1 parent 6ed1974 commit e0b76a8

1 file changed

Lines changed: 125 additions & 46 deletions

File tree

tests/emulation.rs

Lines changed: 125 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::time::Duration;
2+
13
use wreq::{
24
Client, Emulation,
35
http1::Http1Options,
@@ -13,10 +15,9 @@ macro_rules! join {
1315
};
1416
}
1517

16-
#[tokio::test]
17-
async fn test_emulation_firefox() -> wreq::Result<()> {
18+
fn tls_options_template() -> TlsOptions {
1819
// TLS options config
19-
let tls = TlsOptions::builder()
20+
TlsOptions::builder()
2021
.curves_list(join!(
2122
":",
2223
"X25519MLKEM768",
@@ -103,62 +104,67 @@ async fn test_emulation_firefox() -> wreq::Result<()> {
103104
ExtensionType::CERT_COMPRESSION,
104105
ExtensionType::ENCRYPTED_CLIENT_HELLO,
105106
])
107+
.build()
108+
}
109+
110+
fn http2_options_template() -> Http2Options {
111+
// HTTP/2 headers frame pseudo-header order
112+
let headers_pseudo_order = PseudoOrder::builder()
113+
.extend([
114+
PseudoId::Method,
115+
PseudoId::Path,
116+
PseudoId::Authority,
117+
PseudoId::Scheme,
118+
])
106119
.build();
107120

121+
// HTTP/2 settings frame order
122+
let settings_order = SettingsOrder::builder()
123+
.extend([
124+
SettingId::HeaderTableSize,
125+
SettingId::EnablePush,
126+
SettingId::MaxConcurrentStreams,
127+
SettingId::InitialWindowSize,
128+
SettingId::MaxFrameSize,
129+
SettingId::MaxHeaderListSize,
130+
SettingId::EnableConnectProtocol,
131+
SettingId::NoRfc7540Priorities,
132+
])
133+
.build();
134+
135+
Http2Options::builder()
136+
.header_table_size(65536)
137+
.enable_push(false)
138+
.initial_window_size(131072)
139+
.max_frame_size(16384)
140+
.initial_connection_window_size(12517377 + 65535)
141+
.headers_stream_dependency(StreamDependency::new(StreamId::ZERO, 41, false))
142+
.headers_pseudo_order(headers_pseudo_order)
143+
.settings_order(settings_order)
144+
.build()
145+
}
146+
147+
fn emulation_template() -> Emulation {
108148
// HTTP/1 options config
109149
let http1 = Http1Options::builder()
110150
.allow_obsolete_multiline_headers_in_responses(true)
111151
.max_headers(100)
112152
.build();
113153

114-
// HTTP/2 options config
115-
let http2 = {
116-
// HTTP/2 headers frame pseudo-header order
117-
let headers_pseudo_order = PseudoOrder::builder()
118-
.extend([
119-
PseudoId::Method,
120-
PseudoId::Path,
121-
PseudoId::Authority,
122-
PseudoId::Scheme,
123-
])
124-
.build();
125-
126-
// HTTP/2 settings frame order
127-
let settings_order = SettingsOrder::builder()
128-
.extend([
129-
SettingId::HeaderTableSize,
130-
SettingId::EnablePush,
131-
SettingId::MaxConcurrentStreams,
132-
SettingId::InitialWindowSize,
133-
SettingId::MaxFrameSize,
134-
SettingId::MaxHeaderListSize,
135-
SettingId::EnableConnectProtocol,
136-
SettingId::NoRfc7540Priorities,
137-
])
138-
.build();
139-
140-
Http2Options::builder()
141-
.header_table_size(65536)
142-
.enable_push(false)
143-
.initial_window_size(131072)
144-
.max_frame_size(16384)
145-
.initial_connection_window_size(12517377 + 65535)
146-
.headers_stream_dependency(StreamDependency::new(StreamId::ZERO, 41, false))
147-
.headers_pseudo_order(headers_pseudo_order)
148-
.settings_order(settings_order)
149-
.build()
150-
};
151-
152154
// This provider encapsulates TLS, HTTP/1, HTTP/2, default headers, and original headers
153-
let emulation = Emulation::builder()
154-
.tls_options(tls)
155+
Emulation::builder()
156+
.tls_options(tls_options_template())
155157
.http1_options(http1)
156-
.http2_options(http2)
157-
.build();
158+
.http2_options(http2_options_template())
159+
.build()
160+
}
158161

162+
#[tokio::test]
163+
async fn test_emulation() -> wreq::Result<()> {
159164
// Build a client with emulation config
160165
let client = Client::builder()
161-
.emulation(emulation)
166+
.emulation(emulation_template())
167+
.connect_timeout(Duration::from_secs(10))
162168
.cert_verification(false)
163169
.build()?;
164170

@@ -176,3 +182,76 @@ async fn test_emulation_firefox() -> wreq::Result<()> {
176182

177183
Ok(())
178184
}
185+
186+
#[tokio::test]
187+
async fn test_request_with_emulation() -> wreq::Result<()> {
188+
// Build a client with emulation config
189+
let client = Client::builder()
190+
.connect_timeout(Duration::from_secs(10))
191+
.cert_verification(false)
192+
.build()?;
193+
194+
// Use the API you're already familiar with
195+
let resp = client
196+
.post("https://tls.browserleaks.com/")
197+
.emulation(emulation_template())
198+
.send()
199+
.await?;
200+
let text = resp.text().await?;
201+
assert!(
202+
text.contains("t13d1717h2_5b57614c22b0_3cbfd9057e0d"),
203+
"Response ja4_hash fingerprint not found"
204+
);
205+
assert!(
206+
text.contains("6ea73faa8fc5aac76bded7bd238f6433"),
207+
"Response akamai_hash fingerprint not found"
208+
);
209+
210+
Ok(())
211+
}
212+
213+
#[tokio::test]
214+
async fn test_request_with_emulation_tls() -> wreq::Result<()> {
215+
// Build a client with emulation config
216+
let client = Client::builder()
217+
.connect_timeout(Duration::from_secs(10))
218+
.cert_verification(false)
219+
.build()?;
220+
221+
// Use the API you're already familiar with
222+
let resp = client
223+
.get("https://tls.browserleaks.com/")
224+
.emulation(tls_options_template())
225+
.send()
226+
.await?;
227+
let text = resp.text().await?;
228+
assert!(
229+
text.contains("t13d1717h2_5b57614c22b0_3cbfd9057e0d"),
230+
"Response ja4_hash fingerprint not found"
231+
);
232+
233+
Ok(())
234+
}
235+
236+
#[tokio::test]
237+
async fn test_request_with_emulation_http2() -> wreq::Result<()> {
238+
// Build a client with emulation config
239+
let client = Client::builder()
240+
.connect_timeout(Duration::from_secs(10))
241+
.cert_verification(false)
242+
.build()?;
243+
244+
// Use the API you're already familiar with
245+
let resp = client
246+
.get("https://tls.browserleaks.com/")
247+
.emulation(http2_options_template())
248+
.send()
249+
.await?;
250+
let text = resp.text().await?;
251+
assert!(
252+
text.contains("6ea73faa8fc5aac76bded7bd238f6433"),
253+
"Response akamai_hash fingerprint not found"
254+
);
255+
256+
Ok(())
257+
}

0 commit comments

Comments
 (0)