wreq 1.2.4 → 1.2.5
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 +3 -7
- data/Cargo.toml +6 -1
- data/crates/wreq-util/.github/FUNDING.yml +15 -0
- data/crates/wreq-util/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/crates/wreq-util/.github/ISSUE_TEMPLATE/custom.md +10 -0
- data/crates/wreq-util/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/crates/wreq-util/.github/dependabot.yml +22 -0
- data/crates/wreq-util/.github/workflows/ci.yml +82 -0
- data/crates/wreq-util/.github/workflows/release-plz.yml +52 -0
- data/crates/wreq-util/.gitignore +24 -0
- data/crates/wreq-util/CHANGELOG.md +74 -0
- data/crates/wreq-util/Cargo.toml +94 -0
- data/crates/wreq-util/LICENSE +201 -0
- data/crates/wreq-util/README.md +62 -0
- data/crates/wreq-util/examples/emulate.rs +39 -0
- data/crates/wreq-util/examples/tower_delay.rs +191 -0
- data/crates/wreq-util/release-plz.toml +2 -0
- data/crates/wreq-util/rustfmt.toml +5 -0
- data/crates/wreq-util/src/emulate/compress.rs +85 -0
- data/crates/wreq-util/src/emulate/macros.rs +370 -0
- data/crates/wreq-util/src/emulate/profile/chrome/header.rs +59 -0
- data/crates/wreq-util/src/emulate/profile/chrome/http2.rs +65 -0
- data/crates/wreq-util/src/emulate/profile/chrome/tls.rs +153 -0
- data/crates/wreq-util/src/emulate/profile/chrome.rs +2028 -0
- data/crates/wreq-util/src/emulate/profile/firefox/header.rs +21 -0
- data/crates/wreq-util/src/emulate/profile/firefox/http2.rs +113 -0
- data/crates/wreq-util/src/emulate/profile/firefox/tls.rs +253 -0
- data/crates/wreq-util/src/emulate/profile/firefox.rs +518 -0
- data/crates/wreq-util/src/emulate/profile/okhttp.rs +241 -0
- data/crates/wreq-util/src/emulate/profile/opera/header.rs +30 -0
- data/crates/wreq-util/src/emulate/profile/opera/http2.rs +50 -0
- data/crates/wreq-util/src/emulate/profile/opera/tls.rs +97 -0
- data/crates/wreq-util/src/emulate/profile/opera.rs +299 -0
- data/crates/wreq-util/src/emulate/profile/safari/header.rs +59 -0
- data/crates/wreq-util/src/emulate/profile/safari/http2.rs +116 -0
- data/crates/wreq-util/src/emulate/profile/safari/tls.rs +177 -0
- data/crates/wreq-util/src/emulate/profile/safari.rs +222 -0
- data/crates/wreq-util/src/emulate/profile.rs +47 -0
- data/crates/wreq-util/src/emulate.rs +369 -0
- data/crates/wreq-util/src/lib.rs +14 -0
- data/crates/wreq-util/src/rand.rs +24 -0
- data/crates/wreq-util/src/tower/delay/future.rs +43 -0
- data/crates/wreq-util/src/tower/delay/layer.rs +201 -0
- data/crates/wreq-util/src/tower/delay/service.rs +190 -0
- data/crates/wreq-util/src/tower/delay.rs +98 -0
- data/crates/wreq-util/src/tower.rs +7 -0
- data/crates/wreq-util/tests/client.rs +51 -0
- data/crates/wreq-util/tests/emulate_chrome.rs +270 -0
- data/crates/wreq-util/tests/emulate_firefox.rs +92 -0
- data/crates/wreq-util/tests/emulate_okhttp.rs +46 -0
- data/crates/wreq-util/tests/emulate_opera.rs +113 -0
- data/crates/wreq-util/tests/emulate_safari.rs +151 -0
- data/crates/wreq-util/tests/support/mod.rs +55 -0
- data/crates/wreq-util/tests/support/server.rs +232 -0
- data/examples/emulate_request.rb +1 -1
- data/lib/wreq.rb +20 -18
- data/lib/wreq_ruby/body.rb +3 -0
- data/lib/wreq_ruby/client.rb +18 -18
- data/lib/wreq_ruby/cookie.rb +2 -2
- data/lib/wreq_ruby/emulate.rb +3 -1
- data/lib/wreq_ruby/header.rb +205 -114
- data/lib/wreq_ruby/response.rb +28 -3
- data/src/emulate.rs +1 -0
- data/src/error.rs +2 -6
- data/src/header/helper.rs +112 -0
- data/src/header.rs +198 -133
- data/test/header_test.rb +228 -192
- data/test/stream_test.rb +36 -0
- metadata +54 -1
data/test/header_test.rb
CHANGED
|
@@ -2,289 +2,325 @@ require "test_helper"
|
|
|
2
2
|
|
|
3
3
|
class HeadersTest < Minitest::Test
|
|
4
4
|
def setup
|
|
5
|
-
@
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
})
|
|
10
|
-
@headers = @response.headers
|
|
5
|
+
@headers = Wreq::Headers.new(
|
|
6
|
+
"Content-Type" => "application/json",
|
|
7
|
+
"X-Custom-Header" => "custom-value"
|
|
8
|
+
)
|
|
11
9
|
end
|
|
12
10
|
|
|
13
|
-
def
|
|
14
|
-
assert_instance_of Wreq::Headers, @headers
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def test_initialize
|
|
11
|
+
def test_headers_class_and_empty_constructor
|
|
18
12
|
headers = Wreq::Headers.new
|
|
13
|
+
|
|
19
14
|
assert_instance_of Wreq::Headers, headers
|
|
20
15
|
assert headers.empty?
|
|
21
16
|
assert_equal 0, headers.length
|
|
17
|
+
assert_includes Wreq::Headers.ancestors, Enumerable
|
|
22
18
|
end
|
|
23
19
|
|
|
24
|
-
def
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
def test_collection_api_methods_are_available
|
|
21
|
+
collection_methods = [:[], :[]=, :fetch, :delete, :size, :to_a, :to_h, :to_hash, :each]
|
|
22
|
+
|
|
23
|
+
collection_methods.each do |method|
|
|
24
|
+
assert_respond_to @headers, method
|
|
25
|
+
end
|
|
29
26
|
end
|
|
30
27
|
|
|
31
|
-
def
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
value2 = @headers.get("Content-Type")
|
|
35
|
-
value3 = @headers.get("CONTENT-TYPE")
|
|
28
|
+
def test_initialize_from_hash_and_headers
|
|
29
|
+
headers = Wreq::Headers.new("Accept" => "application/json")
|
|
30
|
+
copy = Wreq::Headers.new(headers)
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
assert_equal value2, value3
|
|
39
|
-
end
|
|
32
|
+
headers["Accept"] = "text/plain"
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
assert_nil result
|
|
34
|
+
assert_equal "text/plain", headers["Accept"]
|
|
35
|
+
assert_equal "application/json", copy["Accept"]
|
|
44
36
|
end
|
|
45
37
|
|
|
46
|
-
def
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
38
|
+
def test_initialize_from_enumerable_pairs
|
|
39
|
+
source = Class.new do
|
|
40
|
+
include Enumerable
|
|
41
|
+
|
|
42
|
+
def each
|
|
43
|
+
yield "X-First", "one"
|
|
44
|
+
yield :set_cookie, ["a=1", "b=2"]
|
|
45
|
+
end
|
|
46
|
+
end.new
|
|
47
|
+
|
|
48
|
+
headers = Wreq::Headers.new(source)
|
|
49
|
+
|
|
50
|
+
assert_includes headers.keys, "x-first"
|
|
51
|
+
assert_includes headers.keys, "set-cookie"
|
|
52
|
+
assert_equal ["a=1", "b=2"], headers[:set_cookie]
|
|
52
53
|
end
|
|
53
54
|
|
|
54
|
-
def
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
assert_empty values
|
|
55
|
+
def test_initialize_rejects_invalid_sources_and_pairs
|
|
56
|
+
assert_raises(Wreq::BuilderError) { Wreq::Headers.new(Object.new) }
|
|
57
|
+
assert_raises(Wreq::BuilderError) { Wreq::Headers.new([["Accept"]]) }
|
|
58
|
+
assert_raises(ArgumentError) { Wreq::Headers.new({}, {}) }
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
def
|
|
62
|
-
headers = Wreq::Headers.new
|
|
63
|
-
|
|
61
|
+
def test_string_and_symbol_names_are_normalized
|
|
62
|
+
headers = Wreq::Headers.new(
|
|
63
|
+
"x-CuStOm-Header" => "value",
|
|
64
|
+
content_type: "application/json"
|
|
65
|
+
)
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
assert_includes headers.keys, "x-custom-header"
|
|
68
|
+
assert_includes headers.keys, "content-type"
|
|
69
|
+
assert_equal "value", headers["X-CUSTOM-HEADER"]
|
|
70
|
+
assert_equal "application/json", headers[:content_type]
|
|
67
71
|
end
|
|
68
72
|
|
|
69
|
-
def
|
|
70
|
-
headers = Wreq::Headers.new
|
|
71
|
-
headers.set("X-Test", "value1")
|
|
72
|
-
headers.set("X-Test", "value2")
|
|
73
|
+
def test_get_returns_first_value
|
|
74
|
+
headers = Wreq::Headers.new("Accept" => ["application/json", "text/plain"])
|
|
73
75
|
|
|
74
|
-
assert_equal "
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
assert_equal "value2", values.first
|
|
76
|
+
assert_equal "application/json", headers.get("accept")
|
|
77
|
+
assert_equal "application/json", headers.get(:accept)
|
|
78
|
+
assert_nil headers.get(:missing)
|
|
78
79
|
end
|
|
79
80
|
|
|
80
|
-
def
|
|
81
|
-
headers = Wreq::Headers.new
|
|
82
|
-
|
|
81
|
+
def test_index_uses_nil_string_and_array_shapes
|
|
82
|
+
headers = Wreq::Headers.new(
|
|
83
|
+
"Accept" => "application/json",
|
|
84
|
+
"Set-Cookie" => ["a=1", "b=2"]
|
|
85
|
+
)
|
|
83
86
|
|
|
84
|
-
|
|
87
|
+
assert_nil headers["Missing"]
|
|
88
|
+
assert_equal "application/json", headers["Accept"]
|
|
89
|
+
assert_equal ["a=1", "b=2"], headers["Set-Cookie"]
|
|
85
90
|
end
|
|
86
91
|
|
|
87
|
-
def
|
|
88
|
-
|
|
89
|
-
headers.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
def test_get_all_always_returns_an_array
|
|
93
|
+
assert_equal ["application/json"], @headers.get_all("CONTENT-TYPE")
|
|
94
|
+
assert_equal [], @headers.get_all("Missing")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def test_set_replaces_existing_occurrences
|
|
98
|
+
headers = Wreq::Headers.new("Accept" => ["application/json", "text/plain"])
|
|
99
|
+
|
|
100
|
+
headers.set("Accept", ["text/html", "application/xml"])
|
|
92
101
|
|
|
93
|
-
|
|
94
|
-
assert_equal
|
|
95
|
-
assert_includes values, "application/json"
|
|
96
|
-
assert_includes values, "text/html"
|
|
97
|
-
assert_includes values, "application/xml"
|
|
102
|
+
assert_equal ["text/html", "application/xml"], headers.get_all("Accept")
|
|
103
|
+
assert_equal 2, headers.length
|
|
98
104
|
end
|
|
99
105
|
|
|
100
|
-
def
|
|
101
|
-
headers = Wreq::Headers.new
|
|
102
|
-
headers.set("X-Remove-Me", "value")
|
|
106
|
+
def test_index_assignment_replaces_existing_occurrences
|
|
107
|
+
headers = Wreq::Headers.new("Set-Cookie" => "old=1")
|
|
103
108
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
109
|
+
assigned = headers.public_send(:[]=, :set_cookie, ["a=1", "b=2"])
|
|
110
|
+
|
|
111
|
+
assert_equal ["a=1", "b=2"], assigned
|
|
112
|
+
assert_equal ["a=1", "b=2"], headers.get_all("Set-Cookie")
|
|
107
113
|
end
|
|
108
114
|
|
|
109
|
-
def
|
|
115
|
+
def test_append_keeps_values_as_separate_occurrences
|
|
110
116
|
headers = Wreq::Headers.new
|
|
111
|
-
|
|
112
|
-
|
|
117
|
+
headers.append("Set-Cookie", "a=1")
|
|
118
|
+
headers.append("Set-Cookie", ["b=2", "c=3"])
|
|
119
|
+
|
|
120
|
+
assert_equal ["a=1", "b=2", "c=3"], headers.get_all("Set-Cookie")
|
|
121
|
+
refute_includes headers.get_all("Set-Cookie"), "a=1,b=2,c=3"
|
|
113
122
|
end
|
|
114
123
|
|
|
115
|
-
def
|
|
124
|
+
def test_set_and_append_return_nil
|
|
116
125
|
headers = Wreq::Headers.new
|
|
117
|
-
headers.set("X-Delete-Me", "value")
|
|
118
126
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
assert_nil headers.get("X-Delete-Me")
|
|
127
|
+
assert_nil headers.set("Accept", "application/json")
|
|
128
|
+
assert_nil headers.append("Accept", "text/plain")
|
|
122
129
|
end
|
|
123
130
|
|
|
124
|
-
def
|
|
125
|
-
|
|
126
|
-
|
|
131
|
+
def test_empty_array_values_remove_or_leave_headers_unchanged
|
|
132
|
+
headers = Wreq::Headers.new("Accept" => "application/json")
|
|
133
|
+
|
|
134
|
+
assert_nil headers.set("Accept", [])
|
|
135
|
+
refute headers.key?("Accept")
|
|
127
136
|
|
|
128
|
-
|
|
129
|
-
refute
|
|
137
|
+
assert_nil headers.append("X-Empty", [])
|
|
138
|
+
refute headers.key?("X-Empty")
|
|
130
139
|
end
|
|
131
140
|
|
|
132
|
-
def
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
end
|
|
141
|
+
def test_fetch_existing_and_missing_values
|
|
142
|
+
assert_equal "application/json", @headers.fetch(:content_type)
|
|
143
|
+
assert_equal "fallback", @headers.fetch("Missing", "fallback")
|
|
144
|
+
assert_equal "MISSING", @headers.fetch("Missing") { |name| name.upcase }
|
|
145
|
+
assert_raises(KeyError) { @headers.fetch("Missing") }
|
|
138
146
|
end
|
|
139
147
|
|
|
140
|
-
def
|
|
141
|
-
|
|
142
|
-
|
|
148
|
+
def test_fetch_block_takes_precedence_over_default
|
|
149
|
+
result = @headers.fetch("Missing", "fallback") { "from block" }
|
|
150
|
+
|
|
151
|
+
assert_equal "from block", result
|
|
143
152
|
end
|
|
144
153
|
|
|
145
|
-
def
|
|
146
|
-
headers = Wreq::Headers.new
|
|
147
|
-
assert_equal 0, headers.length
|
|
154
|
+
def test_fetch_preserves_repeated_values_and_explicit_nil_default
|
|
155
|
+
headers = Wreq::Headers.new("Set-Cookie" => ["a=1", "b=2"])
|
|
148
156
|
|
|
149
|
-
|
|
150
|
-
|
|
157
|
+
assert_equal ["a=1", "b=2"], headers.fetch(:set_cookie)
|
|
158
|
+
assert_nil headers.fetch("Missing", nil)
|
|
159
|
+
end
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
|
|
161
|
+
def test_remove_and_delete_remove_every_occurrence
|
|
162
|
+
headers = Wreq::Headers.new("Set-Cookie" => ["a=1", "b=2"])
|
|
154
163
|
|
|
155
|
-
|
|
156
|
-
headers
|
|
157
|
-
|
|
164
|
+
assert_equal "a=1", headers.delete(:set_cookie)
|
|
165
|
+
assert_nil headers["Set-Cookie"]
|
|
166
|
+
assert_nil headers.remove("Set-Cookie")
|
|
158
167
|
end
|
|
159
168
|
|
|
160
|
-
def
|
|
161
|
-
headers
|
|
162
|
-
assert headers.
|
|
169
|
+
def test_contains_and_key_are_case_insensitive
|
|
170
|
+
assert @headers.contains?("CONTENT-TYPE")
|
|
171
|
+
assert @headers.contains?(:content_type)
|
|
172
|
+
assert @headers.key?("content-type")
|
|
173
|
+
refute @headers.key?("Missing")
|
|
163
174
|
end
|
|
164
175
|
|
|
165
|
-
def
|
|
166
|
-
|
|
176
|
+
def test_length_counts_occurrences_and_keys_are_unique
|
|
177
|
+
headers = Wreq::Headers.new(
|
|
178
|
+
"Accept" => ["application/json", "text/plain"],
|
|
179
|
+
"Content-Type" => "application/json"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
assert_equal 3, headers.length
|
|
183
|
+
assert_equal 3, headers.size
|
|
184
|
+
assert_equal 2, headers.keys.length
|
|
167
185
|
end
|
|
168
186
|
|
|
169
|
-
def
|
|
170
|
-
headers = Wreq::Headers.new
|
|
171
|
-
headers.set("Header1", "value1")
|
|
172
|
-
headers.set("Header2", "value2")
|
|
187
|
+
def test_clear_returns_self
|
|
188
|
+
headers = Wreq::Headers.new("Accept" => "application/json")
|
|
173
189
|
|
|
174
|
-
|
|
175
|
-
headers.clear
|
|
190
|
+
assert_same headers, headers.clear
|
|
176
191
|
assert headers.empty?
|
|
177
|
-
assert_equal 0, headers.length
|
|
178
192
|
end
|
|
179
193
|
|
|
180
|
-
def
|
|
181
|
-
headers = Wreq::Headers.new
|
|
182
|
-
headers.set("Content-Type", "application/json")
|
|
183
|
-
headers.set("Authorization", "Bearer token")
|
|
194
|
+
def test_values_include_every_occurrence
|
|
195
|
+
headers = Wreq::Headers.new("Accept" => ["application/json", "text/plain"])
|
|
184
196
|
|
|
185
|
-
|
|
186
|
-
assert_instance_of Array, keys
|
|
187
|
-
assert_equal 2, keys.length
|
|
188
|
-
assert_includes keys, "content-type"
|
|
189
|
-
assert_includes keys, "authorization"
|
|
197
|
+
assert_equal ["application/json", "text/plain"], headers.values
|
|
190
198
|
end
|
|
191
199
|
|
|
192
|
-
def
|
|
193
|
-
headers = Wreq::Headers.new
|
|
194
|
-
|
|
195
|
-
headers.set("X-Custom-Header", "value")
|
|
200
|
+
def test_each_yields_every_occurrence_and_returns_self
|
|
201
|
+
headers = Wreq::Headers.new("Set-Cookie" => ["a=1", "b=2"])
|
|
202
|
+
pairs = []
|
|
196
203
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
returned = headers.each { |name, value| pairs << [name, value] }
|
|
205
|
+
|
|
206
|
+
assert_same headers, returned
|
|
207
|
+
assert_equal [["set-cookie", "a=1"], ["set-cookie", "b=2"]], pairs
|
|
201
208
|
end
|
|
202
209
|
|
|
203
|
-
def
|
|
204
|
-
headers = Wreq::Headers.new
|
|
205
|
-
|
|
206
|
-
|
|
210
|
+
def test_each_without_a_block_returns_chainable_enumerator
|
|
211
|
+
headers = Wreq::Headers.new(
|
|
212
|
+
"Accept" => "application/json",
|
|
213
|
+
"Set-Cookie" => ["a=1", "b=2"]
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
enumerator = headers.each
|
|
217
|
+
cookies = enumerator.select { |name, _value| name == "set-cookie" }
|
|
207
218
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
assert_equal 2, values.length
|
|
211
|
-
assert_includes values, "application/json"
|
|
212
|
-
assert_includes values, "Bearer token"
|
|
219
|
+
assert_instance_of Enumerator, enumerator
|
|
220
|
+
assert_equal [["set-cookie", "a=1"], ["set-cookie", "b=2"]], cookies
|
|
213
221
|
end
|
|
214
222
|
|
|
215
|
-
def
|
|
216
|
-
headers = Wreq::Headers.new
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
assert_instance_of String, name
|
|
223
|
-
assert_instance_of String, value
|
|
224
|
-
collected[name] = value
|
|
223
|
+
def test_each_allows_mutating_headers_from_the_block
|
|
224
|
+
headers = Wreq::Headers.new("X-First" => "one")
|
|
225
|
+
yielded_names = []
|
|
226
|
+
|
|
227
|
+
headers.each do |name, _value|
|
|
228
|
+
yielded_names << name
|
|
229
|
+
headers["X-Added"] = "two"
|
|
225
230
|
end
|
|
226
231
|
|
|
227
|
-
assert_equal
|
|
228
|
-
assert_equal "
|
|
229
|
-
assert_equal "value2", collected["header2"]
|
|
232
|
+
assert_equal ["x-first"], yielded_names
|
|
233
|
+
assert_equal "two", headers["X-Added"]
|
|
230
234
|
end
|
|
231
235
|
|
|
232
|
-
def
|
|
233
|
-
headers = Wreq::Headers.new
|
|
236
|
+
def test_enumerable_methods_use_each
|
|
237
|
+
headers = Wreq::Headers.new(
|
|
238
|
+
"Accept" => "application/json",
|
|
239
|
+
"Set-Cookie" => ["a=1", "b=2"]
|
|
240
|
+
)
|
|
234
241
|
|
|
235
|
-
|
|
236
|
-
headers.set("Content-Type", "application/json")
|
|
237
|
-
headers.set("Accept", "application/json")
|
|
242
|
+
cookies = headers.select { |name, _value| name == "set-cookie" }
|
|
238
243
|
|
|
239
|
-
assert_equal 2,
|
|
244
|
+
assert_equal [["set-cookie", "a=1"], ["set-cookie", "b=2"]], cookies
|
|
245
|
+
end
|
|
240
246
|
|
|
241
|
-
|
|
242
|
-
headers.
|
|
243
|
-
|
|
247
|
+
def test_to_a_and_to_h_preserve_duplicate_values
|
|
248
|
+
headers = Wreq::Headers.new(
|
|
249
|
+
"Accept" => "application/json",
|
|
250
|
+
"Set-Cookie" => ["a=1", "b=2"]
|
|
251
|
+
)
|
|
244
252
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
253
|
+
expected_pairs = [
|
|
254
|
+
["accept", "application/json"],
|
|
255
|
+
["set-cookie", "a=1"],
|
|
256
|
+
["set-cookie", "b=2"]
|
|
257
|
+
]
|
|
258
|
+
assert_equal expected_pairs.sort, headers.to_a.sort
|
|
259
|
+
assert_equal({
|
|
260
|
+
"accept" => "application/json",
|
|
261
|
+
"set-cookie" => ["a=1", "b=2"]
|
|
262
|
+
}, headers.to_h)
|
|
263
|
+
assert_equal headers.to_h, headers.to_hash
|
|
248
264
|
end
|
|
249
265
|
|
|
250
266
|
def test_special_characters_in_header_values
|
|
267
|
+
value = "Bearer token-123_abc/xyz+456=789"
|
|
268
|
+
@headers.set("Authorization", value)
|
|
269
|
+
|
|
270
|
+
assert_equal value, @headers.get("Authorization")
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def test_invalid_header_names_and_values_raise_builder_error
|
|
251
274
|
headers = Wreq::Headers.new
|
|
252
|
-
special_value = "Bearer token-123_abc/xyz+456=789"
|
|
253
|
-
headers.set("Authorization", special_value)
|
|
254
275
|
|
|
255
|
-
|
|
276
|
+
assert_raises(Wreq::BuilderError) { headers.set(123, "value") }
|
|
277
|
+
assert_raises(Wreq::BuilderError) { headers.set("Bad\nName", "value") }
|
|
278
|
+
assert_raises(Wreq::BuilderError) { headers.set("X-Test", 123) }
|
|
279
|
+
assert_raises(Wreq::BuilderError) { headers.append("X-Test", ["valid", 123]) }
|
|
280
|
+
assert headers.empty?
|
|
256
281
|
end
|
|
257
282
|
|
|
258
|
-
def
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
refute @headers.empty?
|
|
283
|
+
def test_header_entry_limit_raises_builder_error_without_partial_update
|
|
284
|
+
headers = Wreq::Headers.new
|
|
285
|
+
values = Array.new(32_769, "value")
|
|
262
286
|
|
|
263
|
-
|
|
264
|
-
|
|
287
|
+
error = assert_raises(Wreq::BuilderError) { headers.append("X-Large", values) }
|
|
288
|
+
|
|
289
|
+
assert_match(/32,768/, error.message)
|
|
290
|
+
assert headers.empty?
|
|
265
291
|
end
|
|
266
292
|
|
|
267
|
-
def
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
@headers.each do |name, value|
|
|
271
|
-
assert_instance_of String, name
|
|
272
|
-
assert_instance_of String, value
|
|
273
|
-
count += 1
|
|
274
|
-
end
|
|
293
|
+
def test_response_headers_integration
|
|
294
|
+
headers = response_headers
|
|
295
|
+
pairs = headers.each.to_a
|
|
275
296
|
|
|
276
|
-
|
|
277
|
-
|
|
297
|
+
assert_instance_of Wreq::Headers, headers
|
|
298
|
+
refute headers.empty?
|
|
299
|
+
assert headers.contains?("Content-Type")
|
|
300
|
+
assert_equal headers.length, pairs.length
|
|
278
301
|
end
|
|
279
302
|
|
|
280
|
-
def
|
|
281
|
-
|
|
282
|
-
|
|
303
|
+
def test_response_headers_are_fresh_mutable_snapshots
|
|
304
|
+
response = Wreq.get("#{HTTPBIN_URL}/response-headers", query: {"X-Test" => "original"})
|
|
305
|
+
first = response.headers
|
|
306
|
+
second = response.headers
|
|
307
|
+
|
|
308
|
+
refute_same first, second
|
|
309
|
+
first["X-Test"] = "changed"
|
|
310
|
+
first["X-Local"] = "value"
|
|
311
|
+
|
|
312
|
+
assert_equal "changed", first["X-Test"]
|
|
313
|
+
assert_equal "original", second["X-Test"]
|
|
314
|
+
assert_nil second["X-Local"]
|
|
315
|
+
assert_equal "original", response.headers["X-Test"]
|
|
316
|
+
end
|
|
283
317
|
|
|
284
|
-
|
|
285
|
-
headers2.set("X-Test", "value2")
|
|
318
|
+
private
|
|
286
319
|
|
|
287
|
-
|
|
288
|
-
|
|
320
|
+
def response_headers
|
|
321
|
+
Wreq.get(
|
|
322
|
+
"#{HTTPBIN_URL}/response-headers",
|
|
323
|
+
query: {"X-Custom-Header" => "custom-value"}
|
|
324
|
+
).headers
|
|
289
325
|
end
|
|
290
326
|
end
|
data/test/stream_test.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require "test_helper"
|
|
2
2
|
require "socket"
|
|
3
|
+
require "timeout"
|
|
3
4
|
|
|
4
5
|
class StreamTest < Minitest::Test
|
|
5
6
|
def test_simple_push_stream
|
|
@@ -174,6 +175,41 @@ class StreamTest < Minitest::Test
|
|
|
174
175
|
assert killed, "Connect+timeout phase should be interruptible"
|
|
175
176
|
end
|
|
176
177
|
|
|
178
|
+
def test_thread_raise_propagates_ruby_interrupt
|
|
179
|
+
server = TCPServer.new("127.0.0.1", 0)
|
|
180
|
+
accepted = Queue.new
|
|
181
|
+
errors = Queue.new
|
|
182
|
+
|
|
183
|
+
server_thread = Thread.new do
|
|
184
|
+
socket = server.accept
|
|
185
|
+
accepted << true
|
|
186
|
+
sleep
|
|
187
|
+
ensure
|
|
188
|
+
socket&.close
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
request_thread = Thread.new do
|
|
192
|
+
Wreq.get("http://127.0.0.1:#{server.addr[1]}/", timeout: 60)
|
|
193
|
+
rescue Interrupt, StandardError => error
|
|
194
|
+
errors << error
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
Timeout.timeout(5) { accepted.pop }
|
|
198
|
+
request_thread.raise(Interrupt, "test interrupt")
|
|
199
|
+
|
|
200
|
+
assert request_thread.join(5), "Interrupted request thread should stop"
|
|
201
|
+
|
|
202
|
+
error = Timeout.timeout(1) { errors.pop }
|
|
203
|
+
assert_instance_of Interrupt, error
|
|
204
|
+
assert_equal "test interrupt", error.message
|
|
205
|
+
ensure
|
|
206
|
+
request_thread&.kill
|
|
207
|
+
request_thread&.join(1)
|
|
208
|
+
server_thread&.kill
|
|
209
|
+
server_thread&.join(1)
|
|
210
|
+
server&.close
|
|
211
|
+
end
|
|
212
|
+
|
|
177
213
|
def test_thread_interrupt_body_reading
|
|
178
214
|
url = "#{HTTPBIN_URL}/drip?duration=5&numbytes=5"
|
|
179
215
|
thread = Thread.new do
|
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.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- SearchApi
|
|
@@ -27,6 +27,58 @@ files:
|
|
|
27
27
|
- README.md
|
|
28
28
|
- Rakefile
|
|
29
29
|
- build.rs
|
|
30
|
+
- crates/wreq-util/.github/FUNDING.yml
|
|
31
|
+
- crates/wreq-util/.github/ISSUE_TEMPLATE/bug_report.md
|
|
32
|
+
- crates/wreq-util/.github/ISSUE_TEMPLATE/custom.md
|
|
33
|
+
- crates/wreq-util/.github/ISSUE_TEMPLATE/feature_request.md
|
|
34
|
+
- crates/wreq-util/.github/dependabot.yml
|
|
35
|
+
- crates/wreq-util/.github/workflows/ci.yml
|
|
36
|
+
- crates/wreq-util/.github/workflows/release-plz.yml
|
|
37
|
+
- crates/wreq-util/.gitignore
|
|
38
|
+
- crates/wreq-util/CHANGELOG.md
|
|
39
|
+
- crates/wreq-util/Cargo.toml
|
|
40
|
+
- crates/wreq-util/LICENSE
|
|
41
|
+
- crates/wreq-util/README.md
|
|
42
|
+
- crates/wreq-util/examples/emulate.rs
|
|
43
|
+
- crates/wreq-util/examples/tower_delay.rs
|
|
44
|
+
- crates/wreq-util/release-plz.toml
|
|
45
|
+
- crates/wreq-util/rustfmt.toml
|
|
46
|
+
- crates/wreq-util/src/emulate.rs
|
|
47
|
+
- crates/wreq-util/src/emulate/compress.rs
|
|
48
|
+
- crates/wreq-util/src/emulate/macros.rs
|
|
49
|
+
- crates/wreq-util/src/emulate/profile.rs
|
|
50
|
+
- crates/wreq-util/src/emulate/profile/chrome.rs
|
|
51
|
+
- crates/wreq-util/src/emulate/profile/chrome/header.rs
|
|
52
|
+
- crates/wreq-util/src/emulate/profile/chrome/http2.rs
|
|
53
|
+
- crates/wreq-util/src/emulate/profile/chrome/tls.rs
|
|
54
|
+
- crates/wreq-util/src/emulate/profile/firefox.rs
|
|
55
|
+
- crates/wreq-util/src/emulate/profile/firefox/header.rs
|
|
56
|
+
- crates/wreq-util/src/emulate/profile/firefox/http2.rs
|
|
57
|
+
- crates/wreq-util/src/emulate/profile/firefox/tls.rs
|
|
58
|
+
- crates/wreq-util/src/emulate/profile/okhttp.rs
|
|
59
|
+
- crates/wreq-util/src/emulate/profile/opera.rs
|
|
60
|
+
- crates/wreq-util/src/emulate/profile/opera/header.rs
|
|
61
|
+
- crates/wreq-util/src/emulate/profile/opera/http2.rs
|
|
62
|
+
- crates/wreq-util/src/emulate/profile/opera/tls.rs
|
|
63
|
+
- crates/wreq-util/src/emulate/profile/safari.rs
|
|
64
|
+
- crates/wreq-util/src/emulate/profile/safari/header.rs
|
|
65
|
+
- crates/wreq-util/src/emulate/profile/safari/http2.rs
|
|
66
|
+
- crates/wreq-util/src/emulate/profile/safari/tls.rs
|
|
67
|
+
- crates/wreq-util/src/lib.rs
|
|
68
|
+
- crates/wreq-util/src/rand.rs
|
|
69
|
+
- crates/wreq-util/src/tower.rs
|
|
70
|
+
- crates/wreq-util/src/tower/delay.rs
|
|
71
|
+
- crates/wreq-util/src/tower/delay/future.rs
|
|
72
|
+
- crates/wreq-util/src/tower/delay/layer.rs
|
|
73
|
+
- crates/wreq-util/src/tower/delay/service.rs
|
|
74
|
+
- crates/wreq-util/tests/client.rs
|
|
75
|
+
- crates/wreq-util/tests/emulate_chrome.rs
|
|
76
|
+
- crates/wreq-util/tests/emulate_firefox.rs
|
|
77
|
+
- crates/wreq-util/tests/emulate_okhttp.rs
|
|
78
|
+
- crates/wreq-util/tests/emulate_opera.rs
|
|
79
|
+
- crates/wreq-util/tests/emulate_safari.rs
|
|
80
|
+
- crates/wreq-util/tests/support/mod.rs
|
|
81
|
+
- crates/wreq-util/tests/support/server.rs
|
|
30
82
|
- docs/windows-gnu-tokio-crash.md
|
|
31
83
|
- examples/body.rb
|
|
32
84
|
- examples/client.rb
|
|
@@ -65,6 +117,7 @@ files:
|
|
|
65
117
|
- src/extractor.rs
|
|
66
118
|
- src/gvl.rs
|
|
67
119
|
- src/header.rs
|
|
120
|
+
- src/header/helper.rs
|
|
68
121
|
- src/http.rs
|
|
69
122
|
- src/lib.rs
|
|
70
123
|
- src/macros.rs
|