wreq 1.2.5 → 1.2.6
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 +4 -4
- data/Cargo.lock +20 -13
- data/Cargo.toml +10 -2
- data/crates/wreq-util/src/emulate/macros.rs +12 -10
- data/crates/wreq-util/src/emulate/profile/chrome/header.rs +18 -3
- data/crates/wreq-util/src/emulate/profile/firefox/header.rs +16 -0
- data/crates/wreq-util/src/emulate/profile/opera/header.rs +6 -7
- data/crates/wreq-util/tests/client.rs +103 -1
- data/lib/wreq.rb +70 -45
- data/lib/wreq_ruby/body.rb +29 -11
- data/lib/wreq_ruby/client.rb +88 -55
- data/lib/wreq_ruby/cookie.rb +79 -19
- data/lib/wreq_ruby/emulate.rb +74 -6
- data/lib/wreq_ruby/error.rb +5 -7
- data/lib/wreq_ruby/http.rb +74 -0
- data/lib/wreq_ruby/response.rb +3 -0
- data/script/build_windows_gnu.ps1 +6 -0
- data/src/arch.rs +22 -0
- data/src/client/body/form.rs +2 -0
- data/src/client/body/json.rs +47 -14
- data/src/client/body/stream.rs +147 -43
- data/src/client/body.rs +11 -15
- data/src/client/param.rs +7 -7
- data/src/client/req.rs +87 -47
- data/src/client/resp.rs +23 -24
- data/src/client.rs +310 -230
- data/src/cookie.rs +280 -87
- data/src/emulate.rs +85 -50
- data/src/error.rs +198 -41
- data/src/extractor.rs +16 -76
- data/src/header.rs +146 -23
- data/src/http.rs +62 -33
- data/src/lib.rs +26 -20
- data/src/macros.rs +71 -46
- data/src/options.rs +284 -0
- data/src/rt.rs +22 -11
- data/src/serde/de/array_deserializer.rs +48 -0
- data/src/serde/de/array_enumerator.rs +59 -0
- data/src/serde/de/deserializer.rs +307 -0
- data/src/serde/de/enum_deserializer.rs +47 -0
- data/src/serde/de/hash_deserializer.rs +89 -0
- data/src/serde/de/number_deserializer.rs +51 -0
- data/src/serde/de/variant_deserializer.rs +101 -0
- data/src/serde/de.rs +33 -0
- data/src/serde/error.rs +146 -0
- data/src/serde/ser/enums.rs +14 -0
- data/src/serde/ser/map_serializer.rs +56 -0
- data/src/serde/ser/seq_serializer.rs +71 -0
- data/src/serde/ser/serializer.rs +194 -0
- data/src/serde/ser/struct_serializer.rs +106 -0
- data/src/serde/ser/struct_variant_serializer.rs +44 -0
- data/src/serde/ser/tuple_variant_serializer.rs +41 -0
- data/src/serde/ser.rs +18 -0
- data/src/serde/tests.rs +237 -0
- data/src/serde.rs +202 -0
- data/test/body_sender_test.rb +246 -0
- data/test/cookie_test.rb +211 -10
- data/test/json_precision_test.rb +209 -0
- data/test/option_validation_test.rb +311 -0
- data/test/value_semantics_test.rb +238 -0
- metadata +25 -2
- data/src/header/helper.rs +0 -112
data/src/client/param.rs
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
+
use ::serde::{Deserialize, Serialize};
|
|
1
2
|
use indexmap::IndexMap;
|
|
2
|
-
use serde::{Deserialize, Serialize};
|
|
3
3
|
|
|
4
|
-
///
|
|
4
|
+
/// HTTP parameters represented as an insertion-ordered Ruby mapping.
|
|
5
5
|
pub type Params = IndexMap<String, ParamValue>;
|
|
6
6
|
|
|
7
|
-
///
|
|
7
|
+
/// A scalar Ruby value accepted in query-string and form mappings.
|
|
8
8
|
#[derive(Serialize, Deserialize)]
|
|
9
9
|
#[serde(untagged)]
|
|
10
10
|
pub enum ParamValue {
|
|
11
|
-
/// A
|
|
11
|
+
/// A Ruby `true` or `false` value.
|
|
12
12
|
Boolean(bool),
|
|
13
|
-
///
|
|
13
|
+
/// A Ruby Integer that fits in the native pointer-sized range.
|
|
14
14
|
Number(isize),
|
|
15
|
-
/// A
|
|
15
|
+
/// A Ruby Float.
|
|
16
16
|
Float64(f64),
|
|
17
|
-
/// A
|
|
17
|
+
/// A Ruby String or Symbol.
|
|
18
18
|
String(String),
|
|
19
19
|
}
|
data/src/client/req.rs
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
use std::{net::IpAddr, time::Duration};
|
|
2
2
|
|
|
3
|
+
use ::serde::Deserialize;
|
|
3
4
|
use http::header;
|
|
4
5
|
use magnus::{RHash, TryConvert, typed_data::Obj, value::ReprValue};
|
|
5
|
-
use serde::Deserialize;
|
|
6
6
|
use wreq::{Client, Proxy};
|
|
7
7
|
|
|
8
|
-
use super::body::{Body, Form, Json};
|
|
8
|
+
use super::body::{Body, form::Form, json::Json};
|
|
9
9
|
use crate::{
|
|
10
|
+
arch::SUPPORTS_INTERFACE,
|
|
10
11
|
client::{query::Query, resp::Response},
|
|
11
12
|
cookie::Cookies,
|
|
12
13
|
emulate::Emulation,
|
|
13
|
-
error::
|
|
14
|
+
error::wreq_error,
|
|
14
15
|
extractor::Extractor,
|
|
15
16
|
header::{Headers, OrigHeaders},
|
|
16
17
|
http::{Method, Version},
|
|
18
|
+
options::{NativeOption, Options},
|
|
17
19
|
rt,
|
|
18
20
|
};
|
|
19
21
|
|
|
@@ -22,12 +24,12 @@ use crate::{
|
|
|
22
24
|
#[non_exhaustive]
|
|
23
25
|
pub struct Request {
|
|
24
26
|
/// The emulation option for the request.
|
|
25
|
-
#[serde(
|
|
26
|
-
emulation:
|
|
27
|
+
#[serde(default)]
|
|
28
|
+
emulation: NativeOption<Emulation>,
|
|
27
29
|
|
|
28
30
|
/// The proxy to use for the request.
|
|
29
|
-
#[serde(
|
|
30
|
-
proxy:
|
|
31
|
+
#[serde(default)]
|
|
32
|
+
proxy: NativeOption<Proxy>,
|
|
31
33
|
|
|
32
34
|
/// Bind to a local IP Address.
|
|
33
35
|
local_address: Option<IpAddr>,
|
|
@@ -43,23 +45,23 @@ pub struct Request {
|
|
|
43
45
|
read_timeout: Option<u64>,
|
|
44
46
|
|
|
45
47
|
/// The HTTP version to use for the request.
|
|
46
|
-
#[serde(
|
|
47
|
-
version:
|
|
48
|
+
#[serde(default)]
|
|
49
|
+
version: NativeOption<Version>,
|
|
48
50
|
|
|
49
51
|
/// The option enables default headers.
|
|
50
52
|
default_headers: Option<bool>,
|
|
51
53
|
|
|
52
54
|
/// The headers to use for the request.
|
|
53
|
-
#[serde(
|
|
54
|
-
headers:
|
|
55
|
+
#[serde(default)]
|
|
56
|
+
headers: NativeOption<Headers>,
|
|
55
57
|
|
|
56
58
|
/// The original headers to use for the request.
|
|
57
|
-
#[serde(
|
|
58
|
-
orig_headers:
|
|
59
|
+
#[serde(default)]
|
|
60
|
+
orig_headers: NativeOption<OrigHeaders>,
|
|
59
61
|
|
|
60
62
|
/// The cookies to use for the request.
|
|
61
|
-
#[serde(
|
|
62
|
-
cookies:
|
|
63
|
+
#[serde(default)]
|
|
64
|
+
cookies: NativeOption<Cookies>,
|
|
63
65
|
|
|
64
66
|
/// Whether to allow redirects.
|
|
65
67
|
allow_redirects: Option<bool>,
|
|
@@ -95,57 +97,95 @@ pub struct Request {
|
|
|
95
97
|
form: Option<Form>,
|
|
96
98
|
|
|
97
99
|
/// The JSON body to use for the request.
|
|
98
|
-
|
|
100
|
+
#[serde(default)]
|
|
101
|
+
json: NativeOption<Json>,
|
|
99
102
|
|
|
100
103
|
/// The body to use for the request.
|
|
101
|
-
#[serde(
|
|
102
|
-
body:
|
|
104
|
+
#[serde(default)]
|
|
105
|
+
body: NativeOption<Body>,
|
|
103
106
|
}
|
|
104
107
|
|
|
105
108
|
impl Request {
|
|
106
109
|
/// Create a new [`Request`] from Ruby keyword arguments.
|
|
110
|
+
///
|
|
111
|
+
/// # Errors
|
|
112
|
+
///
|
|
113
|
+
/// Returns before network I/O for unknown, duplicate, unsupported,
|
|
114
|
+
/// conflicting, ineffective, or invalid option values.
|
|
107
115
|
pub fn new(ruby: &magnus::Ruby, hash: RHash) -> Result<Self, magnus::Error> {
|
|
108
116
|
let keyword = hash.as_value();
|
|
109
|
-
let
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
builder.proxy = Extractor::<Proxy>::try_convert(keyword)?.into_inner();
|
|
117
|
+
let options = Options::new(ruby, hash);
|
|
118
|
+
let mut builder = Self::deserialize_options(&options)?;
|
|
119
|
+
options
|
|
120
|
+
.validator()
|
|
121
|
+
.require_when_present(
|
|
122
|
+
stringify!(max_redirects),
|
|
123
|
+
builder.max_redirects.is_some(),
|
|
124
|
+
builder.allow_redirects == Some(true),
|
|
125
|
+
":allow_redirects to be true",
|
|
126
|
+
)
|
|
127
|
+
.finish()?;
|
|
128
|
+
|
|
129
|
+
extract_native_option!(
|
|
130
|
+
options,
|
|
131
|
+
builder,
|
|
132
|
+
emulation,
|
|
133
|
+
Obj<Emulation> => |value| (*value).clone()
|
|
134
|
+
);
|
|
135
|
+
extract_native_option!(options, builder, version);
|
|
136
|
+
extract_native_option!(options, builder, headers);
|
|
137
|
+
extract_native_option!(options, builder, orig_headers);
|
|
138
|
+
extract_native_option!(options, builder, cookies);
|
|
139
|
+
extract_native_option!(options, builder, json, present);
|
|
140
|
+
builder
|
|
141
|
+
.proxy
|
|
142
|
+
.set(Extractor::<Proxy>::try_convert(keyword)?.into_inner());
|
|
143
|
+
extract_native_option!(options, builder, body);
|
|
137
144
|
|
|
138
145
|
Ok(builder)
|
|
139
146
|
}
|
|
147
|
+
|
|
148
|
+
/// Validate pre-conversion rules and deserialize the request options.
|
|
149
|
+
///
|
|
150
|
+
/// # Errors
|
|
151
|
+
///
|
|
152
|
+
/// Returns `ArgumentError` for failed rules or the Ruby conversion error
|
|
153
|
+
/// produced by an invalid option value.
|
|
154
|
+
fn deserialize_options(options: &Options<'_>) -> Result<Self, magnus::Error> {
|
|
155
|
+
options
|
|
156
|
+
.validate_keys::<Self>()?
|
|
157
|
+
.validator()
|
|
158
|
+
.reject_unsupported(stringify!(interface), SUPPORTS_INTERFACE)
|
|
159
|
+
.reject_conflicts([
|
|
160
|
+
(stringify!(body), options.is_non_nil(stringify!(body))),
|
|
161
|
+
(stringify!(form), options.is_non_nil(stringify!(form))),
|
|
162
|
+
(stringify!(json), options.is_present(stringify!(json))),
|
|
163
|
+
])
|
|
164
|
+
.reject_conflicts([
|
|
165
|
+
(stringify!(auth), options.is_non_nil(stringify!(auth))),
|
|
166
|
+
(
|
|
167
|
+
stringify!(bearer_auth),
|
|
168
|
+
options.is_non_nil(stringify!(bearer_auth)),
|
|
169
|
+
),
|
|
170
|
+
(
|
|
171
|
+
stringify!(basic_auth),
|
|
172
|
+
options.is_non_nil(stringify!(basic_auth)),
|
|
173
|
+
),
|
|
174
|
+
])
|
|
175
|
+
.finish()?
|
|
176
|
+
.deserialize::<Self>()
|
|
177
|
+
}
|
|
140
178
|
}
|
|
141
179
|
|
|
142
180
|
pub fn execute_request<U: AsRef<str>>(
|
|
181
|
+
ruby: &magnus::Ruby,
|
|
143
182
|
client: Client,
|
|
144
183
|
method: Method,
|
|
145
184
|
url: U,
|
|
146
185
|
mut request: Request,
|
|
147
186
|
) -> Result<Response, magnus::Error> {
|
|
148
187
|
rt::try_block_on(
|
|
188
|
+
ruby,
|
|
149
189
|
async move {
|
|
150
190
|
let mut builder = client.request(method.into_ffi(), url.as_ref());
|
|
151
191
|
|
|
@@ -269,6 +309,6 @@ pub fn execute_request<U: AsRef<str>>(
|
|
|
269
309
|
// Send request.
|
|
270
310
|
builder.send().await.map(Response::new)
|
|
271
311
|
},
|
|
272
|
-
|
|
312
|
+
wreq_error,
|
|
273
313
|
)
|
|
274
314
|
}
|
data/src/client/resp.rs
CHANGED
|
@@ -9,10 +9,10 @@ use magnus::{Error, Module, RArray, RModule, Ruby, Value, scan_args::scan_args};
|
|
|
9
9
|
use wreq::Uri;
|
|
10
10
|
|
|
11
11
|
use crate::{
|
|
12
|
-
client::body::{
|
|
12
|
+
client::body::{json::Json, stream::BodyReceiver},
|
|
13
13
|
cookie::Cookie,
|
|
14
|
-
error::{memory_error, no_block_given_error,
|
|
15
|
-
gvl
|
|
14
|
+
error::{memory_error, no_block_given_error, wreq_error},
|
|
15
|
+
gvl,
|
|
16
16
|
header::Headers,
|
|
17
17
|
http::{StatusCode, Version},
|
|
18
18
|
rt,
|
|
@@ -64,7 +64,7 @@ impl Response {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/// Internal method to get the wreq::Response, optionally streaming the body.
|
|
67
|
-
fn response(&self, stream: bool) -> Result<wreq::Response, Error> {
|
|
67
|
+
fn response(&self, ruby: &Ruby, stream: bool) -> Result<wreq::Response, Error> {
|
|
68
68
|
let build_response = |body: wreq::Body| -> wreq::Response {
|
|
69
69
|
let mut response = HttpResponse::new(body);
|
|
70
70
|
*response.version_mut() = self.version.into_ffi();
|
|
@@ -81,8 +81,9 @@ impl Response {
|
|
|
81
81
|
Ok(build_response(body))
|
|
82
82
|
} else {
|
|
83
83
|
let bytes = rt::try_block_on(
|
|
84
|
+
ruby,
|
|
84
85
|
BodyExt::collect(body).map_ok(|buf| buf.to_bytes()),
|
|
85
|
-
|
|
86
|
+
wreq_error,
|
|
86
87
|
)?;
|
|
87
88
|
|
|
88
89
|
self.body
|
|
@@ -103,7 +104,7 @@ impl Response {
|
|
|
103
104
|
};
|
|
104
105
|
}
|
|
105
106
|
|
|
106
|
-
Err(memory_error())
|
|
107
|
+
Err(memory_error(ruby))
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
|
|
@@ -167,44 +168,42 @@ impl Response {
|
|
|
167
168
|
}
|
|
168
169
|
|
|
169
170
|
/// Get the response body as bytes.
|
|
170
|
-
pub fn bytes(&
|
|
171
|
-
let response =
|
|
172
|
-
rt::try_block_on(response.bytes(),
|
|
171
|
+
pub fn bytes(ruby: &Ruby, rb_self: &Self) -> Result<Bytes, Error> {
|
|
172
|
+
let response = rb_self.response(ruby, false)?;
|
|
173
|
+
rt::try_block_on(ruby, response.bytes(), wreq_error)
|
|
173
174
|
}
|
|
174
175
|
|
|
175
176
|
/// Get the full response text given a specific encoding.
|
|
176
|
-
pub fn text(&
|
|
177
|
+
pub fn text(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<String, Error> {
|
|
177
178
|
let args = scan_args::<(), (Option<String>,), (), (), (), ()>(args)?;
|
|
178
|
-
let response =
|
|
179
|
+
let response = rb_self.response(ruby, false)?;
|
|
179
180
|
match args.optional.0 {
|
|
180
181
|
Some(encoding) => {
|
|
181
|
-
rt::try_block_on(response.text_with_charset(encoding),
|
|
182
|
+
rt::try_block_on(ruby, response.text_with_charset(encoding), wreq_error)
|
|
182
183
|
}
|
|
183
|
-
None => rt::try_block_on(response.text(),
|
|
184
|
+
None => rt::try_block_on(ruby, response.text(), wreq_error),
|
|
184
185
|
}
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
/// Get the response body as JSON.
|
|
188
189
|
pub fn json(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
189
|
-
let response = rb_self.response(false)?;
|
|
190
|
-
let json = rt::try_block_on(response.json::<Json>(),
|
|
191
|
-
|
|
190
|
+
let response = rb_self.response(ruby, false)?;
|
|
191
|
+
let json = rt::try_block_on(ruby, response.json::<Json>(), wreq_error)?;
|
|
192
|
+
crate::serde::serialize(ruby, &json)
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
/// Yield response body chunks to the given Ruby block.
|
|
195
196
|
pub fn chunks(ruby: &Ruby, rb_self: &Self) -> Result<(), Error> {
|
|
196
197
|
if !ruby.block_given() {
|
|
197
|
-
return Err(no_block_given_error());
|
|
198
|
+
return Err(no_block_given_error(ruby));
|
|
198
199
|
}
|
|
199
200
|
|
|
200
|
-
let receiver =
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
.map(BodyReceiver::new)
|
|
205
|
-
})?;
|
|
201
|
+
let receiver = rb_self
|
|
202
|
+
.response(ruby, true)
|
|
203
|
+
.map(wreq::Response::bytes_stream)
|
|
204
|
+
.map(BodyReceiver::new)?;
|
|
206
205
|
|
|
207
|
-
while let Some(chunk) = receiver.next()? {
|
|
206
|
+
while let Some(chunk) = receiver.next(ruby)? {
|
|
208
207
|
let _: Value = ruby.yield_value(chunk)?;
|
|
209
208
|
}
|
|
210
209
|
|