wreq 1.2.0 → 1.2.1
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 +2 -2
- data/lib/wreq.rb +9 -9
- data/lib/wreq_ruby/client.rb +11 -9
- data/lib/wreq_ruby/http.rb +14 -0
- data/src/client/req.rs +25 -8
- data/src/client.rs +14 -9
- data/src/error.rs +8 -0
- data/src/extractor.rs +1 -22
- data/src/header.rs +24 -1
- data/src/http.rs +16 -1
- data/test/orig_header_test.rb +115 -0
- data/test/request_test.rb +10 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 15ad9f6cc6c41b23c065d2118942ce008260dd0b0ec0124e03d5d72379ed9dda
|
|
4
|
+
data.tar.gz: ef0c61872bffe6dc3e3e7e820d1d774f944d129a5e486e1c8fe50c53d06b4c5d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a2c870dd5fedc1dfd0c72de4b1567b63f9a44ce361a7f6e47a57bfe751ddf1c083a4828542f778236ce1bc2bc529e7b85df19ef33c742580a695df33ac114cd2
|
|
7
|
+
data.tar.gz: b2616fcfc85af1ac603ea330ca6f2c697aa81049d36471df4619327ad0d549af974078f14d4d3f76aee0e581ac8f8fed6d711778d64c8b82fad8c038cec3f14b
|
data/Cargo.lock
CHANGED
data/Cargo.toml
CHANGED
|
@@ -6,7 +6,7 @@ homepage = "https://github.com/SearchApi/wreq-ruby"
|
|
|
6
6
|
repository = "https://github.com/SearchApi/wreq-ruby"
|
|
7
7
|
edition = "2024"
|
|
8
8
|
rust-version = "1.85"
|
|
9
|
-
version = "1.2.
|
|
9
|
+
version = "1.2.1"
|
|
10
10
|
|
|
11
11
|
[lib]
|
|
12
12
|
crate-type = ["cdylib"]
|
|
@@ -38,7 +38,7 @@ indexmap = { version = "2.14.0", features = ["serde"] }
|
|
|
38
38
|
cookie = "0.18.1"
|
|
39
39
|
bytes = "1.11.1"
|
|
40
40
|
arc-swap = "1.9.1"
|
|
41
|
-
http = "1.4.
|
|
41
|
+
http = "1.4.1"
|
|
42
42
|
http-body-util = "0.1.3"
|
|
43
43
|
futures-util = { version = "0.3.32", default-features = false }
|
|
44
44
|
|
data/lib/wreq.rb
CHANGED
|
@@ -25,7 +25,7 @@ unless defined?(Wreq)
|
|
|
25
25
|
# @param method [Wreq::Method] HTTP method to use
|
|
26
26
|
# @param url [String] Target URL
|
|
27
27
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
28
|
-
# @param orig_headers [
|
|
28
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
29
29
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
30
30
|
# @param query [Hash, nil] URL query parameters
|
|
31
31
|
# @param auth [String, nil] Authorization header value
|
|
@@ -56,7 +56,7 @@ unless defined?(Wreq)
|
|
|
56
56
|
#
|
|
57
57
|
# @param url [String] Target URL
|
|
58
58
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
59
|
-
# @param orig_headers [
|
|
59
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
60
60
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
61
61
|
# @param query [Hash, nil] URL query parameters
|
|
62
62
|
# @param auth [String, nil] Authorization header value
|
|
@@ -87,7 +87,7 @@ unless defined?(Wreq)
|
|
|
87
87
|
#
|
|
88
88
|
# @param url [String] Target URL
|
|
89
89
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
90
|
-
# @param orig_headers [
|
|
90
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
91
91
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
92
92
|
# @param query [Hash, nil] URL query parameters
|
|
93
93
|
# @param auth [String, nil] Authorization header value
|
|
@@ -118,7 +118,7 @@ unless defined?(Wreq)
|
|
|
118
118
|
#
|
|
119
119
|
# @param url [String] Target URL
|
|
120
120
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
121
|
-
# @param orig_headers [
|
|
121
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
122
122
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
123
123
|
# @param query [Hash, nil] URL query parameters
|
|
124
124
|
# @param auth [String, nil] Authorization header value
|
|
@@ -149,7 +149,7 @@ unless defined?(Wreq)
|
|
|
149
149
|
#
|
|
150
150
|
# @param url [String] Target URL
|
|
151
151
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
152
|
-
# @param orig_headers [
|
|
152
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
153
153
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
154
154
|
# @param query [Hash, nil] URL query parameters
|
|
155
155
|
# @param auth [String, nil] Authorization header value
|
|
@@ -180,7 +180,7 @@ unless defined?(Wreq)
|
|
|
180
180
|
#
|
|
181
181
|
# @param url [String] Target URL
|
|
182
182
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
183
|
-
# @param orig_headers [
|
|
183
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
184
184
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
185
185
|
# @param query [Hash, nil] URL query parameters
|
|
186
186
|
# @param auth [String, nil] Authorization header value
|
|
@@ -211,7 +211,7 @@ unless defined?(Wreq)
|
|
|
211
211
|
#
|
|
212
212
|
# @param url [String] Target URL
|
|
213
213
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
214
|
-
# @param orig_headers [
|
|
214
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
215
215
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
216
216
|
# @param query [Hash, nil] URL query parameters
|
|
217
217
|
# @param auth [String, nil] Authorization header value
|
|
@@ -242,7 +242,7 @@ unless defined?(Wreq)
|
|
|
242
242
|
#
|
|
243
243
|
# @param url [String] Target URL
|
|
244
244
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
245
|
-
# @param orig_headers [
|
|
245
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
246
246
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
247
247
|
# @param query [Hash, nil] URL query parameters
|
|
248
248
|
# @param auth [String, nil] Authorization header value
|
|
@@ -273,7 +273,7 @@ unless defined?(Wreq)
|
|
|
273
273
|
#
|
|
274
274
|
# @param url [String] Target URL
|
|
275
275
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
276
|
-
# @param orig_headers [
|
|
276
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
277
277
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
278
278
|
# @param query [Hash, nil] URL query parameters
|
|
279
279
|
# @param auth [String, nil] Authorization header value
|
data/lib/wreq_ruby/client.rb
CHANGED
|
@@ -38,6 +38,8 @@ unless defined?(Wreq)
|
|
|
38
38
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Default headers to include
|
|
39
39
|
# in every request. Header names are case-insensitive. These headers
|
|
40
40
|
# can be overridden on a per-request basis.
|
|
41
|
+
# @param orig_headers [Array<String>, nil] Original header names used to
|
|
42
|
+
# preserve raw header order and HTTP/1 case-sensitive header handling.
|
|
41
43
|
#
|
|
42
44
|
# @param referer [Boolean, nil] Whether to automatically send Referer
|
|
43
45
|
# headers when following redirects. When true, the previous URL will
|
|
@@ -237,7 +239,7 @@ unless defined?(Wreq)
|
|
|
237
239
|
# @param method [Wreq::Method] HTTP method to use
|
|
238
240
|
# @param url [String] Target URL
|
|
239
241
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
240
|
-
# @param orig_headers [
|
|
242
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
241
243
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
242
244
|
# @param query [Hash, nil] URL query parameters
|
|
243
245
|
# @param auth [String, nil] Authorization header value
|
|
@@ -268,7 +270,7 @@ unless defined?(Wreq)
|
|
|
268
270
|
#
|
|
269
271
|
# @param url [String] Target URL
|
|
270
272
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
271
|
-
# @param orig_headers [
|
|
273
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
272
274
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
273
275
|
# @param query [Hash, nil] URL query parameters
|
|
274
276
|
# @param auth [String, nil] Authorization header value
|
|
@@ -299,7 +301,7 @@ unless defined?(Wreq)
|
|
|
299
301
|
#
|
|
300
302
|
# @param url [String] Target URL
|
|
301
303
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
302
|
-
# @param orig_headers [
|
|
304
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
303
305
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
304
306
|
# @param query [Hash, nil] URL query parameters
|
|
305
307
|
# @param auth [String, nil] Authorization header value
|
|
@@ -330,7 +332,7 @@ unless defined?(Wreq)
|
|
|
330
332
|
#
|
|
331
333
|
# @param url [String] Target URL
|
|
332
334
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
333
|
-
# @param orig_headers [
|
|
335
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
334
336
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
335
337
|
# @param query [Hash, nil] URL query parameters
|
|
336
338
|
# @param auth [String, nil] Authorization header value
|
|
@@ -361,7 +363,7 @@ unless defined?(Wreq)
|
|
|
361
363
|
#
|
|
362
364
|
# @param url [String] Target URL
|
|
363
365
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
364
|
-
# @param orig_headers [
|
|
366
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
365
367
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
366
368
|
# @param query [Hash, nil] URL query parameters
|
|
367
369
|
# @param auth [String, nil] Authorization header value
|
|
@@ -392,7 +394,7 @@ unless defined?(Wreq)
|
|
|
392
394
|
#
|
|
393
395
|
# @param url [String] Target URL
|
|
394
396
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
395
|
-
# @param orig_headers [
|
|
397
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
396
398
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
397
399
|
# @param query [Hash, nil] URL query parameters
|
|
398
400
|
# @param auth [String, nil] Authorization header value
|
|
@@ -423,7 +425,7 @@ unless defined?(Wreq)
|
|
|
423
425
|
#
|
|
424
426
|
# @param url [String] Target URL
|
|
425
427
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
426
|
-
# @param orig_headers [
|
|
428
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
427
429
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
428
430
|
# @param query [Hash, nil] URL query parameters
|
|
429
431
|
# @param auth [String, nil] Authorization header value
|
|
@@ -454,7 +456,7 @@ unless defined?(Wreq)
|
|
|
454
456
|
#
|
|
455
457
|
# @param url [String] Target URL
|
|
456
458
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
457
|
-
# @param orig_headers [
|
|
459
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
458
460
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
459
461
|
# @param query [Hash, nil] URL query parameters
|
|
460
462
|
# @param auth [String, nil] Authorization header value
|
|
@@ -485,7 +487,7 @@ unless defined?(Wreq)
|
|
|
485
487
|
#
|
|
486
488
|
# @param url [String] Target URL
|
|
487
489
|
# @param headers [Wreq::Headers, Hash{String=>String}, nil] Custom headers for this request
|
|
488
|
-
# @param orig_headers [
|
|
490
|
+
# @param orig_headers [Array<String>, nil] Original header names used to preserve raw header order and HTTP/1 case-sensitive header handling
|
|
489
491
|
# @param default_headers [Hash{String=>String}, nil] Default headers to merge
|
|
490
492
|
# @param query [Hash, nil] URL query parameters
|
|
491
493
|
# @param auth [String, nil] Authorization header value
|
data/lib/wreq_ruby/http.rb
CHANGED
|
@@ -49,6 +49,20 @@ module Wreq
|
|
|
49
49
|
def to_s
|
|
50
50
|
end
|
|
51
51
|
end
|
|
52
|
+
|
|
53
|
+
# Compares HTTP versions by semantic value, not object identity.
|
|
54
|
+
#
|
|
55
|
+
# This method is implemented by the native extension.
|
|
56
|
+
# When comparing with non-{Wreq::Version} objects, it returns false.
|
|
57
|
+
#
|
|
58
|
+
# @param other [Object] object to compare against
|
|
59
|
+
# @return [Boolean] true when both represent the same HTTP version
|
|
60
|
+
# @example
|
|
61
|
+
# Wreq::Version::HTTP_11 == response.version
|
|
62
|
+
unless method_defined?(:==)
|
|
63
|
+
def ==(other)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
52
66
|
end
|
|
53
67
|
|
|
54
68
|
# HTTP status code wrapper.
|
data/src/client/req.rs
CHANGED
|
@@ -3,7 +3,7 @@ use std::{net::IpAddr, time::Duration};
|
|
|
3
3
|
use http::header;
|
|
4
4
|
use magnus::{RHash, TryConvert, typed_data::Obj, value::ReprValue};
|
|
5
5
|
use serde::Deserialize;
|
|
6
|
-
use wreq::{Client, Proxy
|
|
6
|
+
use wreq::{Client, Proxy};
|
|
7
7
|
|
|
8
8
|
use super::body::{Body, Form, Json};
|
|
9
9
|
use crate::{
|
|
@@ -12,8 +12,8 @@ use crate::{
|
|
|
12
12
|
emulate::Emulation,
|
|
13
13
|
error::wreq_error_to_magnus,
|
|
14
14
|
extractor::Extractor,
|
|
15
|
-
header::Headers,
|
|
16
|
-
http::Method,
|
|
15
|
+
header::{Headers, OrigHeaders},
|
|
16
|
+
http::{Method, Version},
|
|
17
17
|
rt,
|
|
18
18
|
};
|
|
19
19
|
|
|
@@ -54,7 +54,7 @@ pub struct Request {
|
|
|
54
54
|
|
|
55
55
|
/// The original headers to use for the request.
|
|
56
56
|
#[serde(skip)]
|
|
57
|
-
orig_headers: Option<
|
|
57
|
+
orig_headers: Option<OrigHeaders>,
|
|
58
58
|
|
|
59
59
|
/// The cookies to use for the request.
|
|
60
60
|
#[serde(skip)]
|
|
@@ -112,10 +112,18 @@ impl Request {
|
|
|
112
112
|
builder.emulation = Some((*obj).clone());
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
+
if let Some(v) = hash.get(ruby.to_symbol(stringify!(version))) {
|
|
116
|
+
builder.version = Some(Version::try_convert(v)?);
|
|
117
|
+
}
|
|
118
|
+
|
|
115
119
|
if let Some(v) = hash.get(ruby.to_symbol(stringify!(headers))) {
|
|
116
120
|
builder.headers = Some(Headers::try_convert(v)?);
|
|
117
121
|
}
|
|
118
122
|
|
|
123
|
+
if let Some(v) = hash.get(ruby.to_symbol(stringify!(orig_headers))) {
|
|
124
|
+
builder.orig_headers = Some(OrigHeaders::try_convert(v)?);
|
|
125
|
+
}
|
|
126
|
+
|
|
119
127
|
if let Some(v) = hash.get(ruby.to_symbol(stringify!(cookies))) {
|
|
120
128
|
builder.cookies = Some(Cookies::try_convert(v)?);
|
|
121
129
|
}
|
|
@@ -125,8 +133,6 @@ impl Request {
|
|
|
125
133
|
}
|
|
126
134
|
|
|
127
135
|
builder.proxy = Extractor::<Proxy>::try_convert(keyword)?.into_inner();
|
|
128
|
-
builder.version = Extractor::<Version>::try_convert(keyword)?.into_inner();
|
|
129
|
-
builder.orig_headers = Extractor::<OrigHeaderMap>::try_convert(keyword)?.into_inner();
|
|
130
136
|
|
|
131
137
|
Ok(builder)
|
|
132
138
|
}
|
|
@@ -145,7 +151,13 @@ pub fn execute_request<U: AsRef<str>>(
|
|
|
145
151
|
apply_option!(set_if_some_inner, builder, request.emulation, emulation);
|
|
146
152
|
|
|
147
153
|
// Version options.
|
|
148
|
-
apply_option!(
|
|
154
|
+
apply_option!(
|
|
155
|
+
set_if_some_map,
|
|
156
|
+
builder,
|
|
157
|
+
request.version,
|
|
158
|
+
version,
|
|
159
|
+
Version::into_ffi
|
|
160
|
+
);
|
|
149
161
|
|
|
150
162
|
// Timeout options.
|
|
151
163
|
apply_option!(
|
|
@@ -170,7 +182,12 @@ pub fn execute_request<U: AsRef<str>>(
|
|
|
170
182
|
|
|
171
183
|
// Headers options.
|
|
172
184
|
apply_option!(set_if_some_into_inner, builder, request.headers, headers);
|
|
173
|
-
apply_option!(
|
|
185
|
+
apply_option!(
|
|
186
|
+
set_if_some_inner,
|
|
187
|
+
builder,
|
|
188
|
+
request.orig_headers,
|
|
189
|
+
orig_headers
|
|
190
|
+
);
|
|
174
191
|
apply_option!(
|
|
175
192
|
set_if_some,
|
|
176
193
|
builder,
|
data/src/client.rs
CHANGED
|
@@ -10,10 +10,7 @@ use magnus::{
|
|
|
10
10
|
Module, Object, RHash, RModule, Ruby, TryConvert, Value, function, method, typed_data::Obj,
|
|
11
11
|
};
|
|
12
12
|
use serde::Deserialize;
|
|
13
|
-
use wreq::{
|
|
14
|
-
Proxy,
|
|
15
|
-
header::{HeaderValue, OrigHeaderMap},
|
|
16
|
-
};
|
|
13
|
+
use wreq::{Proxy, header::HeaderValue};
|
|
17
14
|
|
|
18
15
|
use crate::{
|
|
19
16
|
client::{req::execute_request, resp::Response},
|
|
@@ -22,7 +19,7 @@ use crate::{
|
|
|
22
19
|
error::wreq_error_to_magnus,
|
|
23
20
|
extractor::Extractor,
|
|
24
21
|
gvl,
|
|
25
|
-
header::Headers,
|
|
22
|
+
header::{Headers, OrigHeaders},
|
|
26
23
|
http::Method,
|
|
27
24
|
};
|
|
28
25
|
|
|
@@ -40,7 +37,7 @@ struct Builder {
|
|
|
40
37
|
headers: Option<Headers>,
|
|
41
38
|
/// The original headers to use for the client.
|
|
42
39
|
#[serde(skip)]
|
|
43
|
-
orig_headers: Option<
|
|
40
|
+
orig_headers: Option<OrigHeaders>,
|
|
44
41
|
/// Whether to use referer.
|
|
45
42
|
referer: Option<bool>,
|
|
46
43
|
/// Whether to allow redirects.
|
|
@@ -143,6 +140,10 @@ impl Builder {
|
|
|
143
140
|
builder.headers = Some(Headers::try_convert(v)?);
|
|
144
141
|
}
|
|
145
142
|
|
|
143
|
+
if let Some(v) = hash.get(ruby.to_symbol(stringify!(orig_headers))) {
|
|
144
|
+
builder.orig_headers = Some(OrigHeaders::try_convert(v)?);
|
|
145
|
+
}
|
|
146
|
+
|
|
146
147
|
if let Some(v) = hash.get(ruby.to_symbol(stringify!(cookie_provider))) {
|
|
147
148
|
builder.cookie_provider = Some((*Obj::<Jar>::try_convert(v)?).clone());
|
|
148
149
|
}
|
|
@@ -152,7 +153,6 @@ impl Builder {
|
|
|
152
153
|
}
|
|
153
154
|
|
|
154
155
|
builder.user_agent = Extractor::<HeaderValue>::try_convert(*keyword)?.into_inner();
|
|
155
|
-
builder.orig_headers = Extractor::<OrigHeaderMap>::try_convert(*keyword)?.into_inner();
|
|
156
156
|
builder.proxy = Extractor::<Proxy>::try_convert(*keyword)?.into_inner();
|
|
157
157
|
|
|
158
158
|
Ok(builder)
|
|
@@ -175,14 +175,19 @@ impl Client {
|
|
|
175
175
|
// User agent options.
|
|
176
176
|
apply_option!(set_if_some, builder, params.user_agent, user_agent);
|
|
177
177
|
|
|
178
|
-
//
|
|
178
|
+
// Headers options.
|
|
179
179
|
apply_option!(
|
|
180
180
|
set_if_some_into_inner,
|
|
181
181
|
builder,
|
|
182
182
|
params.headers,
|
|
183
183
|
default_headers
|
|
184
184
|
);
|
|
185
|
-
apply_option!(
|
|
185
|
+
apply_option!(
|
|
186
|
+
set_if_some_inner,
|
|
187
|
+
builder,
|
|
188
|
+
params.orig_headers,
|
|
189
|
+
orig_headers
|
|
190
|
+
);
|
|
186
191
|
|
|
187
192
|
// Allow redirects options.
|
|
188
193
|
apply_option!(set_if_some, builder, params.referer, referer);
|
data/src/error.rs
CHANGED
|
@@ -117,6 +117,14 @@ pub fn header_value_error_to_magnus(err: wreq::header::InvalidHeaderValue) -> Ma
|
|
|
117
117
|
)
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
/// Map type/value errors to corresponding [`magnus::Error`]
|
|
121
|
+
pub fn type_value_error_to_magnus(err: &str) -> MagnusError {
|
|
122
|
+
MagnusError::new(
|
|
123
|
+
ruby!().get_inner(&BUILDER_ERROR),
|
|
124
|
+
format!("type error: {err}"),
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
|
|
120
128
|
/// Map [`wreq::Error`] to corresponding [`magnus::Error`]
|
|
121
129
|
pub fn wreq_error_to_magnus(err: wreq::Error) -> MagnusError {
|
|
122
130
|
let error_msg = err.to_string();
|
data/src/extractor.rs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
use magnus::{RArray, RHash, RString, Ruby, TryConvert, r_hash::ForEach};
|
|
2
2
|
use wreq::{
|
|
3
|
-
Proxy,
|
|
3
|
+
Proxy,
|
|
4
4
|
header::{HeaderMap, HeaderName, HeaderValue, OrigHeaderMap},
|
|
5
5
|
};
|
|
6
6
|
|
|
@@ -32,27 +32,6 @@ where
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// ===== impl Extractor<Version> =====
|
|
36
|
-
|
|
37
|
-
impl ExtractorName for Version {
|
|
38
|
-
const NAME: &str = "version";
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
impl TryConvert for Extractor<Version> {
|
|
42
|
-
fn try_convert(value: magnus::Value) -> Result<Self, magnus::Error> {
|
|
43
|
-
let keyword = RHash::try_convert(value)?;
|
|
44
|
-
if let Some(version_val) = keyword.get(Version::NAME) {
|
|
45
|
-
return <&crate::http::Version>::try_convert(version_val)
|
|
46
|
-
.cloned()
|
|
47
|
-
.map(crate::http::Version::into_ffi)
|
|
48
|
-
.map(Some)
|
|
49
|
-
.map(Extractor);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
Ok(Extractor(None))
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
35
|
// ===== impl Extractor<HeaderValue> =====
|
|
57
36
|
|
|
58
37
|
impl ExtractorName for HeaderValue {
|
data/src/header.rs
CHANGED
|
@@ -9,8 +9,11 @@ use magnus::{
|
|
|
9
9
|
r_hash::ForEach,
|
|
10
10
|
typed_data::{Inspect, Obj},
|
|
11
11
|
};
|
|
12
|
+
use wreq::header::OrigHeaderMap;
|
|
12
13
|
|
|
13
|
-
use crate::error::{
|
|
14
|
+
use crate::error::{
|
|
15
|
+
header_name_error_to_magnus, header_value_error_to_magnus, type_value_error_to_magnus,
|
|
16
|
+
};
|
|
14
17
|
|
|
15
18
|
/// HTTP headers collection with read and write operations.
|
|
16
19
|
///
|
|
@@ -20,6 +23,9 @@ use crate::error::{header_name_error_to_magnus, header_value_error_to_magnus};
|
|
|
20
23
|
#[magnus::wrap(class = "Wreq::Headers", free_immediately, size)]
|
|
21
24
|
pub struct Headers(pub RefCell<HeaderMap>);
|
|
22
25
|
|
|
26
|
+
/// A map from header names to their original casing as received in an HTTP message.
|
|
27
|
+
pub struct OrigHeaders(pub OrigHeaderMap);
|
|
28
|
+
|
|
23
29
|
struct HeaderIter {
|
|
24
30
|
inner: http::header::IntoIter<HeaderValue>,
|
|
25
31
|
next_name: Option<HeaderName>,
|
|
@@ -166,6 +172,23 @@ impl TryConvert for Headers {
|
|
|
166
172
|
}
|
|
167
173
|
}
|
|
168
174
|
|
|
175
|
+
// ===== impl OrigHeaders =====
|
|
176
|
+
|
|
177
|
+
impl TryConvert for OrigHeaders {
|
|
178
|
+
fn try_convert(value: magnus::Value) -> Result<Self, magnus::Error> {
|
|
179
|
+
let mut map = OrigHeaderMap::new();
|
|
180
|
+
|
|
181
|
+
let rarray = RArray::from_value(value)
|
|
182
|
+
.ok_or_else(|| type_value_error_to_magnus("Expected an array of strings"))?;
|
|
183
|
+
|
|
184
|
+
for value in rarray.into_iter().flat_map(RString::from_value) {
|
|
185
|
+
map.insert(value.to_bytes());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
Ok(Self(map))
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
169
192
|
// ===== impl HeaderIter =====
|
|
170
193
|
|
|
171
194
|
impl Iterator for HeaderIter {
|
data/src/http.rs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
use magnus::{Error, Module, RModule, Ruby, method, typed_data::Inspect};
|
|
1
|
+
use magnus::{Error, Module, RModule, Ruby, TryConvert, Value, method, typed_data::Inspect};
|
|
2
2
|
|
|
3
3
|
define_ruby_enum!(
|
|
4
4
|
/// An HTTP version.
|
|
@@ -41,6 +41,20 @@ impl Version {
|
|
|
41
41
|
pub fn to_s(&self) -> String {
|
|
42
42
|
self.into_ffi().inspect()
|
|
43
43
|
}
|
|
44
|
+
|
|
45
|
+
/// Value-based equality for Ruby (`==`).
|
|
46
|
+
#[inline]
|
|
47
|
+
pub fn equals(&self, other: Value) -> bool {
|
|
48
|
+
<&Version>::try_convert(other)
|
|
49
|
+
.map(|other| *self == *other)
|
|
50
|
+
.unwrap_or(false)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
impl TryConvert for Version {
|
|
55
|
+
fn try_convert(value: magnus::Value) -> Result<Self, magnus::Error> {
|
|
56
|
+
<&Version>::try_convert(value).cloned()
|
|
57
|
+
}
|
|
44
58
|
}
|
|
45
59
|
|
|
46
60
|
// ===== impl StatusCode =====
|
|
@@ -113,6 +127,7 @@ pub fn include(ruby: &Ruby, gem_module: &RModule) -> Result<(), Error> {
|
|
|
113
127
|
version_class.const_set("HTTP_2", Version::HTTP_2)?;
|
|
114
128
|
version_class.const_set("HTTP_3", Version::HTTP_3)?;
|
|
115
129
|
version_class.define_method("to_s", method!(Version::to_s, 0))?;
|
|
130
|
+
version_class.define_method("==", method!(Version::equals, 1))?;
|
|
116
131
|
|
|
117
132
|
let status_code_class = gem_module.define_class("StatusCode", ruby.class_object())?;
|
|
118
133
|
status_code_class.define_method("as_int", method!(StatusCode::as_int, 0))?;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class OrigHeaderTest < Minitest::Test
|
|
4
|
+
URL = "https://tls.browserleaks.com/http1"
|
|
5
|
+
|
|
6
|
+
CASES = [
|
|
7
|
+
{
|
|
8
|
+
name: "mixed_case_descending",
|
|
9
|
+
headers: {
|
|
10
|
+
"X-Zeta-Token" => "zeta",
|
|
11
|
+
"x-alpha-key" => "alpha",
|
|
12
|
+
"X-MiXeD-CaSe" => "mixed"
|
|
13
|
+
},
|
|
14
|
+
orig_headers: ["X-Zeta-Token", "x-alpha-key", "X-MiXeD-CaSe"]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "reverse_alpha_order",
|
|
18
|
+
headers: {
|
|
19
|
+
"X-Third" => "3",
|
|
20
|
+
"X-Second" => "2",
|
|
21
|
+
"X-First" => "1"
|
|
22
|
+
},
|
|
23
|
+
orig_headers: ["X-Third", "X-Second", "X-First"]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "preserve_weird_casing",
|
|
27
|
+
headers: {
|
|
28
|
+
"x-a" => "a",
|
|
29
|
+
"X-B" => "b",
|
|
30
|
+
"x-C" => "c"
|
|
31
|
+
},
|
|
32
|
+
orig_headers: ["x-C", "x-a", "X-B"]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "interleaved_tokens",
|
|
36
|
+
headers: {
|
|
37
|
+
"X-Token-3" => "v3",
|
|
38
|
+
"X-Token-1" => "v1",
|
|
39
|
+
"X-Token-2" => "v2"
|
|
40
|
+
},
|
|
41
|
+
orig_headers: ["X-Token-1", "X-Token-2", "X-Token-3"]
|
|
42
|
+
}
|
|
43
|
+
].freeze
|
|
44
|
+
|
|
45
|
+
def test_client_default_orig_headers_preserves_header_order_in_multiple_shuffled_cases
|
|
46
|
+
CASES.each do |kase|
|
|
47
|
+
client = Wreq::Client.new(
|
|
48
|
+
headers: kase[:headers],
|
|
49
|
+
orig_headers: kase[:orig_headers]
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
response = client.get(URL, version: Wreq::Version::HTTP_11)
|
|
53
|
+
assert_equal 200, response.code, "case=#{kase[:name]}"
|
|
54
|
+
|
|
55
|
+
echoed_headers = extract_http1_headers(response.json, kase[:name])
|
|
56
|
+
assert_header_order(echoed_headers, kase[:orig_headers], kase[:name])
|
|
57
|
+
assert_header_values(echoed_headers, kase[:headers], kase[:name])
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_module_request_orig_headers_preserves_header_order_in_multiple_shuffled_cases
|
|
62
|
+
CASES.each do |kase|
|
|
63
|
+
response = Wreq.get(
|
|
64
|
+
URL,
|
|
65
|
+
headers: kase[:headers],
|
|
66
|
+
orig_headers: kase[:orig_headers],
|
|
67
|
+
version: Wreq::Version::HTTP_11
|
|
68
|
+
)
|
|
69
|
+
assert_equal 200, response.code, "case=#{kase[:name]}"
|
|
70
|
+
|
|
71
|
+
echoed_headers = extract_http1_headers(response.json, kase[:name])
|
|
72
|
+
assert_header_order(echoed_headers, kase[:orig_headers], kase[:name])
|
|
73
|
+
assert_header_values(echoed_headers, kase[:headers], kase[:name])
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def extract_http1_headers(json, case_name)
|
|
80
|
+
http1 = fetch_by_name(json, "http1")
|
|
81
|
+
refute_nil http1, "case=#{case_name}: expected JSON key 'http1', got #{json.keys.inspect}"
|
|
82
|
+
|
|
83
|
+
headers = fetch_by_name(http1, "headers")
|
|
84
|
+
refute_nil headers, "case=#{case_name}: expected JSON key 'http1.headers'"
|
|
85
|
+
headers
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def fetch_by_name(hash_like, key_name)
|
|
89
|
+
return hash_like[key_name] if hash_like.respond_to?(:key?) && hash_like.key?(key_name)
|
|
90
|
+
return hash_like[key_name.to_sym] if hash_like.respond_to?(:key?) && hash_like.key?(key_name.to_sym)
|
|
91
|
+
|
|
92
|
+
pair = hash_like.find { |k, _| k.to_s == key_name }
|
|
93
|
+
pair&.last
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def assert_header_order(echoed_headers, ordered_names, case_name)
|
|
97
|
+
echoed_keys = echoed_headers.keys
|
|
98
|
+
positions = ordered_names.map do |expected_name|
|
|
99
|
+
index = echoed_keys.index(expected_name)
|
|
100
|
+
refute_nil index, "case=#{case_name}: expected header to exist in echo: #{expected_name}"
|
|
101
|
+
index
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
assert_equal positions.sort, positions,
|
|
105
|
+
"case=#{case_name}: expected header order #{ordered_names.inspect}, got keys #{echoed_keys.inspect}"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def assert_header_values(echoed_headers, expected_headers, case_name)
|
|
109
|
+
expected_headers.each do |name, expected_value|
|
|
110
|
+
assert echoed_headers.key?(name),
|
|
111
|
+
"case=#{case_name}: expected exact-case header name #{name}, got #{echoed_headers.keys.inspect}"
|
|
112
|
+
assert_equal expected_value, echoed_headers[name]
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
data/test/request_test.rb
CHANGED
|
@@ -6,6 +6,16 @@ class WreqHttpbinTest < Minitest::Test
|
|
|
6
6
|
@client = Wreq::Client.new(timeout: 30)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
def test_spec_http1_version
|
|
10
|
+
response = Wreq.get("https://tls.browserleaks.com", version: Wreq::Version::HTTP_11)
|
|
11
|
+
assert_equal response.version, Wreq::Version::HTTP_11
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_spec_http2_version
|
|
15
|
+
response = Wreq.get("https://tls.browserleaks.com", version: Wreq::Version::HTTP_2)
|
|
16
|
+
assert_equal response.version, Wreq::Version::HTTP_2
|
|
17
|
+
end
|
|
18
|
+
|
|
9
19
|
def test_module_get_method
|
|
10
20
|
response = Wreq.get("http://localhost:8080/get")
|
|
11
21
|
assert_equal 200, response.code
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: wreq
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SearchApi
|
|
@@ -74,6 +74,7 @@ files:
|
|
|
74
74
|
- test/header_test.rb
|
|
75
75
|
- test/inspect_test.rb
|
|
76
76
|
- test/module_methods_test.rb
|
|
77
|
+
- test/orig_header_test.rb
|
|
77
78
|
- test/request_parameters_test.rb
|
|
78
79
|
- test/request_test.rb
|
|
79
80
|
- test/response_test.rb
|