wreq 1.2.4-x86_64-linux → 1.2.6-x86_64-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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/crates/wreq-util/.github/FUNDING.yml +15 -0
  3. data/crates/wreq-util/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. data/crates/wreq-util/.github/ISSUE_TEMPLATE/custom.md +10 -0
  5. data/crates/wreq-util/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  6. data/crates/wreq-util/.github/dependabot.yml +22 -0
  7. data/crates/wreq-util/.github/workflows/ci.yml +82 -0
  8. data/crates/wreq-util/.github/workflows/release-plz.yml +52 -0
  9. data/crates/wreq-util/.gitignore +24 -0
  10. data/crates/wreq-util/CHANGELOG.md +74 -0
  11. data/crates/wreq-util/LICENSE +201 -0
  12. data/crates/wreq-util/README.md +62 -0
  13. data/crates/wreq-util/release-plz.toml +2 -0
  14. data/crates/wreq-util/rustfmt.toml +5 -0
  15. data/examples/emulate_request.rb +1 -1
  16. data/lib/wreq.rb +72 -45
  17. data/lib/wreq_ruby/3.3/wreq_ruby.so +0 -0
  18. data/lib/wreq_ruby/3.4/wreq_ruby.so +0 -0
  19. data/lib/wreq_ruby/4.0/wreq_ruby.so +0 -0
  20. data/lib/wreq_ruby/body.rb +30 -9
  21. data/lib/wreq_ruby/client.rb +88 -55
  22. data/lib/wreq_ruby/cookie.rb +81 -21
  23. data/lib/wreq_ruby/emulate.rb +77 -7
  24. data/lib/wreq_ruby/error.rb +5 -7
  25. data/lib/wreq_ruby/header.rb +205 -114
  26. data/lib/wreq_ruby/http.rb +74 -0
  27. data/lib/wreq_ruby/response.rb +31 -3
  28. data/script/build_windows_gnu.ps1 +6 -0
  29. data/test/body_sender_test.rb +246 -0
  30. data/test/cookie_test.rb +211 -10
  31. data/test/header_test.rb +228 -192
  32. data/test/json_precision_test.rb +209 -0
  33. data/test/option_validation_test.rb +311 -0
  34. data/test/stream_test.rb +36 -0
  35. data/test/value_semantics_test.rb +238 -0
  36. metadata +19 -2
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Profile and platform constants mirror the native enum variant names.
4
+ # standard:disable Naming/ConstantName
5
+
3
6
  module Wreq
4
7
  # Browser and client fingerprint profile enumeration backed by Rust.
5
8
  #
@@ -58,6 +61,7 @@ module Wreq
58
61
  Chrome147 = nil
59
62
  Chrome148 = nil
60
63
  Chrome149 = nil
64
+ Chrome150 = nil
61
65
 
62
66
  Edge101 = nil
63
67
  Edge122 = nil
@@ -154,7 +158,7 @@ module Wreq
154
158
  Opera128 = nil
155
159
  Opera129 = nil
156
160
  Opera130 = nil
157
- Opera131 = nils
161
+ Opera131 = nil
158
162
  end
159
163
 
160
164
  unless method_defined?(:to_s)
@@ -163,6 +167,29 @@ module Wreq
163
167
  def to_s
164
168
  end
165
169
  end
170
+
171
+ unless method_defined?(:==)
172
+ # Value-based equality.
173
+ # @param other [Object]
174
+ # @return [Boolean]
175
+ def ==(other)
176
+ end
177
+ end
178
+
179
+ unless method_defined?(:eql?)
180
+ # Strict equality for Hash key and Set member semantics.
181
+ # @param other [Object]
182
+ # @return [Boolean]
183
+ def eql?(other)
184
+ end
185
+ end
186
+
187
+ unless method_defined?(:hash)
188
+ # Hash value consistent with {#eql?} for use as Hash keys.
189
+ # @return [Integer]
190
+ def hash
191
+ end
192
+ end
166
193
  end
167
194
 
168
195
  # Operating system platform enumeration backed by Rust.
@@ -194,6 +221,36 @@ module Wreq
194
221
  def to_s
195
222
  end
196
223
  end
224
+
225
+ unless method_defined?(:to_sym)
226
+ # Returns the platform as a lowercase symbol (e.g. :windows, :linux).
227
+ # @return [Symbol]
228
+ def to_sym
229
+ end
230
+ end
231
+
232
+ unless method_defined?(:==)
233
+ # Value-based equality.
234
+ # @param other [Object]
235
+ # @return [Boolean]
236
+ def ==(other)
237
+ end
238
+ end
239
+
240
+ unless method_defined?(:eql?)
241
+ # Strict equality for Hash key and Set member semantics.
242
+ # @param other [Object]
243
+ # @return [Boolean]
244
+ def eql?(other)
245
+ end
246
+ end
247
+
248
+ unless method_defined?(:hash)
249
+ # Hash value consistent with {#eql?} for use as Hash keys.
250
+ # @return [Integer]
251
+ def hash
252
+ end
253
+ end
197
254
  end
198
255
 
199
256
  # Emulation option wrapper.
@@ -215,18 +272,31 @@ module Wreq
215
272
  #
216
273
  # @param profile [Wreq::Profile, nil] Fingerprint profile to emulate
217
274
  # @param platform [Wreq::Platform, nil] Operating system platform to emulate
218
- # @param http2 [Boolean] Whether HTTP/2 support is enabled
219
- # @param headers [Boolean] Whether default emulation headers are enabled
275
+ # @param http2 [Boolean, nil] Whether HTTP/2 emulation is enabled; defaults
276
+ # to true when omitted or nil
277
+ # @param headers [Boolean, nil] Whether default emulation headers are enabled;
278
+ # defaults to true when omitted or nil
279
+ # @return [Wreq::Emulation] Configured emulation settings
280
+ # @raise [ArgumentError] if an option is unknown or extra arguments are given
281
+ # @raise [TypeError] if the option argument is not a Hash or a value has the
282
+ # wrong Ruby type
220
283
  class Emulation
221
284
  # Native fields and methods are set by the extension.
222
285
  # This stub is for documentation only.
223
- unless method_defined?(:new)
286
+ unless singleton_methods(false).include?(:new)
224
287
  # @param profile [Wreq::Profile, nil] Fingerprint profile to emulate
225
288
  # @param platform [Wreq::Platform, nil] Operating system platform to emulate
226
- # @param http2 [Boolean] Whether HTTP/2 support is enabled
227
- # @param headers [Boolean] Whether default emulation headers are enabled
228
- def self.new(profile: nil, platform: nil, http2: true, headers: true)
289
+ # @param http2 [Boolean, nil] Whether HTTP/2 emulation is enabled; defaults
290
+ # to true when omitted or nil
291
+ # @param headers [Boolean, nil] Whether default emulation headers are enabled;
292
+ # defaults to true when omitted or nil
293
+ # @return [Wreq::Emulation] Configured emulation settings
294
+ # @raise [ArgumentError] if an option is unknown or extra arguments are given
295
+ # @raise [TypeError] if an option or value has the wrong Ruby type
296
+ def self.new(**options)
229
297
  end
230
298
  end
231
299
  end
232
300
  end
301
+
302
+ # standard:enable Naming/ConstantName
@@ -88,7 +88,7 @@ unless defined?(Wreq)
88
88
  #
89
89
  # @example
90
90
  # begin
91
- # client = Wreq::Client.new(max_redirects: 3)
91
+ # client = Wreq::Client.new(allow_redirects: true, max_redirects: 3)
92
92
  # client.get("https://httpbin.io/redirect/10")
93
93
  # rescue Wreq::RedirectError => e
94
94
  # puts "Too many redirects: #{e.message}"
@@ -139,16 +139,14 @@ unless defined?(Wreq)
139
139
 
140
140
  # Configuration and builder errors
141
141
 
142
- # Client configuration is invalid.
142
+ # A native client or request configuration could not be built.
143
143
  #
144
- # Raised when the client is configured with invalid options.
144
+ # Raised when validated Ruby options cannot be represented by the native
145
+ # builder or request body.
145
146
  #
146
147
  # @example
147
148
  # begin
148
- # client = Wreq::Client.new(
149
- # proxy: "invalid://proxy",
150
- # timeout: -1
151
- # )
149
+ # client = Wreq::Client.new(proxy: "invalid://")
152
150
  # rescue Wreq::BuilderError => e
153
151
  # puts "Invalid configuration: #{e.message}"
154
152
  # end
@@ -2,202 +2,293 @@
2
2
 
3
3
  unless defined?(Wreq)
4
4
  module Wreq
5
- # HTTP headers collection.
5
+ # A mutable, case-insensitive collection of HTTP headers.
6
6
  #
7
- # Provides efficient access to HTTP headers with case-insensitive lookups.
8
- # Headers are created by the native extension and cannot be directly instantiated.
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
- # All header names are case-insensitive. Multiple values for the same header
11
- # are supported through the `get_all` method.
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 Accessing response headers
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
- # Create a new empty Headers collection.
25
+ include Enumerable
26
+
27
+ # Create an empty collection or copy header pairs from a source.
38
28
  #
39
- # @return [Wreq::Headers] New headers instance
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
- # headers = Wreq::Headers.new
42
- # headers.set("Content-Type", "application/json")
43
- def self.new
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
- # Get a header value by name (case-insensitive).
41
+ # Return the first value for a header.
47
42
  #
48
- # Returns the first value if multiple values exist for the same header.
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("Content-Type") # => "application/json"
54
- # headers.get("content-type") # => "application/json" (same)
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
- # Get all values for a header name (case-insensitive).
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
- # Useful when a header can have multiple values (e.g., Accept, Set-Cookie).
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 (case-insensitive)
64
- # @return [Array<String>] All values for this header (empty array if not found)
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("Accept")
67
- # # => ["application/json", "text/html", "application/xml"]
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 a header value, replacing any existing values.
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 contains invalid characters
82
+ # @raise [Wreq::BuilderError] if a name or value is invalid
78
83
  # @example
79
- # headers.set("Content-Type", "application/json")
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
- # Append a header value without replacing existing values.
88
+ # Set one or more values and return the assigned value.
85
89
  #
86
- # Adds a new value for the header, preserving any existing values.
87
- # Useful for headers that can have multiple values.
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 to append
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 contains invalid characters
103
+ # @raise [Wreq::BuilderError] if a name or value is invalid
93
104
  # @example
94
- # headers.set("Accept", "application/json")
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
- # Remove all values for a header name.
109
+ # Return a header value, a fallback, or the result of a block.
101
110
  #
102
- # @param name [String] Header name (case-insensitive)
103
- # @return [String, nil] The removed value (first one if multiple), or nil
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.remove("Authorization") # => "Bearer token"
106
- # headers.remove("X-Nonexistent") # => nil
107
- def remove(name)
117
+ # headers.fetch("accept", "*/*")
118
+ # headers.fetch(:missing) { |name| "missing: #{name}" }
119
+ def fetch(name, default = nil)
108
120
  end
109
121
 
110
- # Check if a header exists (case-insensitive).
122
+ # Remove every occurrence for a header.
111
123
  #
112
- # @param name [String] Header name
113
- # @return [Boolean] true if the header exists
124
+ # @param name [String, Symbol] Header name
125
+ # @return [String, nil] The first removed value, or nil when missing
114
126
  # @example
115
- # headers.contains?("Content-Type") # => true
116
- # headers.contains?("X-Missing") # => false
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 if a header key exists (alias for {#contains?}).
145
+ # Check whether a header exists. Alias for {#contains?}.
121
146
  #
122
- # @param name [String] Header name
123
- # @return [Boolean] true if the header exists
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
- # Get the number of headers.
152
+ # Return the number of header occurrences.
130
153
  #
131
- # @return [Integer] Total number of unique header names
132
- # @example
133
- # headers.length # => 12
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
- # Check if there are no headers.
160
+ # Return the number of header occurrences. Alias for {#length}.
138
161
  #
139
- # @return [Boolean] true if no headers exist
140
- # @example
141
- # headers.empty? # => false
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 all headers.
172
+ # Remove every header occurrence.
146
173
  #
147
- # @return [void]
148
- # @example
149
- # headers.clear
150
- # headers.empty? # => true
174
+ # @return [Wreq::Headers] self
151
175
  def clear
152
176
  end
153
177
 
154
- # Get all header names.
178
+ # Return each unique header name.
155
179
  #
156
- # @return [Array<String>] Array of header names (lowercase)
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
- # Get all header values.
164
- #
165
- # Returns one value per header (the first if multiple values exist).
184
+ # Return every header value.
166
185
  #
167
- # @return [Array<String>] Array of header values
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 headers.
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] Header name (lowercase)
192
+ # @yieldparam name [String] Normalized lowercase header name
180
193
  # @yieldparam value [String] Header value
181
- # @return [Enumerator, self] Returns enumerator if no block given, self otherwise
182
- # @example With block
183
- # headers.each do |name, value|
184
- # puts "#{name}: #{value}"
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
@@ -25,6 +25,43 @@ module Wreq
25
25
  TRACE = nil # @return [Wreq::Method] HTTP TRACE method
26
26
  PATCH = nil # @return [Wreq::Method] HTTP PATCH method
27
27
  end
28
+
29
+ # Returns the HTTP method token (e.g. "GET", "POST").
30
+ # @return [String]
31
+ unless method_defined?(:to_s)
32
+ def to_s
33
+ end
34
+ end
35
+
36
+ # Returns the HTTP method as a lowercase symbol (e.g. :get, :post).
37
+ # @return [Symbol]
38
+ unless method_defined?(:to_sym)
39
+ def to_sym
40
+ end
41
+ end
42
+
43
+ # Value-based equality. Returns true when both represent the same HTTP method.
44
+ # @param other [Object]
45
+ # @return [Boolean]
46
+ unless method_defined?(:==)
47
+ def ==(other)
48
+ end
49
+ end
50
+
51
+ # Strict equality for Hash key and Set member semantics.
52
+ # @param other [Object]
53
+ # @return [Boolean]
54
+ unless method_defined?(:eql?)
55
+ def eql?(other)
56
+ end
57
+ end
58
+
59
+ # Hash value consistent with {#eql?} for use as Hash keys.
60
+ # @return [Integer]
61
+ unless method_defined?(:hash)
62
+ def hash
63
+ end
64
+ end
28
65
  end
29
66
 
30
67
  # HTTP version enumeration backed by Rust.
@@ -63,6 +100,21 @@ module Wreq
63
100
  def ==(other)
64
101
  end
65
102
  end
103
+
104
+ # Strict equality for Hash key and Set member semantics.
105
+ # @param other [Object]
106
+ # @return [Boolean]
107
+ unless method_defined?(:eql?)
108
+ def eql?(other)
109
+ end
110
+ end
111
+
112
+ # Hash value consistent with {#eql?} for use as Hash keys.
113
+ # @return [Integer]
114
+ unless method_defined?(:hash)
115
+ def hash
116
+ end
117
+ end
66
118
  end
67
119
 
68
120
  # HTTP status code wrapper.
@@ -141,6 +193,28 @@ module Wreq
141
193
  # @return [String] Status code as string
142
194
  def to_s
143
195
  end
196
+
197
+ # Returns the status code as an integer.
198
+ # @return [Integer] the numeric HTTP status code
199
+ def to_i
200
+ end
201
+
202
+ # Value-based equality. Only compares with other StatusCode instances.
203
+ # @param other [Object]
204
+ # @return [Boolean]
205
+ def ==(other)
206
+ end
207
+
208
+ # Strict equality for Hash key and Set member semantics.
209
+ # @param other [Object]
210
+ # @return [Boolean]
211
+ def eql?(other)
212
+ end
213
+
214
+ # Hash value consistent with {#eql?} for use as Hash keys.
215
+ # @return [Integer]
216
+ def hash
217
+ end
144
218
  end
145
219
  end
146
220
  end