rquest_util/emulation/device/
mod.rs

1//! Emulation for different browsers.
2#![allow(missing_debug_implementations)]
3#![allow(missing_docs)]
4
5#[macro_use]
6mod macros;
7mod chrome;
8mod firefox;
9mod okhttp;
10mod safari;
11
12use rquest::{EmulationProvider, EmulationProviderFactory};
13use serde::{Deserialize, Serialize};
14use typed_builder::TypedBuilder;
15
16#[cfg(feature = "emulation-rand")]
17use strum_macros::VariantArray;
18
19use chrome::*;
20use firefox::*;
21use okhttp::*;
22use safari::*;
23
24mod emulation_imports {
25    pub use super::{EmulationOS, EmulationOption};
26    pub use rquest::header::{
27        ACCEPT, ACCEPT_LANGUAGE, HeaderMap, HeaderName, HeaderValue, UPGRADE_INSECURE_REQUESTS,
28        USER_AGENT,
29    };
30    pub use rquest::{EmulationProvider, Http2Config};
31
32    #[cfg(all(feature = "gzip", feature = "deflate", feature = "brotli"))]
33    pub use rquest::header::ACCEPT_ENCODING;
34}
35
36mod tls_imports {
37    pub use rquest::{
38        AlpnProtos, AlpsProtos, CertCompressionAlgorithm, ExtensionType, SslCurve, TlsConfig,
39        TlsVersion,
40    };
41    pub use typed_builder::TypedBuilder;
42}
43
44mod http2_imports {
45    pub use rquest::PseudoOrder::{self, *};
46    pub use rquest::SettingsOrder::{self, *};
47    pub use rquest::{Priority, StreamDependency, StreamId};
48    pub use std::sync::LazyLock;
49}
50
51macro_rules! define_emulation_enum {
52    ($(#[$meta:meta])* $name:ident, $default_variant:ident, $($variant:ident => $rename:expr),*) => {
53        $(#[$meta])*
54        #[cfg(not(feature = "emulation-rand"))]
55        #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
56        pub enum $name {
57            $(
58                #[serde(rename = $rename)]
59                $variant,
60            )*
61        }
62
63        #[cfg(not(feature = "emulation-rand"))]
64        impl Default for $name {
65            fn default() -> Self {
66                $name::$default_variant
67            }
68        }
69
70        $(#[$meta])*
71        #[cfg(feature = "emulation-rand")]
72        #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize, VariantArray)]
73        pub enum $name {
74            $(
75                #[serde(rename = $rename)]
76                $variant,
77            )*
78        }
79
80        #[cfg(feature = "emulation-rand")]
81        impl Default for $name {
82            fn default() -> Self {
83                $name::$default_variant
84            }
85        }
86    };
87}
88
89define_emulation_enum!(
90    /// Represents different browser versions for impersonation.
91    ///
92    /// The `Emulation` enum provides variants for different browser versions that can be used
93    /// to emulation HTTP requests. Each variant corresponds to a specific browser version.
94    ///
95    /// # Naming Convention
96    ///
97    /// The naming convention for the variants follows the pattern `browser_version`, where
98    /// `browser` is the name of the browser (e.g., `chrome`, `firefox`, `safari`) and `version`
99    /// is the version number. For example, `Chrome100` represents Chrome version 100.
100    ///
101    /// The serialized names of the variants use underscores to separate the browser name and
102    /// version number, following the pattern `browser_version`. For example, `Chrome100` is
103    /// serialized as `"chrome_100"`.
104    ///
105    /// # Examples
106    ///
107    /// ```rust
108    /// use rquest_util::Emulation;
109    ///
110    /// let emulation = Emulation::Chrome100;
111    /// let serialized = serde_json::to_string(&emulation).unwrap();
112    /// assert_eq!(serialized, "\"chrome_100\"");
113    ///
114    /// let deserialized: Emulation = serde_json::from_str(&serialized).unwrap();
115    /// assert_eq!(deserialized, Emulation::Chrome100);
116    /// ```
117    Emulation, Chrome133,
118    Chrome100 => "chrome_100",
119    Chrome101 => "chrome_101",
120    Chrome104 => "chrome_104",
121    Chrome105 => "chrome_105",
122    Chrome106 => "chrome_106",
123    Chrome107 => "chrome_107",
124    Chrome108 => "chrome_108",
125    Chrome109 => "chrome_109",
126    Chrome114 => "chrome_114",
127    Chrome116 => "chrome_116",
128    Chrome117 => "chrome_117",
129    Chrome118 => "chrome_118",
130    Chrome119 => "chrome_119",
131    Chrome120 => "chrome_120",
132    Chrome123 => "chrome_123",
133    Chrome124 => "chrome_124",
134    Chrome126 => "chrome_126",
135    Chrome127 => "chrome_127",
136    Chrome128 => "chrome_128",
137    Chrome129 => "chrome_129",
138    Chrome130 => "chrome_130",
139    Chrome131 => "chrome_131",
140    Chrome132 => "chrome_132",
141    Chrome133 => "chrome_133",
142    SafariIos17_2 => "safari_ios_17.2",
143    SafariIos17_4_1 => "safari_ios_17.4.1",
144    SafariIos16_5 => "safari_ios_16.5",
145    Safari15_3 => "safari_15.3",
146    Safari15_5 => "safari_15.5",
147    Safari15_6_1 => "safari_15.6.1",
148    Safari16 => "safari_16",
149    Safari16_5 => "safari_16.5",
150    Safari17_0 => "safari_17.0",
151    Safari17_2_1 => "safari_17.2.1",
152    Safari17_4_1 => "safari_17.4.1",
153    Safari17_5 => "safari_17.5",
154    Safari18 => "safari_18",
155    SafariIPad18 => "safari_ipad_18",
156    Safari18_2 => "safari_18.2",
157    SafariIos18_1_1 => "safari_ios_18.1.1",
158    OkHttp3_9 => "okhttp_3.9",
159    OkHttp3_11 => "okhttp_3.11",
160    OkHttp3_13 => "okhttp_3.13",
161    OkHttp3_14 => "okhttp_3.14",
162    OkHttp4_9 => "okhttp_4.9",
163    OkHttp4_10 => "okhttp_4.10",
164    OkHttp5 => "okhttp_5",
165    Edge101 => "edge_101",
166    Edge122 => "edge_122",
167    Edge127 => "edge_127",
168    Edge131 => "edge_131",
169    Firefox109 => "firefox_109",
170    Firefox117 => "firefox_117",
171    Firefox128 => "firefox_128",
172    Firefox133 => "firefox_133",
173    Firefox135 => "firefox_135",
174    FirefoxPrivate135 => "firefox_private_135",
175    FirefoxAndroid135 => "firefox_android_135"
176);
177
178/// ======== Emulation impls ========
179impl EmulationProviderFactory for Emulation {
180    fn emulation(self) -> EmulationProvider {
181        EmulationOption::builder()
182            .emulation(self)
183            .build()
184            .emulation()
185    }
186}
187
188/// Represents different operating systems for impersonation.
189///
190/// The `EmulationOS` enum provides variants for different operating systems that can be used
191/// to emulation HTTP requests. Each variant corresponds to a specific operating system.
192///
193/// # Naming Convention
194///
195/// The naming convention for the variants follows the pattern `os_name`, where
196/// `os_name` is the name of the operating system (e.g., `windows`, `macos`, `linux`, `android`, `ios`).
197///
198/// The serialized names of the variants use lowercase letters to represent the operating system names.
199/// For example, `Windows` is serialized as `"windows"`.
200///
201/// # Examples
202///
203/// ```rust
204/// use rquest::EmulationOS;
205///
206/// let emulation_os = EmulationOS::Windows;
207/// let serialized = serde_json::to_string(&emulation_os).unwrap();
208/// assert_eq!(serialized, "\"windows\"");
209///
210/// let deserialized: EmulationOS = serde_json::from_str(&serialized).unwrap();
211/// assert_eq!(deserialized, EmulationOS::Windows);
212/// ```
213#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
214pub enum EmulationOS {
215    #[serde(rename = "windows")]
216    Windows,
217    #[serde(rename = "macos")]
218    #[default]
219    MacOS,
220    #[serde(rename = "linux")]
221    Linux,
222    #[serde(rename = "android")]
223    Android,
224    #[serde(rename = "ios")]
225    IOS,
226}
227
228/// ======== EmulationOS impls ========
229impl EmulationOS {
230    #[inline]
231    fn platform(&self) -> &'static str {
232        match self {
233            EmulationOS::MacOS => "\"macOS\"",
234            EmulationOS::Linux => "\"Linux\"",
235            EmulationOS::Windows => "\"Windows\"",
236            EmulationOS::Android => "\"Android\"",
237            EmulationOS::IOS => "\"iOS\"",
238        }
239    }
240
241    #[inline]
242    fn is_mobile(&self) -> bool {
243        matches!(self, EmulationOS::Android | EmulationOS::IOS)
244    }
245}
246
247#[derive(Default, TypedBuilder)]
248pub struct EmulationOption {
249    /// The browser version to emulation.
250    #[builder(default)]
251    emulation: Emulation,
252
253    /// The operating system.
254    #[builder(default)]
255    emulation_os: EmulationOS,
256
257    /// Whether to skip HTTP/2.
258    #[builder(default = false)]
259    skip_http2: bool,
260
261    /// Whether to skip headers.
262    #[builder(default = false)]
263    skip_headers: bool,
264}
265
266/// ======== EmulationOption impls ========
267impl EmulationProviderFactory for EmulationOption {
268    fn emulation(self) -> EmulationProvider {
269        emulation_match!(
270            self.emulation,
271            self,
272
273            Emulation::Chrome100 => v100::emulation,
274            Emulation::Chrome101 => v101::emulation,
275            Emulation::Chrome104 => v104::emulation,
276            Emulation::Chrome105 => v105::emulation,
277            Emulation::Chrome106 => v106::emulation,
278            Emulation::Chrome107 => v107::emulation,
279            Emulation::Chrome108 => v108::emulation,
280            Emulation::Chrome109 => v109::emulation,
281            Emulation::Chrome114 => v114::emulation,
282            Emulation::Chrome116 => v116::emulation,
283            Emulation::Chrome117 => v117::emulation,
284            Emulation::Chrome118 => v118::emulation,
285            Emulation::Chrome119 => v119::emulation,
286            Emulation::Chrome120 => v120::emulation,
287            Emulation::Chrome123 => v123::emulation,
288            Emulation::Chrome124 => v124::emulation,
289            Emulation::Chrome126 => v126::emulation,
290            Emulation::Chrome127 => v127::emulation,
291            Emulation::Chrome128 => v128::emulation,
292            Emulation::Chrome129 => v129::emulation,
293            Emulation::Chrome130 => v130::emulation,
294            Emulation::Chrome131 => v131::emulation,
295            Emulation::Chrome132 => v132::emulation,
296            Emulation::Chrome133 => v133::emulation,
297
298            Emulation::SafariIos17_2 => safari_ios_17_2::emulation,
299            Emulation::SafariIos17_4_1 => safari_ios_17_4_1::emulation,
300            Emulation::SafariIos16_5 => safari_ios_16_5::emulation,
301            Emulation::Safari15_3 => safari15_3::emulation,
302            Emulation::Safari15_5 => safari15_5::emulation,
303            Emulation::Safari15_6_1 => safari15_6_1::emulation,
304            Emulation::Safari16 => safari16::emulation,
305            Emulation::Safari16_5 => safari16_5::emulation,
306            Emulation::Safari17_0 => safari17_0::emulation,
307            Emulation::Safari17_2_1 => safari17_2_1::emulation,
308            Emulation::Safari17_4_1 => safari17_4_1::emulation,
309            Emulation::Safari17_5 => safari17_5::emulation,
310            Emulation::Safari18 => safari18::emulation,
311            Emulation::SafariIPad18 => safari_ipad_18::emulation,
312            Emulation::Safari18_2 => safari18_2::emulation,
313            Emulation::SafariIos18_1_1 => safari_ios_18_1_1::emulation,
314
315            Emulation::OkHttp3_9 => okhttp3_9::emulation,
316            Emulation::OkHttp3_11 => okhttp3_11::emulation,
317            Emulation::OkHttp3_13 => okhttp3_13::emulation,
318            Emulation::OkHttp3_14 => okhttp3_14::emulation,
319            Emulation::OkHttp4_9 => okhttp4_9::emulation,
320            Emulation::OkHttp4_10 => okhttp4_10::emulation,
321            Emulation::OkHttp5 => okhttp5::emulation,
322
323            Emulation::Edge101 => edge101::emulation,
324            Emulation::Edge122 => edge122::emulation,
325            Emulation::Edge127 => edge127::emulation,
326            Emulation::Edge131 => edge131::emulation,
327
328            Emulation::Firefox109 => ff109::emulation,
329            Emulation::Firefox117 => ff117::emulation,
330            Emulation::Firefox128 => ff128::emulation,
331            Emulation::Firefox133 => ff133::emulation,
332            Emulation::Firefox135 => ff135::emulation,
333            Emulation::FirefoxPrivate135 => ff_private_135::emulation,
334            Emulation::FirefoxAndroid135 => ff_android_135::emulation
335        )
336    }
337}