wreq 1.2.4-aarch64-linux → 1.2.5-aarch64-linux
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/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/LICENSE +201 -0
- data/crates/wreq-util/README.md +62 -0
- data/crates/wreq-util/release-plz.toml +2 -0
- data/crates/wreq-util/rustfmt.toml +5 -0
- data/examples/emulate_request.rb +1 -1
- data/lib/wreq.rb +20 -18
- data/lib/wreq_ruby/3.3/wreq_ruby.so +0 -0
- data/lib/wreq_ruby/3.4/wreq_ruby.so +0 -0
- data/lib/wreq_ruby/4.0/wreq_ruby.so +0 -0
- 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/test/header_test.rb +228 -192
- data/test/stream_test.rb +36 -0
- metadata +15 -2
data/lib/wreq_ruby/header.rb
CHANGED
|
@@ -2,202 +2,293 @@
|
|
|
2
2
|
|
|
3
3
|
unless defined?(Wreq)
|
|
4
4
|
module Wreq
|
|
5
|
-
# HTTP headers
|
|
5
|
+
# A mutable, case-insensitive collection of HTTP headers.
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
7
|
+
# Header names are normalized by the native header map and lookups are
|
|
8
|
+
# case-insensitive. Use the `orig_headers` request option when exact wire
|
|
9
|
+
# casing or header order is required. Duplicate values are stored as
|
|
10
|
+
# separate header occurrences.
|
|
9
11
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
+
# @example Build and query headers
|
|
13
|
+
# headers = Wreq::Headers.new(
|
|
14
|
+
# "Accept" => ["application/json", "text/plain"],
|
|
15
|
+
# content_type: "application/json"
|
|
16
|
+
# )
|
|
17
|
+
# headers["accept"] # => ["application/json", "text/plain"]
|
|
18
|
+
# headers[:content_type] # => "application/json"
|
|
12
19
|
#
|
|
13
|
-
# @example
|
|
14
|
-
# response = Wreq.get("https://example.com")
|
|
15
|
-
# headers = response.headers
|
|
16
|
-
# content_type = headers["Content-Type"]
|
|
17
|
-
# content_type = headers.get("content-type") # Same, case-insensitive
|
|
18
|
-
#
|
|
19
|
-
# @example Getting all values for a header
|
|
20
|
-
# accept_values = headers.get_all("Accept")
|
|
21
|
-
# # => ["application/json", "text/html"]
|
|
22
|
-
#
|
|
23
|
-
# @example Modifying headers
|
|
24
|
-
# headers.set("X-Custom-Header", "value")
|
|
25
|
-
# headers["Authorization"] = "Bearer token"
|
|
26
|
-
# headers.append("Accept", "application/xml")
|
|
27
|
-
#
|
|
28
|
-
# @example Iterating headers
|
|
20
|
+
# @example Iterate over every occurrence
|
|
29
21
|
# headers.each do |name, value|
|
|
30
22
|
# puts "#{name}: #{value}"
|
|
31
23
|
# end
|
|
32
|
-
#
|
|
33
|
-
# @example Converting to hash
|
|
34
|
-
# hash = headers.to_h
|
|
35
|
-
# hash["content-type"] # => "text/html"
|
|
36
24
|
class Headers
|
|
37
|
-
|
|
25
|
+
include Enumerable
|
|
26
|
+
|
|
27
|
+
# Create an empty collection or copy header pairs from a source.
|
|
38
28
|
#
|
|
39
|
-
# @
|
|
29
|
+
# @param source [Hash, Wreq::Headers, Enumerable] A hash, another
|
|
30
|
+
# headers collection, or an enumerable that yields name-value pairs.
|
|
31
|
+
# Omit this argument to create an empty collection.
|
|
32
|
+
# @return [Wreq::Headers]
|
|
33
|
+
# @raise [Wreq::BuilderError] if the source does not contain valid pairs
|
|
40
34
|
# @example
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
|
|
35
|
+
# Wreq::Headers.new
|
|
36
|
+
# Wreq::Headers.new("Accept" => "application/json")
|
|
37
|
+
# Wreq::Headers.new([[:content_type, "application/json"]])
|
|
38
|
+
def self.new(*args)
|
|
44
39
|
end
|
|
45
40
|
|
|
46
|
-
#
|
|
41
|
+
# Return the first value for a header.
|
|
47
42
|
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
# @param name [String] Header name (case-insensitive)
|
|
51
|
-
# @return [String, nil] Header value, or nil if not found
|
|
43
|
+
# @param name [String, Symbol] Header name
|
|
44
|
+
# @return [String, nil] The first value, or nil when the name is missing
|
|
52
45
|
# @example
|
|
53
|
-
# headers.get("
|
|
54
|
-
# headers.get(
|
|
55
|
-
# headers.get("X-Nonexistent") # => nil
|
|
46
|
+
# headers.get("content-type") # => "application/json"
|
|
47
|
+
# headers.get(:missing) # => nil
|
|
56
48
|
def get(name)
|
|
57
49
|
end
|
|
58
50
|
|
|
59
|
-
#
|
|
51
|
+
# Return a header using collection-style value semantics.
|
|
52
|
+
#
|
|
53
|
+
# A missing name returns nil, one occurrence returns a String, and
|
|
54
|
+
# multiple occurrences return an Array<String>.
|
|
60
55
|
#
|
|
61
|
-
#
|
|
56
|
+
# @param name [String, Symbol] Header name
|
|
57
|
+
# @return [String, Array<String>, nil]
|
|
58
|
+
# @example
|
|
59
|
+
# headers["accept"] # => "application/json"
|
|
60
|
+
# headers["set-cookie"] # => ["a=1", "b=2"]
|
|
61
|
+
def [](name)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Return every value for a header.
|
|
62
65
|
#
|
|
63
|
-
# @param name [String] Header name
|
|
64
|
-
# @return [Array<String>]
|
|
66
|
+
# @param name [String, Symbol] Header name
|
|
67
|
+
# @return [Array<String>] Values in insertion order, or an empty array
|
|
65
68
|
# @example
|
|
66
|
-
# headers.get_all("
|
|
67
|
-
# # => [
|
|
68
|
-
# headers.get_all("X-Nonexistent") # => []
|
|
69
|
+
# headers.get_all("set-cookie") # => ["a=1", "b=2"]
|
|
70
|
+
# headers.get_all(:missing) # => []
|
|
69
71
|
def get_all(name)
|
|
70
72
|
end
|
|
71
73
|
|
|
72
|
-
# Set
|
|
74
|
+
# Set one or more values, replacing every existing occurrence.
|
|
75
|
+
#
|
|
76
|
+
# Array values are stored as separate occurrences and are not joined. An
|
|
77
|
+
# empty Array removes the header.
|
|
73
78
|
#
|
|
74
|
-
# @param name [String] Header name
|
|
75
|
-
# @param value [String] Header value
|
|
79
|
+
# @param name [String, Symbol] Header name
|
|
80
|
+
# @param value [String, Array<String>] Header value or values
|
|
76
81
|
# @return [void]
|
|
77
|
-
# @raise [Wreq::BuilderError] if name or value
|
|
82
|
+
# @raise [Wreq::BuilderError] if a name or value is invalid
|
|
78
83
|
# @example
|
|
79
|
-
# headers.set("
|
|
80
|
-
# headers.set("X-Custom-Header", "my-value")
|
|
84
|
+
# headers.set("Accept", ["application/json", "text/plain"])
|
|
81
85
|
def set(name, value)
|
|
82
86
|
end
|
|
83
87
|
|
|
84
|
-
#
|
|
88
|
+
# Set one or more values and return the assigned value.
|
|
85
89
|
#
|
|
86
|
-
#
|
|
87
|
-
#
|
|
90
|
+
# @param name [String, Symbol] Header name
|
|
91
|
+
# @param value [String, Array<String>] Header value or values
|
|
92
|
+
# @return [String, Array<String>] The assigned value
|
|
93
|
+
# @example
|
|
94
|
+
# headers[:content_type] = "application/json"
|
|
95
|
+
def []=(name, value)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Append one or more values without replacing existing occurrences.
|
|
88
99
|
#
|
|
89
|
-
# @param name [String] Header name
|
|
90
|
-
# @param value [String] Header value
|
|
100
|
+
# @param name [String, Symbol] Header name
|
|
101
|
+
# @param value [String, Array<String>] Header value or values
|
|
91
102
|
# @return [void]
|
|
92
|
-
# @raise [Wreq::BuilderError] if name or value
|
|
103
|
+
# @raise [Wreq::BuilderError] if a name or value is invalid
|
|
93
104
|
# @example
|
|
94
|
-
# headers.
|
|
95
|
-
# headers.append("Accept", "text/html")
|
|
96
|
-
# headers.get_all("Accept") # => ["application/json", "text/html"]
|
|
105
|
+
# headers.append("Set-Cookie", ["a=1", "b=2"])
|
|
97
106
|
def append(name, value)
|
|
98
107
|
end
|
|
99
108
|
|
|
100
|
-
#
|
|
109
|
+
# Return a header value, a fallback, or the result of a block.
|
|
101
110
|
#
|
|
102
|
-
# @param name [String] Header name
|
|
103
|
-
# @
|
|
111
|
+
# @param name [String, Symbol] Header name
|
|
112
|
+
# @param default [Object] Optional fallback for a missing name
|
|
113
|
+
# @yieldparam name [String, Symbol] The missing name
|
|
114
|
+
# @return [String, Array<String>, Object]
|
|
115
|
+
# @raise [KeyError] if the name is missing and no fallback is provided
|
|
104
116
|
# @example
|
|
105
|
-
# headers.
|
|
106
|
-
# headers.
|
|
107
|
-
def
|
|
117
|
+
# headers.fetch("accept", "*/*")
|
|
118
|
+
# headers.fetch(:missing) { |name| "missing: #{name}" }
|
|
119
|
+
def fetch(name, default = nil)
|
|
108
120
|
end
|
|
109
121
|
|
|
110
|
-
#
|
|
122
|
+
# Remove every occurrence for a header.
|
|
111
123
|
#
|
|
112
|
-
# @param name [String] Header name
|
|
113
|
-
# @return [
|
|
124
|
+
# @param name [String, Symbol] Header name
|
|
125
|
+
# @return [String, nil] The first removed value, or nil when missing
|
|
114
126
|
# @example
|
|
115
|
-
# headers.
|
|
116
|
-
|
|
127
|
+
# headers.remove("authorization") # => "Bearer token"
|
|
128
|
+
def remove(name)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Remove every occurrence for a header. Alias for {#remove}.
|
|
132
|
+
#
|
|
133
|
+
# @param name [String, Symbol] Header name
|
|
134
|
+
# @return [String, nil] The first removed value, or nil when missing
|
|
135
|
+
def delete(name)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Check whether a header exists.
|
|
139
|
+
#
|
|
140
|
+
# @param name [String, Symbol] Header name
|
|
141
|
+
# @return [Boolean]
|
|
117
142
|
def contains?(name)
|
|
118
143
|
end
|
|
119
144
|
|
|
120
|
-
# Check
|
|
145
|
+
# Check whether a header exists. Alias for {#contains?}.
|
|
121
146
|
#
|
|
122
|
-
# @param name [String] Header name
|
|
123
|
-
# @return [Boolean]
|
|
124
|
-
# @example
|
|
125
|
-
# headers.key?("Accept") # => true
|
|
147
|
+
# @param name [String, Symbol] Header name
|
|
148
|
+
# @return [Boolean]
|
|
126
149
|
def key?(name)
|
|
127
150
|
end
|
|
128
151
|
|
|
129
|
-
#
|
|
152
|
+
# Return the number of header occurrences.
|
|
130
153
|
#
|
|
131
|
-
#
|
|
132
|
-
#
|
|
133
|
-
#
|
|
154
|
+
# This can be greater than `keys.length` when a name has multiple values.
|
|
155
|
+
#
|
|
156
|
+
# @return [Integer]
|
|
134
157
|
def length
|
|
135
158
|
end
|
|
136
159
|
|
|
137
|
-
#
|
|
160
|
+
# Return the number of header occurrences. Alias for {#length}.
|
|
138
161
|
#
|
|
139
|
-
# @return [
|
|
140
|
-
|
|
141
|
-
|
|
162
|
+
# @return [Integer]
|
|
163
|
+
def size
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Check whether the collection has no header occurrences.
|
|
167
|
+
#
|
|
168
|
+
# @return [Boolean]
|
|
142
169
|
def empty?
|
|
143
170
|
end
|
|
144
171
|
|
|
145
|
-
# Remove
|
|
172
|
+
# Remove every header occurrence.
|
|
146
173
|
#
|
|
147
|
-
# @return [
|
|
148
|
-
# @example
|
|
149
|
-
# headers.clear
|
|
150
|
-
# headers.empty? # => true
|
|
174
|
+
# @return [Wreq::Headers] self
|
|
151
175
|
def clear
|
|
152
176
|
end
|
|
153
177
|
|
|
154
|
-
#
|
|
178
|
+
# Return each unique header name.
|
|
155
179
|
#
|
|
156
|
-
# @return [Array<String>]
|
|
157
|
-
# @example
|
|
158
|
-
# headers.keys
|
|
159
|
-
# # => ["content-type", "accept", "user-agent", "authorization"]
|
|
180
|
+
# @return [Array<String>]
|
|
160
181
|
def keys
|
|
161
182
|
end
|
|
162
183
|
|
|
163
|
-
#
|
|
164
|
-
#
|
|
165
|
-
# Returns one value per header (the first if multiple values exist).
|
|
184
|
+
# Return every header value.
|
|
166
185
|
#
|
|
167
|
-
# @return [Array<String>]
|
|
168
|
-
# @example
|
|
169
|
-
# headers.values
|
|
170
|
-
# # => ["application/json", "text/html", "Mozilla/5.0", "Bearer token"]
|
|
186
|
+
# @return [Array<String>]
|
|
171
187
|
def values
|
|
172
188
|
end
|
|
173
189
|
|
|
174
|
-
# Iterate over
|
|
175
|
-
#
|
|
176
|
-
# Yields each header name and value pair. If a header has multiple values,
|
|
177
|
-
# only the first is yielded.
|
|
190
|
+
# Iterate over every header occurrence.
|
|
178
191
|
#
|
|
179
|
-
# @yieldparam name [String]
|
|
192
|
+
# @yieldparam name [String] Normalized lowercase header name
|
|
180
193
|
# @yieldparam value [String] Header value
|
|
181
|
-
# @return [Enumerator,
|
|
182
|
-
#
|
|
183
|
-
#
|
|
184
|
-
#
|
|
185
|
-
# end
|
|
186
|
-
# @example Without block
|
|
187
|
-
# enum = headers.each
|
|
188
|
-
# enum.to_a # => [["content-type", "text/html"], ...]
|
|
194
|
+
# @return [Enumerator, Wreq::Headers] An Enumerator without a block,
|
|
195
|
+
# otherwise self
|
|
196
|
+
# @example
|
|
197
|
+
# headers.each.to_a
|
|
189
198
|
def each
|
|
190
199
|
end
|
|
191
200
|
|
|
201
|
+
# Convert every occurrence to name-value pairs.
|
|
202
|
+
#
|
|
203
|
+
# @return [Array<Array(String, String)>]
|
|
204
|
+
# @example
|
|
205
|
+
# headers.to_a # => [["accept", "application/json"], ...]
|
|
206
|
+
def to_a
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Convert unique names to a Hash.
|
|
210
|
+
#
|
|
211
|
+
# Hash values use the same nil, String, or Array shape as {#[]}.
|
|
212
|
+
#
|
|
213
|
+
# @return [Hash{String => String, Array<String>}]
|
|
214
|
+
# @example
|
|
215
|
+
# headers.to_h # => {"accept" => "application/json"}
|
|
216
|
+
def to_h
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Convert unique names to a Hash. Alias for {#to_h}.
|
|
220
|
+
#
|
|
221
|
+
# @return [Hash{String => String, Array<String>}]
|
|
222
|
+
def to_hash
|
|
223
|
+
end
|
|
224
|
+
|
|
192
225
|
# Convert headers to a string representation.
|
|
226
|
+
#
|
|
227
|
+
# @return [String] String representation of the headers
|
|
193
228
|
def to_s
|
|
194
229
|
end
|
|
230
|
+
|
|
231
|
+
# Return a compact representation for debugging.
|
|
232
|
+
#
|
|
233
|
+
# @return [String]
|
|
234
|
+
# @example
|
|
235
|
+
# headers.inspect # => "#<Wreq::Headers [2 headers]>"
|
|
236
|
+
def inspect
|
|
237
|
+
end
|
|
195
238
|
end
|
|
196
239
|
end
|
|
197
240
|
end
|
|
198
241
|
|
|
242
|
+
# ======================== Ruby API Extensions ========================
|
|
243
|
+
|
|
199
244
|
module Wreq
|
|
200
245
|
class Headers
|
|
246
|
+
FETCH_UNDEFINED = Object.new.freeze
|
|
247
|
+
private_constant :FETCH_UNDEFINED
|
|
248
|
+
|
|
249
|
+
alias delete remove
|
|
250
|
+
alias size length
|
|
251
|
+
|
|
252
|
+
# Return a header value, a fallback, or the result of a block.
|
|
253
|
+
#
|
|
254
|
+
# The block takes precedence when both a default and block are provided.
|
|
255
|
+
#
|
|
256
|
+
# @param name [String, Symbol] Header name
|
|
257
|
+
# @param default [Object] Optional fallback for a missing name
|
|
258
|
+
# @yieldparam name [String, Symbol] The missing name
|
|
259
|
+
# @return [String, Array<String>, Object]
|
|
260
|
+
# @raise [KeyError] if the name is missing and no fallback is provided
|
|
261
|
+
def fetch(name, default = FETCH_UNDEFINED)
|
|
262
|
+
value = self[name]
|
|
263
|
+
return value unless value.nil?
|
|
264
|
+
return yield(name) if block_given?
|
|
265
|
+
return default unless default.equal?(FETCH_UNDEFINED)
|
|
266
|
+
|
|
267
|
+
raise KeyError, "key not found: #{name.inspect}"
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
# Convert every header occurrence to a name-value pair.
|
|
271
|
+
#
|
|
272
|
+
# @return [Array<Array(String, String)>]
|
|
273
|
+
def to_a
|
|
274
|
+
each.to_a
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
# Convert unique normalized names to a Hash.
|
|
278
|
+
#
|
|
279
|
+
# A name with one occurrence maps to a String, while multiple occurrences
|
|
280
|
+
# map to an Array<String>.
|
|
281
|
+
#
|
|
282
|
+
# @return [Hash{String => String, Array<String>}]
|
|
283
|
+
def to_h
|
|
284
|
+
keys.to_h { |name| [name, self[name]] }
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
alias to_hash to_h
|
|
288
|
+
|
|
289
|
+
# Return a compact representation for debugging.
|
|
290
|
+
#
|
|
291
|
+
# @return [String]
|
|
201
292
|
def inspect
|
|
202
293
|
"#<Wreq::Headers [#{length} headers]>"
|
|
203
294
|
end
|
data/lib/wreq_ruby/response.rb
CHANGED
|
@@ -64,6 +64,19 @@ unless defined?(Wreq)
|
|
|
64
64
|
def content_length
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
# Get the response headers.
|
|
68
|
+
#
|
|
69
|
+
# Header names are case-insensitive. Use {Wreq::Headers#get_all} to get
|
|
70
|
+
# every value when a header appears more than once. Each call returns a
|
|
71
|
+
# fresh, mutable snapshot. Changing that snapshot does not change the
|
|
72
|
+
# response or a later snapshot, and object identity is not guaranteed.
|
|
73
|
+
#
|
|
74
|
+
# @return [Wreq::Headers] Response headers
|
|
75
|
+
# @example
|
|
76
|
+
# response.headers.get("content-type") # => "application/json"
|
|
77
|
+
def headers
|
|
78
|
+
end
|
|
79
|
+
|
|
67
80
|
# Get the local socket address.
|
|
68
81
|
#
|
|
69
82
|
# @return [String, nil] Local address (e.g., "127.0.0.1:54321"), or nil
|
|
@@ -80,6 +93,18 @@ unless defined?(Wreq)
|
|
|
80
93
|
def remote_addr
|
|
81
94
|
end
|
|
82
95
|
|
|
96
|
+
# Get cookies parsed from the response's `Set-Cookie` headers.
|
|
97
|
+
#
|
|
98
|
+
# Invalid `Set-Cookie` values are skipped.
|
|
99
|
+
#
|
|
100
|
+
# @return [Array<Wreq::Cookie>] Parsed response cookies
|
|
101
|
+
# @example
|
|
102
|
+
# response.cookies.each do |cookie|
|
|
103
|
+
# puts "#{cookie.name}=#{cookie.value}"
|
|
104
|
+
# end
|
|
105
|
+
def cookies
|
|
106
|
+
end
|
|
107
|
+
|
|
83
108
|
# Get the response bytes as a binary string.
|
|
84
109
|
# @return [String] Response body as binary data
|
|
85
110
|
# @example
|
|
@@ -91,13 +116,13 @@ unless defined?(Wreq)
|
|
|
91
116
|
# Get the response body as text with a specific charset.
|
|
92
117
|
# This method allows you to specify a default encoding
|
|
93
118
|
# to use when decoding the response body.
|
|
94
|
-
#
|
|
95
|
-
#
|
|
119
|
+
# @param default_encoding [String] Default encoding to use (e.g., "UTF-8")
|
|
120
|
+
# @return [String] Response body decoded as text using the specified encoding
|
|
96
121
|
# @example
|
|
97
122
|
# html = response.text("ISO-8859-1")
|
|
98
123
|
# puts html
|
|
99
124
|
# @raise [Wreq::DecodingError] if body cannot be decoded with the specified encoding
|
|
100
|
-
def text(default_encoding
|
|
125
|
+
def text(default_encoding = "UTF-8")
|
|
101
126
|
end
|
|
102
127
|
|
|
103
128
|
# Parse the response body as JSON.
|