wreq_util/emulation/
mod.rs

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