wreq 1.2.3-x64-mingw-ucrt
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Cargo.lock +1687 -0
- data/Cargo.toml +54 -0
- data/Gemfile +18 -0
- data/LICENSE +201 -0
- data/README.md +153 -0
- data/Rakefile +90 -0
- data/build.rs +16 -0
- data/docs/windows-gnu-tokio-crash.md +70 -0
- data/examples/body.rb +42 -0
- data/examples/client.rb +33 -0
- data/examples/cookie.rb +24 -0
- data/examples/emulate_request.rb +37 -0
- data/examples/headers.rb +27 -0
- data/examples/proxy.rb +113 -0
- data/examples/send_stream.rb +85 -0
- data/examples/stream.rb +14 -0
- data/examples/thread_interrupt.rb +83 -0
- data/extconf.rb +7 -0
- data/lib/wreq.rb +303 -0
- data/lib/wreq_ruby/3.3/wreq_ruby.so +0 -0
- data/lib/wreq_ruby/3.4/wreq_ruby.so +0 -0
- data/lib/wreq_ruby/4.0/wreq_ruby.so +0 -0
- data/lib/wreq_ruby/body.rb +36 -0
- data/lib/wreq_ruby/client.rb +526 -0
- data/lib/wreq_ruby/cookie.rb +156 -0
- data/lib/wreq_ruby/emulate.rb +232 -0
- data/lib/wreq_ruby/error.rb +157 -0
- data/lib/wreq_ruby/header.rb +205 -0
- data/lib/wreq_ruby/http.rb +160 -0
- data/lib/wreq_ruby/response.rb +209 -0
- data/script/build_platform_gem.rb +34 -0
- data/script/build_windows_gnu.ps1 +257 -0
- data/src/arch.rs +33 -0
- data/src/client/body/form.rs +2 -0
- data/src/client/body/json.rs +16 -0
- data/src/client/body/stream.rs +146 -0
- data/src/client/body.rs +57 -0
- data/src/client/param.rs +19 -0
- data/src/client/query.rs +2 -0
- data/src/client/req.rs +274 -0
- data/src/client/resp.rs +248 -0
- data/src/client.rs +413 -0
- data/src/cookie.rs +312 -0
- data/src/emulate.rs +376 -0
- data/src/error.rs +163 -0
- data/src/extractor.rs +117 -0
- data/src/gvl.rs +154 -0
- data/src/header.rs +245 -0
- data/src/http.rs +142 -0
- data/src/lib.rs +98 -0
- data/src/macros.rs +123 -0
- data/src/rt.rs +46 -0
- data/test/client_cookie_test.rb +46 -0
- data/test/client_test.rb +136 -0
- data/test/cookie_test.rb +182 -0
- data/test/emulation_test.rb +21 -0
- data/test/error_handling_test.rb +92 -0
- data/test/header_test.rb +290 -0
- data/test/inspect_test.rb +125 -0
- data/test/module_methods_test.rb +75 -0
- data/test/orig_header_test.rb +115 -0
- data/test/request_parameters_test.rb +175 -0
- data/test/request_test.rb +244 -0
- data/test/response_test.rb +69 -0
- data/test/stream_test.rb +397 -0
- data/test/test_helper.rb +52 -0
- data/wreq.gemspec +68 -0
- metadata +123 -0
data/src/cookie.rs
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
use std::{fmt, sync::Arc, time::SystemTime};
|
|
2
|
+
|
|
3
|
+
use bytes::Bytes;
|
|
4
|
+
use cookie::{Cookie as RawCookie, Expiration, ParseError, time::Duration};
|
|
5
|
+
use magnus::{
|
|
6
|
+
Error, Module, Object, RHash, RModule, RString, Ruby, TryConvert, Value, function, method,
|
|
7
|
+
r_hash::ForEach, typed_data::Obj, value::ReprValue,
|
|
8
|
+
};
|
|
9
|
+
use wreq::header::{self, HeaderMap, HeaderValue};
|
|
10
|
+
|
|
11
|
+
use crate::{error::header_value_error_to_magnus, gvl};
|
|
12
|
+
|
|
13
|
+
define_ruby_enum!(
|
|
14
|
+
/// The Cookie SameSite attribute.
|
|
15
|
+
const,
|
|
16
|
+
SameSite,
|
|
17
|
+
"Wreq::SameSite",
|
|
18
|
+
cookie::SameSite,
|
|
19
|
+
Strict,
|
|
20
|
+
Lax,
|
|
21
|
+
None,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
/// A single HTTP cookie.
|
|
25
|
+
#[derive(Clone)]
|
|
26
|
+
#[magnus::wrap(class = "Wreq::Cookie", free_immediately, size)]
|
|
27
|
+
pub struct Cookie(RawCookie<'static>);
|
|
28
|
+
|
|
29
|
+
/// A collection of HTTP cookies.
|
|
30
|
+
#[derive(Default)]
|
|
31
|
+
pub struct Cookies(pub Vec<HeaderValue>);
|
|
32
|
+
|
|
33
|
+
/// A good default `CookieStore` implementation.
|
|
34
|
+
///
|
|
35
|
+
/// This is the implementation used when simply calling `cookie_store(true)`.
|
|
36
|
+
/// This type is exposed to allow creating one and filling it with some
|
|
37
|
+
/// existing cookies more easily, before creating a `Client`.
|
|
38
|
+
#[derive(Clone, Default)]
|
|
39
|
+
#[magnus::wrap(class = "Wreq::Jar", free_immediately, size)]
|
|
40
|
+
pub struct Jar(pub Arc<wreq::cookie::Jar>);
|
|
41
|
+
|
|
42
|
+
// ===== impl Cookie =====
|
|
43
|
+
|
|
44
|
+
impl Cookie {
|
|
45
|
+
/// Create a new [`Cookie`].
|
|
46
|
+
pub fn new(args: &[Value]) -> Result<Self, Error> {
|
|
47
|
+
let args =
|
|
48
|
+
magnus::scan_args::scan_args::<(String, String), (), (), (), magnus::RHash, ()>(args)?;
|
|
49
|
+
#[allow(clippy::type_complexity)]
|
|
50
|
+
let keywords: magnus::scan_args::KwArgs<
|
|
51
|
+
(),
|
|
52
|
+
(
|
|
53
|
+
Option<String>,
|
|
54
|
+
Option<String>,
|
|
55
|
+
Option<u64>,
|
|
56
|
+
Option<f64>,
|
|
57
|
+
Option<bool>,
|
|
58
|
+
Option<bool>,
|
|
59
|
+
Option<Obj<SameSite>>,
|
|
60
|
+
),
|
|
61
|
+
(),
|
|
62
|
+
> = magnus::scan_args::get_kwargs(
|
|
63
|
+
args.keywords,
|
|
64
|
+
&[],
|
|
65
|
+
&[
|
|
66
|
+
"domain",
|
|
67
|
+
"path",
|
|
68
|
+
"max_age",
|
|
69
|
+
"expires",
|
|
70
|
+
"http_only",
|
|
71
|
+
"secure",
|
|
72
|
+
"same_site",
|
|
73
|
+
],
|
|
74
|
+
)?;
|
|
75
|
+
|
|
76
|
+
let (name, value) = args.required;
|
|
77
|
+
|
|
78
|
+
let mut cookie = RawCookie::new(name, value);
|
|
79
|
+
|
|
80
|
+
if let Some(domain) = keywords.optional.0 {
|
|
81
|
+
cookie.set_domain(domain);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if let Some(path) = keywords.optional.1 {
|
|
85
|
+
cookie.set_path(path);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if let Some(max_age) = keywords.optional.2 {
|
|
89
|
+
cookie.set_max_age(Duration::seconds(max_age as i64));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if let Some(expires) = keywords.optional.3 {
|
|
93
|
+
let duration = std::time::Duration::from_secs_f64(expires);
|
|
94
|
+
if let Some(system_time) = SystemTime::UNIX_EPOCH.checked_add(duration) {
|
|
95
|
+
cookie.set_expires(Expiration::DateTime(system_time.into()));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
cookie.set_http_only(keywords.optional.4);
|
|
100
|
+
cookie.set_secure(keywords.optional.5);
|
|
101
|
+
|
|
102
|
+
if let Some(same_site) = keywords.optional.6 {
|
|
103
|
+
cookie.set_same_site(same_site.into_ffi());
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
Ok(Self(cookie))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/// The name of the cookie.
|
|
110
|
+
#[inline]
|
|
111
|
+
pub fn name(&self) -> &str {
|
|
112
|
+
self.0.name()
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/// The value of the cookie.
|
|
116
|
+
#[inline]
|
|
117
|
+
pub fn value(&self) -> &str {
|
|
118
|
+
self.0.value()
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// Returns true if the 'HttpOnly' directive is enabled.
|
|
122
|
+
#[inline]
|
|
123
|
+
pub fn http_only(&self) -> bool {
|
|
124
|
+
self.0.http_only().unwrap_or(false)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/// Returns true if the 'Secure' directive is enabled.
|
|
128
|
+
#[inline]
|
|
129
|
+
pub fn secure(&self) -> bool {
|
|
130
|
+
self.0.secure().unwrap_or(false)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/// Returns true if 'SameSite' directive is 'Lax'.
|
|
134
|
+
#[inline]
|
|
135
|
+
pub fn same_site_lax(&self) -> bool {
|
|
136
|
+
self.0.same_site() == Some(cookie::SameSite::Lax)
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/// Returns true if 'SameSite' directive is 'Strict'.
|
|
140
|
+
#[inline]
|
|
141
|
+
pub fn same_site_strict(&self) -> bool {
|
|
142
|
+
self.0.same_site() == Some(cookie::SameSite::Strict)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// Returns the path directive of the cookie, if set.
|
|
146
|
+
#[inline]
|
|
147
|
+
pub fn path(&self) -> Option<&str> {
|
|
148
|
+
self.0.path()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/// Returns the domain directive of the cookie, if set.
|
|
152
|
+
#[inline]
|
|
153
|
+
pub fn domain(&self) -> Option<&str> {
|
|
154
|
+
self.0.domain()
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/// Get the Max-Age information.
|
|
158
|
+
#[inline]
|
|
159
|
+
pub fn max_age(&self) -> Option<i64> {
|
|
160
|
+
self.0.max_age().map(|d| d.whole_seconds())
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/// The cookie expiration time.
|
|
164
|
+
#[inline]
|
|
165
|
+
pub fn expires(&self) -> Option<f64> {
|
|
166
|
+
match self.0.expires() {
|
|
167
|
+
Some(Expiration::DateTime(offset)) => {
|
|
168
|
+
let system_time = SystemTime::from(offset);
|
|
169
|
+
system_time
|
|
170
|
+
.duration_since(SystemTime::UNIX_EPOCH)
|
|
171
|
+
.ok()
|
|
172
|
+
.map(|d| d.as_secs_f64())
|
|
173
|
+
}
|
|
174
|
+
None | Some(Expiration::Session) => None,
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
impl Cookie {
|
|
180
|
+
/// Parse cookies from a `HeaderMap`.
|
|
181
|
+
pub fn extract_headers_cookies(headers: &HeaderMap) -> Vec<Cookie> {
|
|
182
|
+
headers
|
|
183
|
+
.get_all(header::SET_COOKIE)
|
|
184
|
+
.iter()
|
|
185
|
+
.map(Cookie::parse)
|
|
186
|
+
.flat_map(Result::ok)
|
|
187
|
+
.map(RawCookie::into_owned)
|
|
188
|
+
.map(Cookie)
|
|
189
|
+
.collect()
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
fn parse<'a>(value: &'a HeaderValue) -> Result<RawCookie<'a>, ParseError> {
|
|
193
|
+
std::str::from_utf8(value.as_bytes())
|
|
194
|
+
.map_err(cookie::ParseError::from)
|
|
195
|
+
.and_then(RawCookie::parse)
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
impl fmt::Display for Cookie {
|
|
200
|
+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
201
|
+
write!(f, "{}", self.0)
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// ===== impl Cookies =====
|
|
206
|
+
|
|
207
|
+
impl TryConvert for Cookies {
|
|
208
|
+
fn try_convert(value: magnus::Value) -> Result<Self, magnus::Error> {
|
|
209
|
+
// try extract uncompressed cookies
|
|
210
|
+
if let Some(rhash) = RHash::from_value(value) {
|
|
211
|
+
let mut cookies = Vec::new();
|
|
212
|
+
rhash.foreach(|name: RString, value: RString| {
|
|
213
|
+
let cookie = format!("{name}={value}");
|
|
214
|
+
let header_value = HeaderValue::from_maybe_shared(Bytes::from(cookie))
|
|
215
|
+
.map_err(header_value_error_to_magnus)?;
|
|
216
|
+
cookies.push(header_value);
|
|
217
|
+
Ok(ForEach::Continue)
|
|
218
|
+
})?;
|
|
219
|
+
|
|
220
|
+
return Ok(Self(cookies));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// try extract compressed cookies
|
|
224
|
+
if let Some(cookies) = RString::from_value(value) {
|
|
225
|
+
return Ok(Self(vec![
|
|
226
|
+
HeaderValue::from_maybe_shared(cookies.to_bytes())
|
|
227
|
+
.map_err(header_value_error_to_magnus)?,
|
|
228
|
+
]));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
Ok(Self::default())
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ===== impl Jar =====
|
|
236
|
+
|
|
237
|
+
impl Jar {
|
|
238
|
+
/// Create a new [`Jar`] with an empty cookie store.
|
|
239
|
+
pub fn new() -> Self {
|
|
240
|
+
Jar(Arc::new(wreq::cookie::Jar::default()))
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/// Get all cookies.
|
|
244
|
+
pub fn get_all(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
245
|
+
let cookies: Vec<Cookie> = rb_self
|
|
246
|
+
.0
|
|
247
|
+
.get_all()
|
|
248
|
+
.map(RawCookie::from)
|
|
249
|
+
.map(Cookie)
|
|
250
|
+
.collect();
|
|
251
|
+
let ary = ruby.ary_new_capa(cookies.len());
|
|
252
|
+
for cookie in cookies {
|
|
253
|
+
ary.push(cookie)?;
|
|
254
|
+
}
|
|
255
|
+
Ok(ary.as_value())
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/// Add a cookie to this jar.
|
|
259
|
+
pub fn add(&self, cookie: Value, url: String) {
|
|
260
|
+
if let Ok(cookie) = Obj::<Cookie>::try_convert(cookie) {
|
|
261
|
+
gvl::nogvl(|| self.0.add(cookie.0.clone(), &url))
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if let Ok(cookie_str) = String::try_convert(cookie) {
|
|
265
|
+
gvl::nogvl(|| self.0.add(cookie_str.as_ref(), &url))
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/// Remove a cookie from this jar by name and URL.
|
|
270
|
+
pub fn remove(&self, name: String, url: String) {
|
|
271
|
+
gvl::nogvl(|| self.0.remove(name, &url))
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/// Clear all cookies in this jar.
|
|
275
|
+
pub fn clear(&self) {
|
|
276
|
+
gvl::nogvl(|| self.0.clear())
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
pub fn include(ruby: &Ruby, gem_module: &RModule) -> Result<(), Error> {
|
|
281
|
+
// SameSite enum
|
|
282
|
+
let same_site_class = gem_module.define_class("SameSite", ruby.class_object())?;
|
|
283
|
+
same_site_class.const_set("Strict", SameSite::Strict)?;
|
|
284
|
+
same_site_class.const_set("Lax", SameSite::Lax)?;
|
|
285
|
+
same_site_class.const_set("None", SameSite::None)?;
|
|
286
|
+
|
|
287
|
+
// Cookie class
|
|
288
|
+
let cookie_class = gem_module.define_class("Cookie", ruby.class_object())?;
|
|
289
|
+
cookie_class.define_singleton_method("new", function!(Cookie::new, -1))?;
|
|
290
|
+
cookie_class.define_method("name", method!(Cookie::name, 0))?;
|
|
291
|
+
cookie_class.define_method("value", method!(Cookie::value, 0))?;
|
|
292
|
+
cookie_class.define_method("http_only", method!(Cookie::http_only, 0))?;
|
|
293
|
+
cookie_class.define_method("http_only?", method!(Cookie::http_only, 0))?;
|
|
294
|
+
cookie_class.define_method("secure", method!(Cookie::secure, 0))?;
|
|
295
|
+
cookie_class.define_method("secure?", method!(Cookie::secure, 0))?;
|
|
296
|
+
cookie_class.define_method("same_site_lax?", method!(Cookie::same_site_lax, 0))?;
|
|
297
|
+
cookie_class.define_method("same_site_strict?", method!(Cookie::same_site_strict, 0))?;
|
|
298
|
+
cookie_class.define_method("path", method!(Cookie::path, 0))?;
|
|
299
|
+
cookie_class.define_method("domain", method!(Cookie::domain, 0))?;
|
|
300
|
+
cookie_class.define_method("max_age", method!(Cookie::max_age, 0))?;
|
|
301
|
+
cookie_class.define_method("expires", method!(Cookie::expires, 0))?;
|
|
302
|
+
|
|
303
|
+
// Jar class
|
|
304
|
+
let jar_class = gem_module.define_class("Jar", ruby.class_object())?;
|
|
305
|
+
jar_class.define_singleton_method("new", function!(Jar::new, 0))?;
|
|
306
|
+
jar_class.define_method("get_all", method!(Jar::get_all, 0))?;
|
|
307
|
+
jar_class.define_method("add", method!(Jar::add, 2))?;
|
|
308
|
+
jar_class.define_method("remove", method!(Jar::remove, 2))?;
|
|
309
|
+
jar_class.define_method("clear", method!(Jar::clear, 0))?;
|
|
310
|
+
|
|
311
|
+
Ok(())
|
|
312
|
+
}
|
data/src/emulate.rs
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
use magnus::{
|
|
2
|
+
Error, Module, Object, RHash, RModule, Ruby, TryConvert, Value, function, method,
|
|
3
|
+
typed_data::{Inspect, Obj},
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
define_ruby_enum!(
|
|
7
|
+
/// An emulation profile.
|
|
8
|
+
const,
|
|
9
|
+
Profile,
|
|
10
|
+
"Wreq::Profile",
|
|
11
|
+
wreq_util::Profile,
|
|
12
|
+
Chrome100,
|
|
13
|
+
Chrome101,
|
|
14
|
+
Chrome104,
|
|
15
|
+
Chrome105,
|
|
16
|
+
Chrome106,
|
|
17
|
+
Chrome107,
|
|
18
|
+
Chrome108,
|
|
19
|
+
Chrome109,
|
|
20
|
+
Chrome110,
|
|
21
|
+
Chrome114,
|
|
22
|
+
Chrome116,
|
|
23
|
+
Chrome117,
|
|
24
|
+
Chrome118,
|
|
25
|
+
Chrome119,
|
|
26
|
+
Chrome120,
|
|
27
|
+
Chrome123,
|
|
28
|
+
Chrome124,
|
|
29
|
+
Chrome126,
|
|
30
|
+
Chrome127,
|
|
31
|
+
Chrome128,
|
|
32
|
+
Chrome129,
|
|
33
|
+
Chrome130,
|
|
34
|
+
Chrome131,
|
|
35
|
+
Chrome132,
|
|
36
|
+
Chrome133,
|
|
37
|
+
Chrome134,
|
|
38
|
+
Chrome135,
|
|
39
|
+
Chrome136,
|
|
40
|
+
Chrome137,
|
|
41
|
+
Chrome138,
|
|
42
|
+
Chrome139,
|
|
43
|
+
Chrome140,
|
|
44
|
+
Chrome141,
|
|
45
|
+
Chrome142,
|
|
46
|
+
Chrome143,
|
|
47
|
+
Chrome144,
|
|
48
|
+
Chrome145,
|
|
49
|
+
Chrome146,
|
|
50
|
+
Chrome147,
|
|
51
|
+
Chrome148,
|
|
52
|
+
Chrome149,
|
|
53
|
+
|
|
54
|
+
Edge101,
|
|
55
|
+
Edge122,
|
|
56
|
+
Edge127,
|
|
57
|
+
Edge131,
|
|
58
|
+
Edge134,
|
|
59
|
+
Edge135,
|
|
60
|
+
Edge136,
|
|
61
|
+
Edge137,
|
|
62
|
+
Edge138,
|
|
63
|
+
Edge139,
|
|
64
|
+
Edge140,
|
|
65
|
+
Edge141,
|
|
66
|
+
Edge142,
|
|
67
|
+
Edge143,
|
|
68
|
+
Edge144,
|
|
69
|
+
Edge145,
|
|
70
|
+
Edge146,
|
|
71
|
+
Edge147,
|
|
72
|
+
Edge148,
|
|
73
|
+
|
|
74
|
+
Firefox109,
|
|
75
|
+
Firefox117,
|
|
76
|
+
Firefox128,
|
|
77
|
+
Firefox133,
|
|
78
|
+
Firefox135,
|
|
79
|
+
FirefoxPrivate135,
|
|
80
|
+
FirefoxAndroid135,
|
|
81
|
+
Firefox136,
|
|
82
|
+
FirefoxPrivate136,
|
|
83
|
+
Firefox139,
|
|
84
|
+
Firefox142,
|
|
85
|
+
Firefox143,
|
|
86
|
+
Firefox144,
|
|
87
|
+
Firefox145,
|
|
88
|
+
Firefox146,
|
|
89
|
+
Firefox147,
|
|
90
|
+
Firefox148,
|
|
91
|
+
Firefox149,
|
|
92
|
+
Firefox150,
|
|
93
|
+
Firefox151,
|
|
94
|
+
|
|
95
|
+
SafariIos17_2,
|
|
96
|
+
SafariIos17_4_1,
|
|
97
|
+
SafariIos16_5,
|
|
98
|
+
Safari15_3,
|
|
99
|
+
Safari15_5,
|
|
100
|
+
Safari15_6_1,
|
|
101
|
+
Safari16,
|
|
102
|
+
Safari16_5,
|
|
103
|
+
Safari17_0,
|
|
104
|
+
Safari17_2_1,
|
|
105
|
+
Safari17_4_1,
|
|
106
|
+
Safari17_5,
|
|
107
|
+
Safari17_6,
|
|
108
|
+
Safari18,
|
|
109
|
+
SafariIPad18,
|
|
110
|
+
Safari18_2,
|
|
111
|
+
Safari18_3,
|
|
112
|
+
Safari18_3_1,
|
|
113
|
+
SafariIos18_1_1,
|
|
114
|
+
Safari18_5,
|
|
115
|
+
Safari26,
|
|
116
|
+
Safari26_1,
|
|
117
|
+
Safari26_2,
|
|
118
|
+
Safari26_3,
|
|
119
|
+
Safari26_4,
|
|
120
|
+
SafariIos26,
|
|
121
|
+
SafariIos26_2,
|
|
122
|
+
SafariIPad26,
|
|
123
|
+
SafariIpad26_2,
|
|
124
|
+
|
|
125
|
+
OkHttp3_9,
|
|
126
|
+
OkHttp3_11,
|
|
127
|
+
OkHttp3_13,
|
|
128
|
+
OkHttp3_14,
|
|
129
|
+
OkHttp4_9,
|
|
130
|
+
OkHttp4_10,
|
|
131
|
+
OkHttp4_12,
|
|
132
|
+
OkHttp5,
|
|
133
|
+
|
|
134
|
+
Opera116,
|
|
135
|
+
Opera117,
|
|
136
|
+
Opera118,
|
|
137
|
+
Opera119,
|
|
138
|
+
Opera120,
|
|
139
|
+
Opera121,
|
|
140
|
+
Opera122,
|
|
141
|
+
Opera123,
|
|
142
|
+
Opera124,
|
|
143
|
+
Opera125,
|
|
144
|
+
Opera126,
|
|
145
|
+
Opera127,
|
|
146
|
+
Opera128,
|
|
147
|
+
Opera129,
|
|
148
|
+
Opera130,
|
|
149
|
+
Opera131,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
define_ruby_enum!(
|
|
153
|
+
/// An emulation profile for OS.
|
|
154
|
+
const,
|
|
155
|
+
Platform,
|
|
156
|
+
"Wreq::Platform",
|
|
157
|
+
wreq_util::Platform,
|
|
158
|
+
Windows,
|
|
159
|
+
MacOS,
|
|
160
|
+
Linux,
|
|
161
|
+
Android,
|
|
162
|
+
IOS,
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
/// A struct to represent the `EmulationOption` class.
|
|
166
|
+
#[derive(Clone)]
|
|
167
|
+
#[magnus::wrap(class = "Wreq::Emulation", free_immediately, size)]
|
|
168
|
+
pub struct Emulation(pub wreq_util::Emulation);
|
|
169
|
+
|
|
170
|
+
// ===== impl Profile =====
|
|
171
|
+
|
|
172
|
+
impl Profile {
|
|
173
|
+
pub fn to_s(&self) -> String {
|
|
174
|
+
self.into_ffi().inspect()
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// ===== impl Platform =====
|
|
179
|
+
|
|
180
|
+
impl Platform {
|
|
181
|
+
pub fn to_s(&self) -> String {
|
|
182
|
+
self.into_ffi().inspect()
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// ===== impl Emulation =====
|
|
187
|
+
|
|
188
|
+
impl Emulation {
|
|
189
|
+
fn new(ruby: &Ruby, args: &[Value]) -> Result<Self, Error> {
|
|
190
|
+
let mut profile = None;
|
|
191
|
+
let mut platform = None;
|
|
192
|
+
let mut http2 = None;
|
|
193
|
+
let mut headers = None;
|
|
194
|
+
|
|
195
|
+
if let Some(hash) = args.first().and_then(|v| RHash::from_value(*v)) {
|
|
196
|
+
if let Some(v) = hash.get(ruby.to_symbol(stringify!(profile))) {
|
|
197
|
+
profile = Some(Obj::<Profile>::try_convert(v)?);
|
|
198
|
+
}
|
|
199
|
+
if let Some(v) = hash.get(ruby.to_symbol(stringify!(platform))) {
|
|
200
|
+
platform = Some(Obj::<Platform>::try_convert(v)?);
|
|
201
|
+
}
|
|
202
|
+
if let Some(v) = hash.get(ruby.to_symbol(stringify!(http2))) {
|
|
203
|
+
http2 = Some(bool::try_convert(v)?);
|
|
204
|
+
}
|
|
205
|
+
if let Some(v) = hash.get(ruby.to_symbol(stringify!(headers))) {
|
|
206
|
+
headers = Some(bool::try_convert(v)?);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
let emulation = wreq_util::Emulation::builder()
|
|
211
|
+
.profile(profile.map(|obj| obj.into_ffi()).unwrap_or_default())
|
|
212
|
+
.platform(platform.map(|os| os.into_ffi()).unwrap_or_default())
|
|
213
|
+
.http2(http2.unwrap_or(true))
|
|
214
|
+
.headers(headers.unwrap_or(true))
|
|
215
|
+
.build();
|
|
216
|
+
|
|
217
|
+
Ok(Self(emulation))
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
pub fn include(ruby: &Ruby, gem_module: &RModule) -> Result<(), Error> {
|
|
222
|
+
// Profile enum binding
|
|
223
|
+
let profile = gem_module.define_class("Profile", ruby.class_object())?;
|
|
224
|
+
profile.define_method("to_s", method!(Profile::to_s, 0))?;
|
|
225
|
+
profile.const_set("Chrome100", Profile::Chrome100)?;
|
|
226
|
+
profile.const_set("Chrome101", Profile::Chrome101)?;
|
|
227
|
+
profile.const_set("Chrome104", Profile::Chrome104)?;
|
|
228
|
+
profile.const_set("Chrome105", Profile::Chrome105)?;
|
|
229
|
+
profile.const_set("Chrome106", Profile::Chrome106)?;
|
|
230
|
+
profile.const_set("Chrome107", Profile::Chrome107)?;
|
|
231
|
+
profile.const_set("Chrome108", Profile::Chrome108)?;
|
|
232
|
+
profile.const_set("Chrome109", Profile::Chrome109)?;
|
|
233
|
+
profile.const_set("Chrome110", Profile::Chrome110)?;
|
|
234
|
+
profile.const_set("Chrome114", Profile::Chrome114)?;
|
|
235
|
+
profile.const_set("Chrome116", Profile::Chrome116)?;
|
|
236
|
+
profile.const_set("Chrome117", Profile::Chrome117)?;
|
|
237
|
+
profile.const_set("Chrome118", Profile::Chrome118)?;
|
|
238
|
+
profile.const_set("Chrome119", Profile::Chrome119)?;
|
|
239
|
+
profile.const_set("Chrome120", Profile::Chrome120)?;
|
|
240
|
+
profile.const_set("Chrome123", Profile::Chrome123)?;
|
|
241
|
+
profile.const_set("Chrome124", Profile::Chrome124)?;
|
|
242
|
+
profile.const_set("Chrome126", Profile::Chrome126)?;
|
|
243
|
+
profile.const_set("Chrome127", Profile::Chrome127)?;
|
|
244
|
+
profile.const_set("Chrome128", Profile::Chrome128)?;
|
|
245
|
+
profile.const_set("Chrome129", Profile::Chrome129)?;
|
|
246
|
+
profile.const_set("Chrome130", Profile::Chrome130)?;
|
|
247
|
+
profile.const_set("Chrome131", Profile::Chrome131)?;
|
|
248
|
+
profile.const_set("Chrome132", Profile::Chrome132)?;
|
|
249
|
+
profile.const_set("Chrome133", Profile::Chrome133)?;
|
|
250
|
+
profile.const_set("Chrome134", Profile::Chrome134)?;
|
|
251
|
+
profile.const_set("Chrome135", Profile::Chrome135)?;
|
|
252
|
+
profile.const_set("Chrome136", Profile::Chrome136)?;
|
|
253
|
+
profile.const_set("Chrome137", Profile::Chrome137)?;
|
|
254
|
+
profile.const_set("Chrome138", Profile::Chrome138)?;
|
|
255
|
+
profile.const_set("Chrome139", Profile::Chrome139)?;
|
|
256
|
+
profile.const_set("Chrome140", Profile::Chrome140)?;
|
|
257
|
+
profile.const_set("Chrome141", Profile::Chrome141)?;
|
|
258
|
+
profile.const_set("Chrome142", Profile::Chrome142)?;
|
|
259
|
+
profile.const_set("Chrome143", Profile::Chrome143)?;
|
|
260
|
+
profile.const_set("Chrome144", Profile::Chrome144)?;
|
|
261
|
+
profile.const_set("Chrome145", Profile::Chrome145)?;
|
|
262
|
+
profile.const_set("Chrome146", Profile::Chrome146)?;
|
|
263
|
+
profile.const_set("Chrome147", Profile::Chrome147)?;
|
|
264
|
+
profile.const_set("Chrome148", Profile::Chrome148)?;
|
|
265
|
+
|
|
266
|
+
profile.const_set("Edge101", Profile::Edge101)?;
|
|
267
|
+
profile.const_set("Edge122", Profile::Edge122)?;
|
|
268
|
+
profile.const_set("Edge127", Profile::Edge127)?;
|
|
269
|
+
profile.const_set("Edge131", Profile::Edge131)?;
|
|
270
|
+
profile.const_set("Edge134", Profile::Edge134)?;
|
|
271
|
+
profile.const_set("Edge135", Profile::Edge135)?;
|
|
272
|
+
profile.const_set("Edge136", Profile::Edge136)?;
|
|
273
|
+
profile.const_set("Edge137", Profile::Edge137)?;
|
|
274
|
+
profile.const_set("Edge138", Profile::Edge138)?;
|
|
275
|
+
profile.const_set("Edge139", Profile::Edge139)?;
|
|
276
|
+
profile.const_set("Edge140", Profile::Edge140)?;
|
|
277
|
+
profile.const_set("Edge141", Profile::Edge141)?;
|
|
278
|
+
profile.const_set("Edge142", Profile::Edge142)?;
|
|
279
|
+
profile.const_set("Edge143", Profile::Edge143)?;
|
|
280
|
+
profile.const_set("Edge144", Profile::Edge144)?;
|
|
281
|
+
profile.const_set("Edge145", Profile::Edge145)?;
|
|
282
|
+
profile.const_set("Edge146", Profile::Edge146)?;
|
|
283
|
+
profile.const_set("Edge147", Profile::Edge147)?;
|
|
284
|
+
profile.const_set("Edge148", Profile::Edge148)?;
|
|
285
|
+
|
|
286
|
+
profile.const_set("Firefox109", Profile::Firefox109)?;
|
|
287
|
+
profile.const_set("Firefox117", Profile::Firefox117)?;
|
|
288
|
+
profile.const_set("Firefox128", Profile::Firefox128)?;
|
|
289
|
+
profile.const_set("Firefox133", Profile::Firefox133)?;
|
|
290
|
+
profile.const_set("Firefox135", Profile::Firefox135)?;
|
|
291
|
+
profile.const_set("FirefoxPrivate135", Profile::FirefoxPrivate135)?;
|
|
292
|
+
profile.const_set("FirefoxAndroid135", Profile::FirefoxAndroid135)?;
|
|
293
|
+
profile.const_set("Firefox136", Profile::Firefox136)?;
|
|
294
|
+
profile.const_set("FirefoxPrivate136", Profile::FirefoxPrivate136)?;
|
|
295
|
+
profile.const_set("Firefox139", Profile::Firefox139)?;
|
|
296
|
+
profile.const_set("Firefox142", Profile::Firefox142)?;
|
|
297
|
+
profile.const_set("Firefox143", Profile::Firefox143)?;
|
|
298
|
+
profile.const_set("Firefox144", Profile::Firefox144)?;
|
|
299
|
+
profile.const_set("Firefox145", Profile::Firefox145)?;
|
|
300
|
+
profile.const_set("Firefox146", Profile::Firefox146)?;
|
|
301
|
+
profile.const_set("Firefox147", Profile::Firefox147)?;
|
|
302
|
+
profile.const_set("Firefox148", Profile::Firefox148)?;
|
|
303
|
+
profile.const_set("Firefox149", Profile::Firefox149)?;
|
|
304
|
+
profile.const_set("Firefox150", Profile::Firefox150)?;
|
|
305
|
+
profile.const_set("Firefox151", Profile::Firefox151)?;
|
|
306
|
+
|
|
307
|
+
profile.const_set("SafariIos17_2", Profile::SafariIos17_2)?;
|
|
308
|
+
profile.const_set("SafariIos17_4_1", Profile::SafariIos17_4_1)?;
|
|
309
|
+
profile.const_set("SafariIos16_5", Profile::SafariIos16_5)?;
|
|
310
|
+
profile.const_set("Safari15_3", Profile::Safari15_3)?;
|
|
311
|
+
profile.const_set("Safari15_5", Profile::Safari15_5)?;
|
|
312
|
+
profile.const_set("Safari15_6_1", Profile::Safari15_6_1)?;
|
|
313
|
+
profile.const_set("Safari16", Profile::Safari16)?;
|
|
314
|
+
profile.const_set("Safari16_5", Profile::Safari16_5)?;
|
|
315
|
+
profile.const_set("Safari17_0", Profile::Safari17_0)?;
|
|
316
|
+
profile.const_set("Safari17_2_1", Profile::Safari17_2_1)?;
|
|
317
|
+
profile.const_set("Safari17_4_1", Profile::Safari17_4_1)?;
|
|
318
|
+
profile.const_set("Safari17_5", Profile::Safari17_5)?;
|
|
319
|
+
profile.const_set("Safari17_6", Profile::Safari17_6)?;
|
|
320
|
+
profile.const_set("Safari18", Profile::Safari18)?;
|
|
321
|
+
profile.const_set("SafariIPad18", Profile::SafariIPad18)?;
|
|
322
|
+
profile.const_set("Safari18_2", Profile::Safari18_2)?;
|
|
323
|
+
profile.const_set("Safari18_3", Profile::Safari18_3)?;
|
|
324
|
+
profile.const_set("Safari18_3_1", Profile::Safari18_3_1)?;
|
|
325
|
+
profile.const_set("SafariIos18_1_1", Profile::SafariIos18_1_1)?;
|
|
326
|
+
profile.const_set("Safari18_5", Profile::Safari18_5)?;
|
|
327
|
+
profile.const_set("Safari26", Profile::Safari26)?;
|
|
328
|
+
profile.const_set("Safari26_1", Profile::Safari26_1)?;
|
|
329
|
+
profile.const_set("Safari26_2", Profile::Safari26_2)?;
|
|
330
|
+
profile.const_set("Safari26_3", Profile::Safari26_3)?;
|
|
331
|
+
profile.const_set("Safari26_4", Profile::Safari26_4)?;
|
|
332
|
+
profile.const_set("SafariIos26", Profile::SafariIos26)?;
|
|
333
|
+
profile.const_set("SafariIos26_2", Profile::SafariIos26_2)?;
|
|
334
|
+
profile.const_set("SafariIPad26", Profile::SafariIPad26)?;
|
|
335
|
+
profile.const_set("SafariIpad26_2", Profile::SafariIpad26_2)?;
|
|
336
|
+
|
|
337
|
+
profile.const_set("OkHttp3_9", Profile::OkHttp3_9)?;
|
|
338
|
+
profile.const_set("OkHttp3_11", Profile::OkHttp3_11)?;
|
|
339
|
+
profile.const_set("OkHttp3_13", Profile::OkHttp3_13)?;
|
|
340
|
+
profile.const_set("OkHttp3_14", Profile::OkHttp3_14)?;
|
|
341
|
+
profile.const_set("OkHttp4_9", Profile::OkHttp4_9)?;
|
|
342
|
+
profile.const_set("OkHttp4_10", Profile::OkHttp4_10)?;
|
|
343
|
+
profile.const_set("OkHttp4_12", Profile::OkHttp4_12)?;
|
|
344
|
+
profile.const_set("OkHttp5", Profile::OkHttp5)?;
|
|
345
|
+
|
|
346
|
+
profile.const_set("Opera116", Profile::Opera116)?;
|
|
347
|
+
profile.const_set("Opera117", Profile::Opera117)?;
|
|
348
|
+
profile.const_set("Opera118", Profile::Opera118)?;
|
|
349
|
+
profile.const_set("Opera119", Profile::Opera119)?;
|
|
350
|
+
profile.const_set("Opera120", Profile::Opera120)?;
|
|
351
|
+
profile.const_set("Opera121", Profile::Opera121)?;
|
|
352
|
+
profile.const_set("Opera122", Profile::Opera122)?;
|
|
353
|
+
profile.const_set("Opera123", Profile::Opera123)?;
|
|
354
|
+
profile.const_set("Opera124", Profile::Opera124)?;
|
|
355
|
+
profile.const_set("Opera125", Profile::Opera125)?;
|
|
356
|
+
profile.const_set("Opera126", Profile::Opera126)?;
|
|
357
|
+
profile.const_set("Opera127", Profile::Opera127)?;
|
|
358
|
+
profile.const_set("Opera128", Profile::Opera128)?;
|
|
359
|
+
profile.const_set("Opera129", Profile::Opera129)?;
|
|
360
|
+
profile.const_set("Opera130", Profile::Opera130)?;
|
|
361
|
+
profile.const_set("Opera131", Profile::Opera131)?;
|
|
362
|
+
|
|
363
|
+
// Platform enum binding
|
|
364
|
+
let platform = gem_module.define_class("Platform", ruby.class_object())?;
|
|
365
|
+
platform.define_method("to_s", method!(Platform::to_s, 0))?;
|
|
366
|
+
platform.const_set("Windows", Platform::Windows)?;
|
|
367
|
+
platform.const_set("MacOS", Platform::MacOS)?;
|
|
368
|
+
platform.const_set("Linux", Platform::Linux)?;
|
|
369
|
+
platform.const_set("Android", Platform::Android)?;
|
|
370
|
+
platform.const_set("IOS", Platform::IOS)?;
|
|
371
|
+
|
|
372
|
+
// Emulation class binding
|
|
373
|
+
let emulation = gem_module.define_class("Emulation", ruby.class_object())?;
|
|
374
|
+
emulation.define_singleton_method("new", function!(Emulation::new, -1))?;
|
|
375
|
+
Ok(())
|
|
376
|
+
}
|