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