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 rquest::Http2Config;
26    pub use rquest::header::{
27        ACCEPT, ACCEPT_LANGUAGE, HeaderMap, HeaderName, HeaderValue, UPGRADE_INSECURE_REQUESTS,
28        USER_AGENT,
29    };
30
31    #[cfg(all(feature = "gzip", feature = "deflate", feature = "brotli"))]
32    pub use rquest::header::ACCEPT_ENCODING;
33}
34
35mod tls_imports {
36    pub use rquest::{
37        AlpnProtos, AlpsProtos, CertCompressionAlgorithm, ExtensionType, SslCurve, TlsConfig,
38        TlsVersion,
39    };
40    pub use typed_builder::TypedBuilder;
41}
42
43mod http2_imports {
44    pub use rquest::PseudoOrder::{self, *};
45    pub use rquest::SettingsOrder::{self, *};
46    pub use rquest::{Priority, StreamDependency, StreamId};
47    pub use std::sync::LazyLock;
48}
49
50macro_rules! define_emulation_enum {
51    ($(#[$meta:meta])* $name:ident, $default_variant:ident, $($variant:ident => $rename:expr),*) => {
52        $(#[$meta])*
53        #[cfg(not(feature = "emulation-rand"))]
54        #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
55        pub enum $name {
56            $(
57                #[serde(rename = $rename)]
58                $variant,
59            )*
60        }
61
62        #[cfg(not(feature = "emulation-rand"))]
63        impl Default for $name {
64            fn default() -> Self {
65                $name::$default_variant
66            }
67        }
68
69        $(#[$meta])*
70        #[cfg(feature = "emulation-rand")]
71        #[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize, VariantArray)]
72        pub enum $name {
73            $(
74                #[serde(rename = $rename)]
75                $variant,
76            )*
77        }
78
79        #[cfg(feature = "emulation-rand")]
80        impl Default for $name {
81            fn default() -> Self {
82                $name::$default_variant
83            }
84        }
85    };
86}
87
88define_emulation_enum!(
89    /// Represents different browser versions for impersonation.
90    ///
91    /// The `Emulation` enum provides variants for different browser versions that can be used
92    /// to emulation HTTP requests. Each variant corresponds to a specific browser version.
93    ///
94    /// # Naming Convention
95    ///
96    /// The naming convention for the variants follows the pattern `browser_version`, where
97    /// `browser` is the name of the browser (e.g., `chrome`, `firefox`, `safari`) and `version`
98    /// is the version number. For example, `Chrome100` represents Chrome version 100.
99    ///
100    /// The serialized names of the variants use underscores to separate the browser name and
101    /// version number, following the pattern `browser_version`. For example, `Chrome100` is
102    /// serialized as `"chrome_100"`.
103    ///
104    /// # Examples
105    ///
106    /// ```rust
107    /// use rquest_util::Emulation;
108    ///
109    /// let emulation = Emulation::Chrome100;
110    /// let serialized = serde_json::to_string(&emulation).unwrap();
111    /// assert_eq!(serialized, "\"chrome_100\"");
112    ///
113    /// let deserialized: Emulation = serde_json::from_str(&serialized).unwrap();
114    /// assert_eq!(deserialized, Emulation::Chrome100);
115    /// ```
116    Emulation, Chrome133,
117    Chrome100 => "chrome_100",
118    Chrome101 => "chrome_101",
119    Chrome104 => "chrome_104",
120    Chrome105 => "chrome_105",
121    Chrome106 => "chrome_106",
122    Chrome107 => "chrome_107",
123    Chrome108 => "chrome_108",
124    Chrome109 => "chrome_109",
125    Chrome114 => "chrome_114",
126    Chrome116 => "chrome_116",
127    Chrome117 => "chrome_117",
128    Chrome118 => "chrome_118",
129    Chrome119 => "chrome_119",
130    Chrome120 => "chrome_120",
131    Chrome123 => "chrome_123",
132    Chrome124 => "chrome_124",
133    Chrome126 => "chrome_126",
134    Chrome127 => "chrome_127",
135    Chrome128 => "chrome_128",
136    Chrome129 => "chrome_129",
137    Chrome130 => "chrome_130",
138    Chrome131 => "chrome_131",
139    Chrome132 => "chrome_132",
140    Chrome133 => "chrome_133",
141    SafariIos17_2 => "safari_ios_17.2",
142    SafariIos17_4_1 => "safari_ios_17.4.1",
143    SafariIos16_5 => "safari_ios_16.5",
144    Safari15_3 => "safari_15.3",
145    Safari15_5 => "safari_15.5",
146    Safari15_6_1 => "safari_15.6.1",
147    Safari16 => "safari_16",
148    Safari16_5 => "safari_16.5",
149    Safari17_0 => "safari_17.0",
150    Safari17_2_1 => "safari_17.2.1",
151    Safari17_4_1 => "safari_17.4.1",
152    Safari17_5 => "safari_17.5",
153    Safari18 => "safari_18",
154    SafariIPad18 => "safari_ipad_18",
155    Safari18_2 => "safari_18.2",
156    SafariIos18_1_1 => "safari_ios_18.1.1",
157    Safari18_3 => "safari_18.3",
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            Emulation::Safari18_3 => safari18_3::emulation,
315
316            Emulation::OkHttp3_9 => okhttp3_9::emulation,
317            Emulation::OkHttp3_11 => okhttp3_11::emulation,
318            Emulation::OkHttp3_13 => okhttp3_13::emulation,
319            Emulation::OkHttp3_14 => okhttp3_14::emulation,
320            Emulation::OkHttp4_9 => okhttp4_9::emulation,
321            Emulation::OkHttp4_10 => okhttp4_10::emulation,
322            Emulation::OkHttp5 => okhttp5::emulation,
323
324            Emulation::Edge101 => edge101::emulation,
325            Emulation::Edge122 => edge122::emulation,
326            Emulation::Edge127 => edge127::emulation,
327            Emulation::Edge131 => edge131::emulation,
328
329            Emulation::Firefox109 => ff109::emulation,
330            Emulation::Firefox117 => ff117::emulation,
331            Emulation::Firefox128 => ff128::emulation,
332            Emulation::Firefox133 => ff133::emulation,
333            Emulation::Firefox135 => ff135::emulation,
334            Emulation::FirefoxPrivate135 => ff_private_135::emulation,
335            Emulation::FirefoxAndroid135 => ff_android_135::emulation
336        )
337    }
338}