wreq 1.2.12 → 1.2.13
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 +1 -1
- data/Cargo.toml +1 -1
- data/docs/fork-safety.md +49 -32
- data/docs/interrupt-handling.md +4 -3
- data/lib/wreq.rb +36 -12
- data/lib/wreq_ruby/body.rb +9 -6
- data/lib/wreq_ruby/client.rb +18 -14
- data/lib/wreq_ruby/cookie.rb +9 -0
- data/lib/wreq_ruby/error.rb +7 -5
- data/lib/wreq_ruby/response.rb +23 -7
- data/src/arch.rs +83 -37
- data/src/client/body/stream.rs +15 -24
- data/src/client/req.rs +119 -122
- data/src/client/resp.rs +101 -55
- data/src/client.rs +78 -36
- data/src/cookie.rs +47 -11
- data/src/error.rs +1 -1
- data/src/lib.rs +0 -2
- data/src/macros.rs +0 -1
- data/src/rt.rs +20 -36
- data/test/fork_test.rb +30 -6
- data/test/scripts/fork_safety.rb +66 -43
- data/test/scripts/prefork_runtime.rb +95 -0
- metadata +2 -1
data/src/client/resp.rs
CHANGED
|
@@ -22,7 +22,10 @@ use crate::{
|
|
|
22
22
|
|
|
23
23
|
/// A response from a request.
|
|
24
24
|
#[magnus::wrap(class = "Wreq::Response", free_immediately, size)]
|
|
25
|
-
pub struct Response
|
|
25
|
+
pub struct Response(ProcessLocal<ResponseInner>);
|
|
26
|
+
|
|
27
|
+
/// Inner response state owned by the process that received it.
|
|
28
|
+
struct ResponseInner {
|
|
26
29
|
uri: Uri,
|
|
27
30
|
version: Version,
|
|
28
31
|
status: StatusCode,
|
|
@@ -30,7 +33,8 @@ pub struct Response {
|
|
|
30
33
|
headers: HeaderMap,
|
|
31
34
|
local_addr: Option<SocketAddr>,
|
|
32
35
|
remote_addr: Option<SocketAddr>,
|
|
33
|
-
|
|
36
|
+
body: ArcSwapOption<Body>,
|
|
37
|
+
extensions: Extensions,
|
|
34
38
|
}
|
|
35
39
|
|
|
36
40
|
/// Represents the state of the HTTP response body.
|
|
@@ -41,12 +45,6 @@ enum Body {
|
|
|
41
45
|
Reusable(Bytes),
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
/// Response state that may contain handles owned by the native runtime.
|
|
45
|
-
struct NativeResponseState {
|
|
46
|
-
body: ArcSwapOption<Body>,
|
|
47
|
-
extensions: Extensions,
|
|
48
|
-
}
|
|
49
|
-
|
|
50
48
|
impl Response {
|
|
51
49
|
/// Create a new [`Response`] instance.
|
|
52
50
|
pub fn new(response: wreq::Response) -> Self {
|
|
@@ -57,7 +55,7 @@ impl Response {
|
|
|
57
55
|
let response = HttpResponse::from(response);
|
|
58
56
|
let (parts, body) = response.into_parts();
|
|
59
57
|
|
|
60
|
-
Response {
|
|
58
|
+
Response(ProcessLocal::new(ResponseInner {
|
|
61
59
|
uri,
|
|
62
60
|
local_addr,
|
|
63
61
|
remote_addr,
|
|
@@ -65,23 +63,20 @@ impl Response {
|
|
|
65
63
|
version: Version::from_ffi(parts.version),
|
|
66
64
|
status: StatusCode::from(parts.status),
|
|
67
65
|
headers: parts.headers,
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}),
|
|
72
|
-
}
|
|
66
|
+
body: ArcSwapOption::from_pointee(Body::Streamable(body)),
|
|
67
|
+
extensions: parts.extensions,
|
|
68
|
+
}))
|
|
73
69
|
}
|
|
74
70
|
|
|
75
71
|
/// Internal method to get the wreq::Response, optionally streaming the body.
|
|
76
72
|
fn response(&self, ruby: &Ruby, stream: bool) -> Result<wreq::Response, Error> {
|
|
77
|
-
|
|
78
|
-
let state = self.state.as_ref();
|
|
73
|
+
let state = self.0.get(ruby)?;
|
|
79
74
|
|
|
80
75
|
let build_response = |body: wreq::Body| -> wreq::Response {
|
|
81
76
|
let mut response = HttpResponse::new(body);
|
|
82
|
-
*response.version_mut() =
|
|
83
|
-
*response.status_mut() =
|
|
84
|
-
*response.headers_mut() =
|
|
77
|
+
*response.version_mut() = state.version.into_ffi();
|
|
78
|
+
*response.status_mut() = state.status.0;
|
|
79
|
+
*response.headers_mut() = state.headers.clone();
|
|
85
80
|
*response.extensions_mut() = state.extensions.clone();
|
|
86
81
|
wreq::Response::from(response)
|
|
87
82
|
};
|
|
@@ -92,11 +87,11 @@ impl Response {
|
|
|
92
87
|
return if stream {
|
|
93
88
|
Ok(build_response(body))
|
|
94
89
|
} else {
|
|
95
|
-
let bytes = rt::
|
|
90
|
+
let bytes = rt::block_on(
|
|
96
91
|
ruby,
|
|
97
92
|
BodyExt::collect(body).map_ok(|buf| buf.to_bytes()),
|
|
98
|
-
|
|
99
|
-
)?;
|
|
93
|
+
)?
|
|
94
|
+
.map_err(|err| wreq_error(ruby, err))?;
|
|
100
95
|
|
|
101
96
|
state
|
|
102
97
|
.body
|
|
@@ -124,38 +119,66 @@ impl Response {
|
|
|
124
119
|
|
|
125
120
|
impl Response {
|
|
126
121
|
/// Get the response status code as a u16.
|
|
122
|
+
///
|
|
123
|
+
/// # Errors
|
|
124
|
+
///
|
|
125
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
127
126
|
#[inline]
|
|
128
|
-
pub fn code(&
|
|
129
|
-
|
|
127
|
+
pub fn code(ruby: &Ruby, rb_self: &Self) -> Result<u16, Error> {
|
|
128
|
+
rb_self
|
|
129
|
+
.0
|
|
130
|
+
.get(ruby)
|
|
131
|
+
.map(|response| response.status.0.as_u16())
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
/// Get the response status code.
|
|
135
|
+
///
|
|
136
|
+
/// # Errors
|
|
137
|
+
///
|
|
138
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
133
139
|
#[inline]
|
|
134
|
-
pub fn status(&
|
|
135
|
-
|
|
140
|
+
pub fn status(ruby: &Ruby, rb_self: &Self) -> Result<StatusCode, Error> {
|
|
141
|
+
rb_self.0.get(ruby).map(|response| response.status)
|
|
136
142
|
}
|
|
137
143
|
|
|
138
144
|
/// Get the response HTTP version.
|
|
145
|
+
///
|
|
146
|
+
/// # Errors
|
|
147
|
+
///
|
|
148
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
139
149
|
#[inline]
|
|
140
|
-
pub fn version(&
|
|
141
|
-
|
|
150
|
+
pub fn version(ruby: &Ruby, rb_self: &Self) -> Result<Version, Error> {
|
|
151
|
+
rb_self.0.get(ruby).map(|response| response.version)
|
|
142
152
|
}
|
|
143
153
|
|
|
144
154
|
/// Get the response URL.
|
|
155
|
+
///
|
|
156
|
+
/// # Errors
|
|
157
|
+
///
|
|
158
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
145
159
|
#[inline]
|
|
146
|
-
pub fn url(&
|
|
147
|
-
|
|
160
|
+
pub fn url(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
|
|
161
|
+
rb_self.0.get(ruby).map(|response| response.uri.to_string())
|
|
148
162
|
}
|
|
149
163
|
|
|
150
164
|
/// Get the content length of the response, if known.
|
|
165
|
+
///
|
|
166
|
+
/// # Errors
|
|
167
|
+
///
|
|
168
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
151
169
|
#[inline]
|
|
152
|
-
pub fn content_length(&
|
|
153
|
-
|
|
170
|
+
pub fn content_length(ruby: &Ruby, rb_self: &Self) -> Result<Option<u64>, Error> {
|
|
171
|
+
rb_self.0.get(ruby).map(|response| response.content_length)
|
|
154
172
|
}
|
|
155
173
|
|
|
156
174
|
/// Get the response cookies.
|
|
175
|
+
///
|
|
176
|
+
/// # Errors
|
|
177
|
+
///
|
|
178
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
157
179
|
pub fn cookies(ruby: &Ruby, rb_self: &Self) -> Result<RArray, Error> {
|
|
158
|
-
let
|
|
180
|
+
let response = rb_self.0.get(ruby)?;
|
|
181
|
+
let cookies = Cookie::extract_headers_cookies(&response.headers);
|
|
159
182
|
let ary = ruby.ary_new_capa(cookies.len());
|
|
160
183
|
for cookie in cookies {
|
|
161
184
|
ary.push(cookie)?;
|
|
@@ -164,63 +187,86 @@ impl Response {
|
|
|
164
187
|
}
|
|
165
188
|
|
|
166
189
|
/// Get the response headers.
|
|
190
|
+
///
|
|
191
|
+
/// # Errors
|
|
192
|
+
///
|
|
193
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
167
194
|
#[inline]
|
|
168
|
-
pub fn headers(&
|
|
169
|
-
|
|
195
|
+
pub fn headers(ruby: &Ruby, rb_self: &Self) -> Result<Headers, Error> {
|
|
196
|
+
rb_self
|
|
197
|
+
.0
|
|
198
|
+
.get(ruby)
|
|
199
|
+
.map(|response| Headers::from(response.headers.clone()))
|
|
170
200
|
}
|
|
171
201
|
|
|
172
202
|
/// Get the local socket address, if available.
|
|
203
|
+
///
|
|
204
|
+
/// # Errors
|
|
205
|
+
///
|
|
206
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
173
207
|
#[inline]
|
|
174
|
-
pub fn local_addr(&
|
|
175
|
-
|
|
208
|
+
pub fn local_addr(ruby: &Ruby, rb_self: &Self) -> Result<Option<String>, Error> {
|
|
209
|
+
rb_self
|
|
210
|
+
.0
|
|
211
|
+
.get(ruby)
|
|
212
|
+
.map(|response| response.local_addr.map(|addr| addr.to_string()))
|
|
176
213
|
}
|
|
177
214
|
|
|
178
215
|
/// Get the remote socket address, if available.
|
|
216
|
+
///
|
|
217
|
+
/// # Errors
|
|
218
|
+
///
|
|
219
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
179
220
|
#[inline]
|
|
180
|
-
pub fn remote_addr(&
|
|
181
|
-
|
|
221
|
+
pub fn remote_addr(ruby: &Ruby, rb_self: &Self) -> Result<Option<String>, Error> {
|
|
222
|
+
rb_self
|
|
223
|
+
.0
|
|
224
|
+
.get(ruby)
|
|
225
|
+
.map(|response| response.remote_addr.map(|addr| addr.to_string()))
|
|
182
226
|
}
|
|
183
227
|
|
|
184
228
|
/// Return peer certificate data retained for this response.
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
229
|
+
///
|
|
230
|
+
/// # Errors
|
|
231
|
+
///
|
|
232
|
+
/// Returns `Wreq::ForkError` when the response belongs to a parent process.
|
|
233
|
+
fn tls_info(ruby: &Ruby, rb_self: &Self) -> Result<Option<TlsInfo>, Error> {
|
|
234
|
+
Ok(rb_self
|
|
235
|
+
.0
|
|
236
|
+
.get(ruby)?
|
|
188
237
|
.extensions
|
|
189
238
|
.get::<wreq::tls::TlsInfo>()
|
|
190
239
|
.cloned()
|
|
191
|
-
.map(TlsInfo)
|
|
240
|
+
.map(TlsInfo))
|
|
192
241
|
}
|
|
193
242
|
|
|
194
243
|
/// Get the response body as bytes.
|
|
195
244
|
pub fn bytes(ruby: &Ruby, rb_self: &Self) -> Result<Bytes, Error> {
|
|
196
245
|
let response = rb_self.response(ruby, false)?;
|
|
197
|
-
rt::
|
|
246
|
+
rt::block_on(ruby, response.bytes())?.map_err(|err| wreq_error(ruby, err))
|
|
198
247
|
}
|
|
199
248
|
|
|
200
249
|
/// Get the full response text given a specific encoding.
|
|
201
250
|
pub fn text(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<String, Error> {
|
|
202
|
-
rt::ensure_current(ruby)?;
|
|
203
251
|
let args = scan_args::<(), (Option<String>,), (), (), (), ()>(args)?;
|
|
204
252
|
let response = rb_self.response(ruby, false)?;
|
|
205
253
|
match args.optional.0 {
|
|
206
|
-
Some(encoding) =>
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
None => rt::try_block_on(ruby, response.text(), wreq_error),
|
|
254
|
+
Some(encoding) => rt::block_on(ruby, response.text_with_charset(encoding))?
|
|
255
|
+
.map_err(|err| wreq_error(ruby, err)),
|
|
256
|
+
None => rt::block_on(ruby, response.text())?.map_err(|err| wreq_error(ruby, err)),
|
|
210
257
|
}
|
|
211
258
|
}
|
|
212
259
|
|
|
213
260
|
/// Get the response body as JSON.
|
|
214
261
|
pub fn json(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
215
262
|
let response = rb_self.response(ruby, false)?;
|
|
216
|
-
let json =
|
|
263
|
+
let json =
|
|
264
|
+
rt::block_on(ruby, response.json::<Json>())?.map_err(|err| wreq_error(ruby, err))?;
|
|
217
265
|
crate::serde::serialize(ruby, &json)
|
|
218
266
|
}
|
|
219
267
|
|
|
220
268
|
/// Yield response body chunks to the given Ruby block.
|
|
221
269
|
pub fn chunks(ruby: &Ruby, rb_self: &Self) -> Result<(), Error> {
|
|
222
|
-
rt::ensure_current(ruby)?;
|
|
223
|
-
|
|
224
270
|
if !ruby.block_given() {
|
|
225
271
|
return Err(no_block_given_error(ruby));
|
|
226
272
|
}
|
|
@@ -241,11 +287,11 @@ impl Response {
|
|
|
241
287
|
///
|
|
242
288
|
/// # Errors
|
|
243
289
|
///
|
|
244
|
-
/// Returns `Wreq::ForkError` before touching a
|
|
290
|
+
/// Returns `Wreq::ForkError` before touching a response inherited from the
|
|
245
291
|
/// parent process.
|
|
246
292
|
pub fn close(ruby: &Ruby, rb_self: &Self) -> Result<(), Error> {
|
|
247
|
-
|
|
248
|
-
gvl::nogvl(||
|
|
293
|
+
let response = rb_self.0.get(ruby)?;
|
|
294
|
+
gvl::nogvl(|| response.body.swap(None));
|
|
249
295
|
Ok(())
|
|
250
296
|
}
|
|
251
297
|
}
|
data/src/client.rs
CHANGED
|
@@ -21,7 +21,6 @@ use crate::{
|
|
|
21
21
|
header::{Headers, OrigHeaders, UserAgent},
|
|
22
22
|
http::Method,
|
|
23
23
|
options::{NativeOption, Options},
|
|
24
|
-
rt,
|
|
25
24
|
};
|
|
26
25
|
|
|
27
26
|
/// A builder for `Client`.
|
|
@@ -51,7 +50,7 @@ struct Builder {
|
|
|
51
50
|
cookie_store: Option<bool>,
|
|
52
51
|
/// Whether to use cookie store provider.
|
|
53
52
|
#[serde(default)]
|
|
54
|
-
cookie_provider: NativeOption<Jar
|
|
53
|
+
cookie_provider: NativeOption<Obj<Jar>>,
|
|
55
54
|
|
|
56
55
|
// ========= Timeout options =========
|
|
57
56
|
/// The timeout to use for the client. (in seconds)
|
|
@@ -121,7 +120,6 @@ struct Builder {
|
|
|
121
120
|
zstd: Option<bool>,
|
|
122
121
|
}
|
|
123
122
|
|
|
124
|
-
#[derive(Clone)]
|
|
125
123
|
#[magnus::wrap(class = "Wreq::Client", free_immediately, size)]
|
|
126
124
|
pub struct Client(ProcessLocal<wreq::Client>);
|
|
127
125
|
|
|
@@ -171,12 +169,7 @@ impl Builder {
|
|
|
171
169
|
extract_native_option!(options, builder, user_agent);
|
|
172
170
|
extract_native_option!(options, builder, headers);
|
|
173
171
|
extract_native_option!(options, builder, orig_headers);
|
|
174
|
-
extract_native_option!(
|
|
175
|
-
options,
|
|
176
|
-
builder,
|
|
177
|
-
cookie_provider,
|
|
178
|
-
Obj<Jar> => |value| (*value).clone()
|
|
179
|
-
);
|
|
172
|
+
extract_native_option!(options, builder, cookie_provider);
|
|
180
173
|
builder
|
|
181
174
|
.proxy
|
|
182
175
|
.set(Extractor::<Proxy>::try_convert(options.as_value())?.into_inner());
|
|
@@ -193,11 +186,9 @@ impl Client {
|
|
|
193
186
|
/// # Errors
|
|
194
187
|
///
|
|
195
188
|
/// Returns Ruby configuration errors from [`Builder::from_options`] or the
|
|
196
|
-
/// native fallible client builder.
|
|
197
|
-
/// `ArgumentError`.
|
|
189
|
+
/// native fallible client builder. An inherited cookie provider returns
|
|
190
|
+
/// `Wreq::ForkError`, and extra positional arguments return `ArgumentError`.
|
|
198
191
|
pub fn new(ruby: &Ruby, args: &[Value]) -> Result<Self, magnus::Error> {
|
|
199
|
-
rt::ensure_current(ruby)?;
|
|
200
|
-
|
|
201
192
|
Options::from_args(ruby, args, "client")?
|
|
202
193
|
.map(Builder::from_options)
|
|
203
194
|
.transpose()
|
|
@@ -221,12 +212,15 @@ impl Client {
|
|
|
221
212
|
///
|
|
222
213
|
/// # Errors
|
|
223
214
|
///
|
|
224
|
-
/// Returns `Wreq::ForkError`
|
|
225
|
-
///
|
|
226
|
-
///
|
|
215
|
+
/// Returns `Wreq::ForkError` if the cookie provider belongs to a parent
|
|
216
|
+
/// process. Native build failures are mapped only after the GVL has been
|
|
217
|
+
/// reacquired.
|
|
227
218
|
fn build(ruby: &Ruby, mut params: Builder) -> Result<wreq::Client, magnus::Error> {
|
|
228
|
-
|
|
229
|
-
|
|
219
|
+
let mut cookie_provider = params
|
|
220
|
+
.cookie_provider
|
|
221
|
+
.take()
|
|
222
|
+
.map(|jar| jar.clone_store(ruby))
|
|
223
|
+
.transpose()?;
|
|
230
224
|
let result = gvl::nogvl(|| {
|
|
231
225
|
let mut builder = wreq::Client::builder();
|
|
232
226
|
|
|
@@ -270,12 +264,7 @@ impl Client {
|
|
|
270
264
|
|
|
271
265
|
// Cookie options.
|
|
272
266
|
apply_option!(set_if_some, builder, params.cookie_store, cookie_store);
|
|
273
|
-
apply_option!(
|
|
274
|
-
set_if_some_inner,
|
|
275
|
-
builder,
|
|
276
|
-
params.cookie_provider,
|
|
277
|
-
cookie_provider
|
|
278
|
-
);
|
|
267
|
+
apply_option!(set_if_some, builder, cookie_provider, cookie_provider);
|
|
279
268
|
|
|
280
269
|
// TCP options.
|
|
281
270
|
apply_option!(
|
|
@@ -393,9 +382,14 @@ impl Client {
|
|
|
393
382
|
result.map_err(|err| wreq_error(ruby, err))
|
|
394
383
|
}
|
|
395
384
|
|
|
396
|
-
/// Clone the native client handle
|
|
397
|
-
|
|
398
|
-
|
|
385
|
+
/// Clone the native client handle in the process that created it.
|
|
386
|
+
///
|
|
387
|
+
/// # Errors
|
|
388
|
+
///
|
|
389
|
+
/// Returns `Wreq::ForkError` when the client was inherited from a parent
|
|
390
|
+
/// process.
|
|
391
|
+
fn native_client(&self, ruby: &Ruby) -> Result<wreq::Client, magnus::Error> {
|
|
392
|
+
self.0.get(ruby).cloned()
|
|
399
393
|
}
|
|
400
394
|
}
|
|
401
395
|
|
|
@@ -431,63 +425,111 @@ impl Client {
|
|
|
431
425
|
#[inline]
|
|
432
426
|
pub fn request(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
433
427
|
let ((method, url), request) = extract_request!(ruby, args, (Obj<Method>, String));
|
|
434
|
-
execute_request(ruby, rb_self.native_client()
|
|
428
|
+
execute_request(ruby, rb_self.native_client(ruby)?, *method, url, request)
|
|
435
429
|
}
|
|
436
430
|
|
|
437
431
|
/// Send a GET request.
|
|
438
432
|
#[inline]
|
|
439
433
|
pub fn get(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
440
434
|
let ((url,), request) = extract_request!(ruby, args, (String,));
|
|
441
|
-
execute_request(
|
|
435
|
+
execute_request(
|
|
436
|
+
ruby,
|
|
437
|
+
rb_self.native_client(ruby)?,
|
|
438
|
+
Method::GET,
|
|
439
|
+
url,
|
|
440
|
+
request,
|
|
441
|
+
)
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
/// Send a POST request.
|
|
445
445
|
#[inline]
|
|
446
446
|
pub fn post(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
447
447
|
let ((url,), request) = extract_request!(ruby, args, (String,));
|
|
448
|
-
execute_request(
|
|
448
|
+
execute_request(
|
|
449
|
+
ruby,
|
|
450
|
+
rb_self.native_client(ruby)?,
|
|
451
|
+
Method::POST,
|
|
452
|
+
url,
|
|
453
|
+
request,
|
|
454
|
+
)
|
|
449
455
|
}
|
|
450
456
|
|
|
451
457
|
/// Send a PUT request.
|
|
452
458
|
#[inline]
|
|
453
459
|
pub fn put(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
454
460
|
let ((url,), request) = extract_request!(ruby, args, (String,));
|
|
455
|
-
execute_request(
|
|
461
|
+
execute_request(
|
|
462
|
+
ruby,
|
|
463
|
+
rb_self.native_client(ruby)?,
|
|
464
|
+
Method::PUT,
|
|
465
|
+
url,
|
|
466
|
+
request,
|
|
467
|
+
)
|
|
456
468
|
}
|
|
457
469
|
|
|
458
470
|
/// Send a DELETE request.
|
|
459
471
|
#[inline]
|
|
460
472
|
pub fn delete(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
461
473
|
let ((url,), request) = extract_request!(ruby, args, (String,));
|
|
462
|
-
execute_request(
|
|
474
|
+
execute_request(
|
|
475
|
+
ruby,
|
|
476
|
+
rb_self.native_client(ruby)?,
|
|
477
|
+
Method::DELETE,
|
|
478
|
+
url,
|
|
479
|
+
request,
|
|
480
|
+
)
|
|
463
481
|
}
|
|
464
482
|
|
|
465
483
|
/// Send a HEAD request.
|
|
466
484
|
#[inline]
|
|
467
485
|
pub fn head(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
468
486
|
let ((url,), request) = extract_request!(ruby, args, (String,));
|
|
469
|
-
execute_request(
|
|
487
|
+
execute_request(
|
|
488
|
+
ruby,
|
|
489
|
+
rb_self.native_client(ruby)?,
|
|
490
|
+
Method::HEAD,
|
|
491
|
+
url,
|
|
492
|
+
request,
|
|
493
|
+
)
|
|
470
494
|
}
|
|
471
495
|
|
|
472
496
|
/// Send an OPTIONS request.
|
|
473
497
|
#[inline]
|
|
474
498
|
pub fn options(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
475
499
|
let ((url,), request) = extract_request!(ruby, args, (String,));
|
|
476
|
-
execute_request(
|
|
500
|
+
execute_request(
|
|
501
|
+
ruby,
|
|
502
|
+
rb_self.native_client(ruby)?,
|
|
503
|
+
Method::OPTIONS,
|
|
504
|
+
url,
|
|
505
|
+
request,
|
|
506
|
+
)
|
|
477
507
|
}
|
|
478
508
|
|
|
479
509
|
/// Send a TRACE request.
|
|
480
510
|
#[inline]
|
|
481
511
|
pub fn trace(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
482
512
|
let ((url,), request) = extract_request!(ruby, args, (String,));
|
|
483
|
-
execute_request(
|
|
513
|
+
execute_request(
|
|
514
|
+
ruby,
|
|
515
|
+
rb_self.native_client(ruby)?,
|
|
516
|
+
Method::TRACE,
|
|
517
|
+
url,
|
|
518
|
+
request,
|
|
519
|
+
)
|
|
484
520
|
}
|
|
485
521
|
|
|
486
522
|
/// Send a PATCH request.
|
|
487
523
|
#[inline]
|
|
488
524
|
pub fn patch(ruby: &Ruby, rb_self: &Self, args: &[Value]) -> Result<Response, magnus::Error> {
|
|
489
525
|
let ((url,), request) = extract_request!(ruby, args, (String,));
|
|
490
|
-
execute_request(
|
|
526
|
+
execute_request(
|
|
527
|
+
ruby,
|
|
528
|
+
rb_self.native_client(ruby)?,
|
|
529
|
+
Method::PATCH,
|
|
530
|
+
url,
|
|
531
|
+
request,
|
|
532
|
+
)
|
|
491
533
|
}
|
|
492
534
|
}
|
|
493
535
|
|
data/src/cookie.rs
CHANGED
|
@@ -18,6 +18,7 @@ use magnus::{
|
|
|
18
18
|
use wreq::header::{self, HeaderMap, HeaderValue};
|
|
19
19
|
|
|
20
20
|
use crate::{
|
|
21
|
+
arch::ProcessLocal,
|
|
21
22
|
error::{header_value_error, type_error},
|
|
22
23
|
gvl,
|
|
23
24
|
options::{NativeOption, Options},
|
|
@@ -78,9 +79,14 @@ struct Builder {
|
|
|
78
79
|
/// A cookie jar that can be shared with a Ruby `Wreq::Client`.
|
|
79
80
|
///
|
|
80
81
|
/// Pass a populated jar as the client's `cookie_provider` option.
|
|
81
|
-
#[derive(Clone, Default)]
|
|
82
82
|
#[magnus::wrap(class = "Wreq::Jar", free_immediately, size)]
|
|
83
|
-
pub struct Jar(
|
|
83
|
+
pub struct Jar(ProcessLocal<Arc<wreq::cookie::Jar>>);
|
|
84
|
+
|
|
85
|
+
impl Default for Jar {
|
|
86
|
+
fn default() -> Self {
|
|
87
|
+
Self(ProcessLocal::new(Arc::new(wreq::cookie::Jar::default())))
|
|
88
|
+
}
|
|
89
|
+
}
|
|
84
90
|
|
|
85
91
|
// ===== impl Builder =====
|
|
86
92
|
|
|
@@ -309,13 +315,18 @@ impl TryConvert for Cookies {
|
|
|
309
315
|
impl Jar {
|
|
310
316
|
/// Create a new [`Jar`] with an empty cookie store.
|
|
311
317
|
pub fn new() -> Self {
|
|
312
|
-
Self
|
|
318
|
+
Self::default()
|
|
313
319
|
}
|
|
314
320
|
|
|
315
321
|
/// Get all cookies.
|
|
322
|
+
///
|
|
323
|
+
/// # Errors
|
|
324
|
+
///
|
|
325
|
+
/// Returns `Wreq::ForkError` when the jar belongs to a parent process.
|
|
316
326
|
pub fn get_all(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
|
|
317
327
|
let cookies: Vec<Cookie> = rb_self
|
|
318
328
|
.0
|
|
329
|
+
.get(ruby)?
|
|
319
330
|
.get_all()
|
|
320
331
|
.map(RawCookie::from)
|
|
321
332
|
.map(Cookie)
|
|
@@ -331,28 +342,53 @@ impl Jar {
|
|
|
331
342
|
///
|
|
332
343
|
/// # Errors
|
|
333
344
|
///
|
|
334
|
-
/// Returns `
|
|
345
|
+
/// Returns `Wreq::ForkError` when the jar belongs to a parent process, or
|
|
346
|
+
/// `TypeError` when `cookie` is neither a [`Cookie`] nor a String.
|
|
335
347
|
pub fn add(&self, cookie: Value, url: String) -> Result<(), Error> {
|
|
348
|
+
let ruby = Ruby::get_with(cookie);
|
|
349
|
+
let jar = self.0.get(&ruby)?;
|
|
350
|
+
|
|
336
351
|
if let Ok(cookie) = Obj::<Cookie>::try_convert(cookie) {
|
|
337
|
-
gvl::nogvl(||
|
|
352
|
+
gvl::nogvl(|| jar.add(cookie.clone_for_jar(), &url));
|
|
338
353
|
return Ok(());
|
|
339
354
|
}
|
|
340
355
|
|
|
341
|
-
let ruby = Ruby::get_with(cookie);
|
|
342
356
|
let cookie = String::try_convert(cookie)
|
|
343
357
|
.map_err(|_| type_error(&ruby, "cookie must be a Wreq::Cookie or String"))?;
|
|
344
|
-
gvl::nogvl(||
|
|
358
|
+
gvl::nogvl(|| jar.add(cookie.as_ref(), &url));
|
|
345
359
|
Ok(())
|
|
346
360
|
}
|
|
347
361
|
|
|
348
362
|
/// Remove a cookie from this jar by name and URL.
|
|
349
|
-
|
|
350
|
-
|
|
363
|
+
///
|
|
364
|
+
/// # Errors
|
|
365
|
+
///
|
|
366
|
+
/// Returns `Wreq::ForkError` when the jar belongs to a parent process.
|
|
367
|
+
pub fn remove(ruby: &Ruby, rb_self: &Self, name: String, url: String) -> Result<(), Error> {
|
|
368
|
+
let jar = rb_self.0.get(ruby)?;
|
|
369
|
+
gvl::nogvl(|| jar.remove(name, &url));
|
|
370
|
+
Ok(())
|
|
351
371
|
}
|
|
352
372
|
|
|
353
373
|
/// Clear all cookies in this jar.
|
|
354
|
-
|
|
355
|
-
|
|
374
|
+
///
|
|
375
|
+
/// # Errors
|
|
376
|
+
///
|
|
377
|
+
/// Returns `Wreq::ForkError` when the jar belongs to a parent process.
|
|
378
|
+
pub fn clear(ruby: &Ruby, rb_self: &Self) -> Result<(), Error> {
|
|
379
|
+
let jar = rb_self.0.get(ruby)?;
|
|
380
|
+
gvl::nogvl(|| jar.clear());
|
|
381
|
+
Ok(())
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/// Clone the shared native store in the process that created this jar.
|
|
385
|
+
///
|
|
386
|
+
/// # Errors
|
|
387
|
+
///
|
|
388
|
+
/// Returns `Wreq::ForkError` when the jar was inherited from a parent
|
|
389
|
+
/// process.
|
|
390
|
+
pub(crate) fn clone_store(&self, ruby: &Ruby) -> Result<Arc<wreq::cookie::Jar>, Error> {
|
|
391
|
+
self.0.get(ruby).cloned()
|
|
356
392
|
}
|
|
357
393
|
}
|
|
358
394
|
|
data/src/error.rs
CHANGED
|
@@ -105,7 +105,7 @@ pub fn fork_error(ruby: &Ruby, owner_pid: u32, current_pid: u32) -> MagnusError
|
|
|
105
105
|
MagnusError::new(
|
|
106
106
|
ruby.get_inner(&FORK_ERROR),
|
|
107
107
|
format!(
|
|
108
|
-
"wreq-ruby was
|
|
108
|
+
"wreq-ruby native state was created in process {owner_pid} and cannot be used after fork in process {current_pid}"
|
|
109
109
|
),
|
|
110
110
|
)
|
|
111
111
|
}
|
data/src/lib.rs
CHANGED
data/src/macros.rs
CHANGED
|
@@ -149,7 +149,6 @@ macro_rules! define_ruby_enum {
|
|
|
149
149
|
|
|
150
150
|
macro_rules! extract_request {
|
|
151
151
|
($ruby:expr, $args:expr, $required:ty) => {{
|
|
152
|
-
crate::rt::ensure_current($ruby)?;
|
|
153
152
|
let args = magnus::scan_args::scan_args::<$required, (), (), (), magnus::RHash, ()>($args)?;
|
|
154
153
|
let required = args.required;
|
|
155
154
|
let request = crate::client::req::Request::new($ruby, args.keywords)?;
|