1+ use std:: time:: Duration ;
2+
13use 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