wreq 1.2.11 → 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.
data/src/client/req.rs CHANGED
@@ -184,131 +184,128 @@ pub fn execute_request<U: AsRef<str>>(
184
184
  url: U,
185
185
  mut request: Request,
186
186
  ) -> Result<Response, magnus::Error> {
187
- rt::try_block_on(
188
- ruby,
189
- async move {
190
- let mut builder = client.request(method.into_ffi(), url.as_ref());
191
-
192
- // Emulation options.
193
- apply_option!(set_if_some_inner, builder, request.emulation, emulation);
194
-
195
- // Version options.
196
- apply_option!(
197
- set_if_some_map,
198
- builder,
199
- request.version,
200
- version,
201
- Version::into_ffi
202
- );
203
-
204
- // Timeout options.
205
- apply_option!(
206
- set_if_some_map,
207
- builder,
208
- request.timeout,
209
- timeout,
210
- Duration::from_secs
211
- );
212
- apply_option!(
213
- set_if_some_map,
214
- builder,
215
- request.read_timeout,
216
- read_timeout,
217
- Duration::from_secs
218
- );
219
-
220
- // Network options.
221
- apply_option!(set_if_some, builder, request.proxy, proxy);
222
- apply_option!(set_if_some, builder, request.local_address, local_address);
223
- #[cfg(any(
224
- target_os = "android",
225
- target_os = "fuchsia",
226
- target_os = "illumos",
227
- target_os = "ios",
228
- target_os = "linux",
229
- target_os = "macos",
230
- target_os = "solaris",
231
- target_os = "tvos",
232
- target_os = "visionos",
233
- target_os = "watchos",
234
- ))]
235
- apply_option!(set_if_some, builder, request.interface, interface);
236
-
237
- // Headers options.
238
- apply_option!(set_if_some_into_inner, builder, request.headers, headers);
239
- apply_option!(
240
- set_if_some_inner,
241
- builder,
242
- request.orig_headers,
243
- orig_headers
244
- );
245
- apply_option!(
246
- set_if_some,
247
- builder,
248
- request.default_headers,
249
- default_headers
250
- );
251
-
252
- // Cookies options.
253
- if let Some(cookies) = request.cookies.take() {
254
- for cookie in cookies.0 {
255
- builder = builder.header(header::COOKIE, cookie);
256
- }
257
- }
187
+ rt::block_on(ruby, async move {
188
+ let mut builder = client.request(method.into_ffi(), url.as_ref());
189
+
190
+ // Emulation options.
191
+ apply_option!(set_if_some_inner, builder, request.emulation, emulation);
192
+
193
+ // Version options.
194
+ apply_option!(
195
+ set_if_some_map,
196
+ builder,
197
+ request.version,
198
+ version,
199
+ Version::into_ffi
200
+ );
201
+
202
+ // Timeout options.
203
+ apply_option!(
204
+ set_if_some_map,
205
+ builder,
206
+ request.timeout,
207
+ timeout,
208
+ Duration::from_secs
209
+ );
210
+ apply_option!(
211
+ set_if_some_map,
212
+ builder,
213
+ request.read_timeout,
214
+ read_timeout,
215
+ Duration::from_secs
216
+ );
258
217
 
259
- // Authentication options.
260
- apply_option!(
261
- set_if_some_map_ref,
262
- builder,
263
- request.auth,
264
- auth,
265
- AsRef::<str>::as_ref
266
- );
267
- apply_option!(set_if_some, builder, request.bearer_auth, bearer_auth);
268
- if let Some(basic_auth) = request.basic_auth.take() {
269
- builder = builder.basic_auth(basic_auth.0, basic_auth.1);
218
+ // Network options.
219
+ apply_option!(set_if_some, builder, request.proxy, proxy);
220
+ apply_option!(set_if_some, builder, request.local_address, local_address);
221
+ #[cfg(any(
222
+ target_os = "android",
223
+ target_os = "fuchsia",
224
+ target_os = "illumos",
225
+ target_os = "ios",
226
+ target_os = "linux",
227
+ target_os = "macos",
228
+ target_os = "solaris",
229
+ target_os = "tvos",
230
+ target_os = "visionos",
231
+ target_os = "watchos",
232
+ ))]
233
+ apply_option!(set_if_some, builder, request.interface, interface);
234
+
235
+ // Headers options.
236
+ apply_option!(set_if_some_into_inner, builder, request.headers, headers);
237
+ apply_option!(
238
+ set_if_some_inner,
239
+ builder,
240
+ request.orig_headers,
241
+ orig_headers
242
+ );
243
+ apply_option!(
244
+ set_if_some,
245
+ builder,
246
+ request.default_headers,
247
+ default_headers
248
+ );
249
+
250
+ // Cookies options.
251
+ if let Some(cookies) = request.cookies.take() {
252
+ for cookie in cookies.0 {
253
+ builder = builder.header(header::COOKIE, cookie);
270
254
  }
255
+ }
271
256
 
272
- // Allow redirects options.
273
- match request.allow_redirects {
274
- Some(false) => {
275
- builder = builder.redirect(wreq::redirect::Policy::none());
276
- }
277
- Some(true) => {
278
- builder = builder.redirect(
279
- request
280
- .max_redirects
281
- .take()
282
- .map(wreq::redirect::Policy::limited)
283
- .unwrap_or_default(),
284
- );
285
- }
286
- None => {}
287
- };
288
-
289
- // Compression options.
290
- apply_option!(set_if_some, builder, request.gzip, gzip);
291
- apply_option!(set_if_some, builder, request.brotli, brotli);
292
- apply_option!(set_if_some, builder, request.deflate, deflate);
293
- apply_option!(set_if_some, builder, request.zstd, zstd);
294
-
295
- // Query options.
296
- apply_option!(set_if_some_ref, builder, request.query, query);
297
-
298
- // Form options.
299
- apply_option!(set_if_some_ref, builder, request.form, form);
300
-
301
- // JSON options.
302
- apply_option!(set_if_some_ref, builder, request.json, json);
303
-
304
- // Body options.
305
- if let Some(body) = request.body.take() {
306
- builder = builder.body(wreq::Body::from(body));
257
+ // Authentication options.
258
+ apply_option!(
259
+ set_if_some_map_ref,
260
+ builder,
261
+ request.auth,
262
+ auth,
263
+ AsRef::<str>::as_ref
264
+ );
265
+ apply_option!(set_if_some, builder, request.bearer_auth, bearer_auth);
266
+ if let Some(basic_auth) = request.basic_auth.take() {
267
+ builder = builder.basic_auth(basic_auth.0, basic_auth.1);
268
+ }
269
+
270
+ // Allow redirects options.
271
+ match request.allow_redirects {
272
+ Some(false) => {
273
+ builder = builder.redirect(wreq::redirect::Policy::none());
274
+ }
275
+ Some(true) => {
276
+ builder = builder.redirect(
277
+ request
278
+ .max_redirects
279
+ .take()
280
+ .map(wreq::redirect::Policy::limited)
281
+ .unwrap_or_default(),
282
+ );
307
283
  }
284
+ None => {}
285
+ };
286
+
287
+ // Compression options.
288
+ apply_option!(set_if_some, builder, request.gzip, gzip);
289
+ apply_option!(set_if_some, builder, request.brotli, brotli);
290
+ apply_option!(set_if_some, builder, request.deflate, deflate);
291
+ apply_option!(set_if_some, builder, request.zstd, zstd);
292
+
293
+ // Query options.
294
+ apply_option!(set_if_some_ref, builder, request.query, query);
295
+
296
+ // Form options.
297
+ apply_option!(set_if_some_ref, builder, request.form, form);
298
+
299
+ // JSON options.
300
+ apply_option!(set_if_some_ref, builder, request.json, json);
301
+
302
+ // Body options.
303
+ if let Some(body) = request.body.take() {
304
+ builder = builder.body(wreq::Body::from(body));
305
+ }
308
306
 
309
- // Send request.
310
- builder.send().await.map(Response::new)
311
- },
312
- wreq_error,
313
- )
307
+ // Send request.
308
+ builder.send().await.map(Response::new)
309
+ })?
310
+ .map_err(|err| wreq_error(ruby, err))
314
311
  }
data/src/client/resp.rs CHANGED
@@ -9,6 +9,7 @@ use magnus::{Error, Module, RArray, RModule, Ruby, Value, scan_args::scan_args};
9
9
  use wreq::Uri;
10
10
 
11
11
  use crate::{
12
+ arch::ProcessLocal,
12
13
  client::body::{json::Json, stream::BodyReceiver},
13
14
  cookie::Cookie,
14
15
  error::{memory_error, no_block_given_error, wreq_error},
@@ -16,11 +17,15 @@ use crate::{
16
17
  header::Headers,
17
18
  http::{StatusCode, Version},
18
19
  rt,
20
+ tls::TlsInfo,
19
21
  };
20
22
 
21
23
  /// A response from a request.
22
24
  #[magnus::wrap(class = "Wreq::Response", free_immediately, size)]
23
- pub struct Response {
25
+ pub struct Response(ProcessLocal<ResponseInner>);
26
+
27
+ /// Inner response state owned by the process that received it.
28
+ struct ResponseInner {
24
29
  uri: Uri,
25
30
  version: Version,
26
31
  status: StatusCode,
@@ -50,50 +55,54 @@ impl Response {
50
55
  let response = HttpResponse::from(response);
51
56
  let (parts, body) = response.into_parts();
52
57
 
53
- Response {
58
+ Response(ProcessLocal::new(ResponseInner {
54
59
  uri,
55
60
  local_addr,
56
61
  remote_addr,
57
62
  content_length,
58
- extensions: parts.extensions,
59
63
  version: Version::from_ffi(parts.version),
60
64
  status: StatusCode::from(parts.status),
61
65
  headers: parts.headers,
62
66
  body: ArcSwapOption::from_pointee(Body::Streamable(body)),
63
- }
67
+ extensions: parts.extensions,
68
+ }))
64
69
  }
65
70
 
66
71
  /// Internal method to get the wreq::Response, optionally streaming the body.
67
72
  fn response(&self, ruby: &Ruby, stream: bool) -> Result<wreq::Response, Error> {
73
+ let state = self.0.get(ruby)?;
74
+
68
75
  let build_response = |body: wreq::Body| -> wreq::Response {
69
76
  let mut response = HttpResponse::new(body);
70
- *response.version_mut() = self.version.into_ffi();
71
- *response.status_mut() = self.status.0;
72
- *response.headers_mut() = self.headers.clone();
73
- *response.extensions_mut() = self.extensions.clone();
77
+ *response.version_mut() = state.version.into_ffi();
78
+ *response.status_mut() = state.status.0;
79
+ *response.headers_mut() = state.headers.clone();
80
+ *response.extensions_mut() = state.extensions.clone();
74
81
  wreq::Response::from(response)
75
82
  };
76
83
 
77
- if let Some(arc) = self.body.swap(None) {
84
+ if let Some(arc) = state.body.swap(None) {
78
85
  match Arc::try_unwrap(arc) {
79
86
  Ok(Body::Streamable(body)) => {
80
87
  return if stream {
81
88
  Ok(build_response(body))
82
89
  } else {
83
- let bytes = rt::try_block_on(
90
+ let bytes = rt::block_on(
84
91
  ruby,
85
92
  BodyExt::collect(body).map_ok(|buf| buf.to_bytes()),
86
- wreq_error,
87
- )?;
93
+ )?
94
+ .map_err(|err| wreq_error(ruby, err))?;
88
95
 
89
- self.body
96
+ state
97
+ .body
90
98
  .store(Some(Arc::new(Body::Reusable(bytes.clone()))));
91
99
 
92
100
  Ok(build_response(wreq::Body::from(bytes)))
93
101
  };
94
102
  }
95
103
  Ok(Body::Reusable(bytes)) => {
96
- self.body
104
+ state
105
+ .body
97
106
  .store(Some(Arc::new(Body::Reusable(bytes.clone()))));
98
107
 
99
108
  if !stream {
@@ -110,38 +119,66 @@ impl Response {
110
119
 
111
120
  impl Response {
112
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.
113
126
  #[inline]
114
- pub fn code(&self) -> u16 {
115
- self.status.0.as_u16()
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())
116
132
  }
117
133
 
118
134
  /// Get the response status code.
135
+ ///
136
+ /// # Errors
137
+ ///
138
+ /// Returns `Wreq::ForkError` when the response belongs to a parent process.
119
139
  #[inline]
120
- pub fn status(&self) -> StatusCode {
121
- self.status
140
+ pub fn status(ruby: &Ruby, rb_self: &Self) -> Result<StatusCode, Error> {
141
+ rb_self.0.get(ruby).map(|response| response.status)
122
142
  }
123
143
 
124
144
  /// Get the response HTTP version.
145
+ ///
146
+ /// # Errors
147
+ ///
148
+ /// Returns `Wreq::ForkError` when the response belongs to a parent process.
125
149
  #[inline]
126
- pub fn version(&self) -> Version {
127
- self.version
150
+ pub fn version(ruby: &Ruby, rb_self: &Self) -> Result<Version, Error> {
151
+ rb_self.0.get(ruby).map(|response| response.version)
128
152
  }
129
153
 
130
154
  /// Get the response URL.
155
+ ///
156
+ /// # Errors
157
+ ///
158
+ /// Returns `Wreq::ForkError` when the response belongs to a parent process.
131
159
  #[inline]
132
- pub fn url(&self) -> String {
133
- self.uri.to_string()
160
+ pub fn url(ruby: &Ruby, rb_self: &Self) -> Result<String, Error> {
161
+ rb_self.0.get(ruby).map(|response| response.uri.to_string())
134
162
  }
135
163
 
136
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.
137
169
  #[inline]
138
- pub fn content_length(&self) -> Option<u64> {
139
- self.content_length
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)
140
172
  }
141
173
 
142
174
  /// Get the response cookies.
175
+ ///
176
+ /// # Errors
177
+ ///
178
+ /// Returns `Wreq::ForkError` when the response belongs to a parent process.
143
179
  pub fn cookies(ruby: &Ruby, rb_self: &Self) -> Result<RArray, Error> {
144
- let cookies = Cookie::extract_headers_cookies(&rb_self.headers);
180
+ let response = rb_self.0.get(ruby)?;
181
+ let cookies = Cookie::extract_headers_cookies(&response.headers);
145
182
  let ary = ruby.ary_new_capa(cookies.len());
146
183
  for cookie in cookies {
147
184
  ary.push(cookie)?;
@@ -150,27 +187,63 @@ impl Response {
150
187
  }
151
188
 
152
189
  /// Get the response headers.
190
+ ///
191
+ /// # Errors
192
+ ///
193
+ /// Returns `Wreq::ForkError` when the response belongs to a parent process.
153
194
  #[inline]
154
- pub fn headers(&self) -> Headers {
155
- Headers::from(self.headers.clone())
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()))
156
200
  }
157
201
 
158
202
  /// Get the local socket address, if available.
203
+ ///
204
+ /// # Errors
205
+ ///
206
+ /// Returns `Wreq::ForkError` when the response belongs to a parent process.
159
207
  #[inline]
160
- pub fn local_addr(&self) -> Option<String> {
161
- self.local_addr.map(|addr| addr.to_string())
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()))
162
213
  }
163
214
 
164
215
  /// Get the remote socket address, if available.
216
+ ///
217
+ /// # Errors
218
+ ///
219
+ /// Returns `Wreq::ForkError` when the response belongs to a parent process.
165
220
  #[inline]
166
- pub fn remote_addr(&self) -> Option<String> {
167
- self.remote_addr.map(|addr| addr.to_string())
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()))
226
+ }
227
+
228
+ /// Return peer certificate data retained for this response.
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)?
237
+ .extensions
238
+ .get::<wreq::tls::TlsInfo>()
239
+ .cloned()
240
+ .map(TlsInfo))
168
241
  }
169
242
 
170
243
  /// Get the response body as bytes.
171
244
  pub fn bytes(ruby: &Ruby, rb_self: &Self) -> Result<Bytes, Error> {
172
245
  let response = rb_self.response(ruby, false)?;
173
- rt::try_block_on(ruby, response.bytes(), wreq_error)
246
+ rt::block_on(ruby, response.bytes())?.map_err(|err| wreq_error(ruby, err))
174
247
  }
175
248
 
176
249
  /// Get the full response text given a specific encoding.
@@ -178,17 +251,17 @@ impl Response {
178
251
  let args = scan_args::<(), (Option<String>,), (), (), (), ()>(args)?;
179
252
  let response = rb_self.response(ruby, false)?;
180
253
  match args.optional.0 {
181
- Some(encoding) => {
182
- rt::try_block_on(ruby, response.text_with_charset(encoding), wreq_error)
183
- }
184
- 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)),
185
257
  }
186
258
  }
187
259
 
188
260
  /// Get the response body as JSON.
189
261
  pub fn json(ruby: &Ruby, rb_self: &Self) -> Result<Value, Error> {
190
262
  let response = rb_self.response(ruby, false)?;
191
- let json = rt::try_block_on(ruby, response.json::<Json>(), wreq_error)?;
263
+ let json =
264
+ rt::block_on(ruby, response.json::<Json>())?.map_err(|err| wreq_error(ruby, err))?;
192
265
  crate::serde::serialize(ruby, &json)
193
266
  }
194
267
 
@@ -211,16 +284,15 @@ impl Response {
211
284
  }
212
285
 
213
286
  /// Close the response body, dropping any resources.
214
- #[inline]
215
- pub fn close(&self) {
216
- gvl::nogvl(|| self.body.swap(None));
217
- }
218
- }
219
-
220
- impl Drop for Response {
221
- fn drop(&mut self) {
222
- // Ensure body is dropped in GVL
223
- self.body.swap(None);
287
+ ///
288
+ /// # Errors
289
+ ///
290
+ /// Returns `Wreq::ForkError` before touching a response inherited from the
291
+ /// parent process.
292
+ pub fn close(ruby: &Ruby, rb_self: &Self) -> Result<(), Error> {
293
+ let response = rb_self.0.get(ruby)?;
294
+ gvl::nogvl(|| response.body.swap(None));
295
+ Ok(())
224
296
  }
225
297
  }
226
298
 
@@ -243,5 +315,6 @@ pub fn include(ruby: &Ruby, gem_module: &RModule) -> Result<(), Error> {
243
315
  response.define_method("json", magnus::method!(Response::json, 0))?;
244
316
  response.define_method("chunks", magnus::method!(Response::chunks, 0))?;
245
317
  response.define_method("close", magnus::method!(Response::close, 0))?;
318
+ response.define_method("tls_info", magnus::method!(Response::tls_info, 0))?;
246
319
  Ok(())
247
320
  }