http 6.0.0-java
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 +7 -0
- data/CHANGELOG.md +267 -0
- data/CONTRIBUTING.md +26 -0
- data/LICENSE.txt +20 -0
- data/README.md +263 -0
- data/SECURITY.md +17 -0
- data/UPGRADING.md +491 -0
- data/http.gemspec +48 -0
- data/lib/http/base64.rb +22 -0
- data/lib/http/chainable/helpers.rb +62 -0
- data/lib/http/chainable/verbs.rb +136 -0
- data/lib/http/chainable.rb +377 -0
- data/lib/http/client.rb +230 -0
- data/lib/http/connection/internals.rb +141 -0
- data/lib/http/connection.rb +265 -0
- data/lib/http/content_type.rb +89 -0
- data/lib/http/errors.rb +67 -0
- data/lib/http/feature.rb +86 -0
- data/lib/http/features/auto_deflate.rb +230 -0
- data/lib/http/features/auto_inflate.rb +64 -0
- data/lib/http/features/caching/entry.rb +178 -0
- data/lib/http/features/caching/in_memory_store.rb +63 -0
- data/lib/http/features/caching.rb +216 -0
- data/lib/http/features/digest_auth.rb +234 -0
- data/lib/http/features/instrumentation.rb +149 -0
- data/lib/http/features/logging.rb +231 -0
- data/lib/http/features/normalize_uri.rb +34 -0
- data/lib/http/features/raise_error.rb +37 -0
- data/lib/http/form_data/composite_io.rb +106 -0
- data/lib/http/form_data/file.rb +95 -0
- data/lib/http/form_data/multipart/param.rb +62 -0
- data/lib/http/form_data/multipart.rb +106 -0
- data/lib/http/form_data/part.rb +52 -0
- data/lib/http/form_data/readable.rb +58 -0
- data/lib/http/form_data/urlencoded.rb +175 -0
- data/lib/http/form_data/version.rb +8 -0
- data/lib/http/form_data.rb +102 -0
- data/lib/http/headers/known.rb +90 -0
- data/lib/http/headers/normalizer.rb +50 -0
- data/lib/http/headers.rb +343 -0
- data/lib/http/mime_type/adapter.rb +43 -0
- data/lib/http/mime_type/json.rb +41 -0
- data/lib/http/mime_type.rb +96 -0
- data/lib/http/options/definitions.rb +189 -0
- data/lib/http/options.rb +241 -0
- data/lib/http/redirector.rb +157 -0
- data/lib/http/request/body.rb +181 -0
- data/lib/http/request/builder.rb +184 -0
- data/lib/http/request/proxy.rb +83 -0
- data/lib/http/request/writer.rb +186 -0
- data/lib/http/request.rb +375 -0
- data/lib/http/response/body.rb +172 -0
- data/lib/http/response/inflater.rb +60 -0
- data/lib/http/response/parser.rb +223 -0
- data/lib/http/response/status/reasons.rb +79 -0
- data/lib/http/response/status.rb +263 -0
- data/lib/http/response.rb +350 -0
- data/lib/http/retriable/delay_calculator.rb +91 -0
- data/lib/http/retriable/errors.rb +35 -0
- data/lib/http/retriable/performer.rb +197 -0
- data/lib/http/session.rb +280 -0
- data/lib/http/timeout/global.rb +229 -0
- data/lib/http/timeout/null.rb +225 -0
- data/lib/http/timeout/per_operation.rb +197 -0
- data/lib/http/uri/normalizer.rb +82 -0
- data/lib/http/uri/parsing.rb +182 -0
- data/lib/http/uri.rb +376 -0
- data/lib/http/version.rb +6 -0
- data/lib/http.rb +36 -0
- data/sig/deps.rbs +122 -0
- data/sig/http.rbs +1619 -0
- data/test/http/base64_test.rb +28 -0
- data/test/http/client_test.rb +739 -0
- data/test/http/connection_test.rb +1533 -0
- data/test/http/content_type_test.rb +190 -0
- data/test/http/errors_test.rb +28 -0
- data/test/http/feature_test.rb +49 -0
- data/test/http/features/auto_deflate_test.rb +317 -0
- data/test/http/features/auto_inflate_test.rb +213 -0
- data/test/http/features/caching_test.rb +942 -0
- data/test/http/features/digest_auth_test.rb +996 -0
- data/test/http/features/instrumentation_test.rb +246 -0
- data/test/http/features/logging_test.rb +654 -0
- data/test/http/features/normalize_uri_test.rb +41 -0
- data/test/http/features/raise_error_test.rb +77 -0
- data/test/http/form_data/composite_io_test.rb +215 -0
- data/test/http/form_data/file_test.rb +255 -0
- data/test/http/form_data/fixtures/the-http-gem.info +1 -0
- data/test/http/form_data/multipart_test.rb +303 -0
- data/test/http/form_data/part_test.rb +90 -0
- data/test/http/form_data/urlencoded_test.rb +164 -0
- data/test/http/form_data_test.rb +232 -0
- data/test/http/headers/normalizer_test.rb +93 -0
- data/test/http/headers_test.rb +888 -0
- data/test/http/mime_type/json_test.rb +39 -0
- data/test/http/mime_type_test.rb +150 -0
- data/test/http/options/base_uri_test.rb +148 -0
- data/test/http/options/body_test.rb +21 -0
- data/test/http/options/features_test.rb +38 -0
- data/test/http/options/form_test.rb +21 -0
- data/test/http/options/headers_test.rb +32 -0
- data/test/http/options/json_test.rb +21 -0
- data/test/http/options/merge_test.rb +78 -0
- data/test/http/options/new_test.rb +37 -0
- data/test/http/options/proxy_test.rb +32 -0
- data/test/http/options_test.rb +575 -0
- data/test/http/redirector_test.rb +639 -0
- data/test/http/request/body_test.rb +318 -0
- data/test/http/request/builder_test.rb +623 -0
- data/test/http/request/writer_test.rb +391 -0
- data/test/http/request_test.rb +1733 -0
- data/test/http/response/body_test.rb +292 -0
- data/test/http/response/parser_test.rb +105 -0
- data/test/http/response/status_test.rb +322 -0
- data/test/http/response_test.rb +502 -0
- data/test/http/retriable/delay_calculator_test.rb +194 -0
- data/test/http/retriable/errors_test.rb +71 -0
- data/test/http/retriable/performer_test.rb +551 -0
- data/test/http/session_test.rb +424 -0
- data/test/http/timeout/global_test.rb +239 -0
- data/test/http/timeout/null_test.rb +218 -0
- data/test/http/timeout/per_operation_test.rb +220 -0
- data/test/http/uri/normalizer_test.rb +89 -0
- data/test/http/uri_test.rb +1140 -0
- data/test/http/version_test.rb +15 -0
- data/test/http_test.rb +818 -0
- data/test/regression_tests.rb +27 -0
- data/test/support/capture_warning.rb +10 -0
- data/test/support/dummy_server/encoding_routes.rb +47 -0
- data/test/support/dummy_server/routes.rb +201 -0
- data/test/support/dummy_server/servlet.rb +81 -0
- data/test/support/dummy_server.rb +200 -0
- data/test/support/fakeio.rb +21 -0
- data/test/support/http_handling_shared/connection_reuse_tests.rb +97 -0
- data/test/support/http_handling_shared/timeout_tests.rb +134 -0
- data/test/support/http_handling_shared.rb +11 -0
- data/test/support/proxy_server.rb +207 -0
- data/test/support/servers/runner.rb +67 -0
- data/test/support/simplecov.rb +28 -0
- data/test/support/ssl_helper.rb +108 -0
- data/test/test_helper.rb +38 -0
- metadata +218 -0
data/lib/http/uri.rb
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
module HTTP
|
|
6
|
+
# HTTP URI with scheme, authority, path, query, and fragment components
|
|
7
|
+
#
|
|
8
|
+
# Stores URI components as instance variables. Addressable is only used
|
|
9
|
+
# when parsing non-ASCII (IRI) strings; ASCII URIs use stdlib's URI.parse.
|
|
10
|
+
class URI
|
|
11
|
+
# The URI given was not valid
|
|
12
|
+
class InvalidError < HTTP::RequestError; end
|
|
13
|
+
|
|
14
|
+
# URI scheme (e.g. "http", "https")
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
# uri.scheme # => "http"
|
|
18
|
+
#
|
|
19
|
+
# @api public
|
|
20
|
+
# @return [String, nil] The URI scheme
|
|
21
|
+
attr_reader :scheme
|
|
22
|
+
|
|
23
|
+
# User component for authentication
|
|
24
|
+
#
|
|
25
|
+
# @example
|
|
26
|
+
# uri.user # => "admin"
|
|
27
|
+
#
|
|
28
|
+
# @api public
|
|
29
|
+
# @return [String, nil] The user component
|
|
30
|
+
attr_reader :user
|
|
31
|
+
|
|
32
|
+
# Password component for authentication
|
|
33
|
+
#
|
|
34
|
+
# @example
|
|
35
|
+
# uri.password # => "secret"
|
|
36
|
+
#
|
|
37
|
+
# @api public
|
|
38
|
+
# @return [String, nil] The password component
|
|
39
|
+
attr_reader :password
|
|
40
|
+
|
|
41
|
+
# Host, either a domain name or IP address
|
|
42
|
+
#
|
|
43
|
+
# @example
|
|
44
|
+
# uri.host # => "example.com"
|
|
45
|
+
#
|
|
46
|
+
# @api public
|
|
47
|
+
# @return [String, nil] The host of the URI
|
|
48
|
+
attr_reader :host
|
|
49
|
+
|
|
50
|
+
# Normalized host
|
|
51
|
+
#
|
|
52
|
+
# @example
|
|
53
|
+
# uri.normalized_host # => "example.com"
|
|
54
|
+
#
|
|
55
|
+
# @api public
|
|
56
|
+
# @return [String, nil] The normalized host of the URI
|
|
57
|
+
attr_reader :normalized_host
|
|
58
|
+
|
|
59
|
+
# URI path component
|
|
60
|
+
#
|
|
61
|
+
# @example
|
|
62
|
+
# uri.path # => "/foo"
|
|
63
|
+
#
|
|
64
|
+
# @api public
|
|
65
|
+
# @return [String] The path component
|
|
66
|
+
attr_accessor :path
|
|
67
|
+
|
|
68
|
+
# URI query string
|
|
69
|
+
#
|
|
70
|
+
# @example
|
|
71
|
+
# uri.query # => "q=1"
|
|
72
|
+
#
|
|
73
|
+
# @api public
|
|
74
|
+
# @return [String, nil] The query component
|
|
75
|
+
attr_accessor :query
|
|
76
|
+
|
|
77
|
+
# URI fragment
|
|
78
|
+
#
|
|
79
|
+
# @example
|
|
80
|
+
# uri.fragment # => "section1"
|
|
81
|
+
#
|
|
82
|
+
# @api public
|
|
83
|
+
# @return [String, nil] The fragment component
|
|
84
|
+
attr_reader :fragment
|
|
85
|
+
|
|
86
|
+
# HTTP scheme string
|
|
87
|
+
# @private
|
|
88
|
+
HTTP_SCHEME = "http"
|
|
89
|
+
|
|
90
|
+
# HTTPS scheme string
|
|
91
|
+
# @private
|
|
92
|
+
HTTPS_SCHEME = "https"
|
|
93
|
+
|
|
94
|
+
# Pattern matching characters requiring percent-encoding
|
|
95
|
+
# @private
|
|
96
|
+
PERCENT_ENCODE = /[^\x21-\x7E]+/
|
|
97
|
+
|
|
98
|
+
# Default ports for supported URI schemes
|
|
99
|
+
# @private
|
|
100
|
+
DEFAULT_PORTS = {
|
|
101
|
+
"http" => 80,
|
|
102
|
+
"https" => 443,
|
|
103
|
+
"ws" => 80,
|
|
104
|
+
"wss" => 443
|
|
105
|
+
}.freeze
|
|
106
|
+
|
|
107
|
+
# Pattern for characters that stdlib's URI.parse silently modifies
|
|
108
|
+
# @private
|
|
109
|
+
NEEDS_ADDRESSABLE = /[^\x20-\x7E]/
|
|
110
|
+
|
|
111
|
+
# Creates an HTTP::URI instance from the given keyword arguments
|
|
112
|
+
#
|
|
113
|
+
# @example
|
|
114
|
+
# HTTP::URI.new(scheme: "http", host: "example.com")
|
|
115
|
+
#
|
|
116
|
+
# @param [String, nil] scheme URI scheme
|
|
117
|
+
# @param [String, nil] user for basic authentication
|
|
118
|
+
# @param [String, nil] password for basic authentication
|
|
119
|
+
# @param [String, nil] host name component (IPv6 addresses must be bracketed)
|
|
120
|
+
# @param [Integer, nil] port network port to connect to
|
|
121
|
+
# @param [String, nil] path component to request
|
|
122
|
+
# @param [String, nil] query component distinct from path
|
|
123
|
+
# @param [String, nil] fragment component at the end of the URI
|
|
124
|
+
#
|
|
125
|
+
# @api public
|
|
126
|
+
# @return [HTTP::URI] new URI instance
|
|
127
|
+
def initialize(scheme: nil, user: nil, password: nil, host: nil,
|
|
128
|
+
port: nil, path: nil, query: nil, fragment: nil)
|
|
129
|
+
@scheme = scheme
|
|
130
|
+
@user = user
|
|
131
|
+
@password = password
|
|
132
|
+
@raw_host = host
|
|
133
|
+
@host = process_ipv6_brackets(host)
|
|
134
|
+
@normalized_host = normalize_host(@host)
|
|
135
|
+
@port = port
|
|
136
|
+
@path = path || ""
|
|
137
|
+
@query = query
|
|
138
|
+
@fragment = fragment
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Are these URI objects equal after normalization
|
|
142
|
+
#
|
|
143
|
+
# @example
|
|
144
|
+
# HTTP::URI.parse("http://example.com") == HTTP::URI.parse("http://example.com")
|
|
145
|
+
#
|
|
146
|
+
# @param [Object] other URI to compare this one with
|
|
147
|
+
#
|
|
148
|
+
# @api public
|
|
149
|
+
# @return [TrueClass, FalseClass] are the URIs equivalent (after normalization)?
|
|
150
|
+
def ==(other)
|
|
151
|
+
other.is_a?(URI) && String(normalize).eql?(String(other.normalize))
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Are these URI objects equal without normalization
|
|
155
|
+
#
|
|
156
|
+
# @example
|
|
157
|
+
# uri = HTTP::URI.parse("http://example.com")
|
|
158
|
+
# uri.eql?(HTTP::URI.parse("http://example.com"))
|
|
159
|
+
#
|
|
160
|
+
# @param [Object] other URI to compare this one with
|
|
161
|
+
#
|
|
162
|
+
# @api public
|
|
163
|
+
# @return [TrueClass, FalseClass] are the URIs equivalent?
|
|
164
|
+
def eql?(other)
|
|
165
|
+
other.is_a?(URI) && String(self).eql?(String(other))
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Hash value based off the normalized form of a URI
|
|
169
|
+
#
|
|
170
|
+
# @example
|
|
171
|
+
# HTTP::URI.parse("http://example.com").hash
|
|
172
|
+
#
|
|
173
|
+
# @api public
|
|
174
|
+
# @return [Integer] A hash of the URI
|
|
175
|
+
def hash
|
|
176
|
+
@hash ||= [self.class, String(self)].hash
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Sets the host component for the URI
|
|
180
|
+
#
|
|
181
|
+
# @example
|
|
182
|
+
# uri = HTTP::URI.parse("http://example.com")
|
|
183
|
+
# uri.host = "other.com"
|
|
184
|
+
#
|
|
185
|
+
# @param [String, #to_str] new_host The new host component
|
|
186
|
+
# @api public
|
|
187
|
+
# @return [void]
|
|
188
|
+
def host=(new_host)
|
|
189
|
+
@raw_host = process_ipv6_brackets(new_host, brackets: true)
|
|
190
|
+
@host = process_ipv6_brackets(@raw_host)
|
|
191
|
+
@normalized_host = normalize_host(@host)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Port number, either as specified or the default
|
|
195
|
+
#
|
|
196
|
+
# @example
|
|
197
|
+
# HTTP::URI.parse("http://example.com").port
|
|
198
|
+
#
|
|
199
|
+
# @api public
|
|
200
|
+
# @return [Integer, nil] port number
|
|
201
|
+
def port
|
|
202
|
+
@port || default_port
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Default port for the URI scheme
|
|
206
|
+
#
|
|
207
|
+
# @example
|
|
208
|
+
# HTTP::URI.parse("http://example.com").default_port # => 80
|
|
209
|
+
#
|
|
210
|
+
# @api public
|
|
211
|
+
# @return [Integer, nil] default port or nil for unknown schemes
|
|
212
|
+
def default_port
|
|
213
|
+
DEFAULT_PORTS[@scheme&.downcase]
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# The origin (scheme + host + port) per RFC 6454
|
|
217
|
+
#
|
|
218
|
+
# @example
|
|
219
|
+
# HTTP::URI.parse("http://example.com").origin # => "http://example.com"
|
|
220
|
+
#
|
|
221
|
+
# @api public
|
|
222
|
+
# @return [String] origin of the URI
|
|
223
|
+
def origin
|
|
224
|
+
port_suffix = ":#{port}" unless port.eql?(default_port)
|
|
225
|
+
"#{String(@scheme).downcase}://#{String(@raw_host).downcase}#{port_suffix}"
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# The path and query for use in an HTTP request line
|
|
229
|
+
#
|
|
230
|
+
# @example
|
|
231
|
+
# HTTP::URI.parse("http://example.com/path?q=1").request_uri # => "/path?q=1"
|
|
232
|
+
#
|
|
233
|
+
# @api public
|
|
234
|
+
# @return [String] request URI string
|
|
235
|
+
def request_uri
|
|
236
|
+
"#{'/' if @path.empty?}#{@path}#{"?#{@query}" if @query}"
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# Returns a new URI with the specified components removed
|
|
240
|
+
#
|
|
241
|
+
# @example
|
|
242
|
+
# HTTP::URI.parse("http://example.com#frag").omit(:fragment)
|
|
243
|
+
#
|
|
244
|
+
# @param components [Symbol] URI components to remove
|
|
245
|
+
# @api public
|
|
246
|
+
# @return [HTTP::URI] new URI without the specified components
|
|
247
|
+
def omit(*components)
|
|
248
|
+
self.class.new(
|
|
249
|
+
**{ scheme: @scheme, user: @user, password: @password, host: @raw_host,
|
|
250
|
+
port: @port, path: @path, query: @query, fragment: @fragment }.except(*components)
|
|
251
|
+
)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
# Resolves another URI against this one per RFC 3986
|
|
255
|
+
#
|
|
256
|
+
# @example
|
|
257
|
+
# HTTP::URI.parse("http://example.com/foo/").join("bar")
|
|
258
|
+
#
|
|
259
|
+
# @param [String, URI] other the URI to resolve
|
|
260
|
+
#
|
|
261
|
+
# @api public
|
|
262
|
+
# @return [HTTP::URI] resolved URI
|
|
263
|
+
def join(other)
|
|
264
|
+
base = self.class.percent_encode(String(self))
|
|
265
|
+
ref = self.class.percent_encode(String(other))
|
|
266
|
+
self.class.parse(::URI.join(base, ref))
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Returns a normalized copy of the URI
|
|
270
|
+
#
|
|
271
|
+
# Lowercases scheme and host, strips default port. Used by {#==}
|
|
272
|
+
# to compare URIs for equivalence.
|
|
273
|
+
#
|
|
274
|
+
# @example
|
|
275
|
+
# HTTP::URI.parse("HTTP://EXAMPLE.COM:80").normalize
|
|
276
|
+
#
|
|
277
|
+
# @api public
|
|
278
|
+
# @return [HTTP::URI] normalized URI
|
|
279
|
+
def normalize
|
|
280
|
+
self.class.new(
|
|
281
|
+
scheme: @scheme&.downcase,
|
|
282
|
+
user: @user,
|
|
283
|
+
password: @password,
|
|
284
|
+
host: @raw_host&.downcase,
|
|
285
|
+
port: (@port unless port.eql?(default_port)),
|
|
286
|
+
path: @path.empty? && @raw_host ? "/" : @path,
|
|
287
|
+
query: @query,
|
|
288
|
+
fragment: @fragment
|
|
289
|
+
)
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# Checks whether the URI scheme is HTTP
|
|
293
|
+
#
|
|
294
|
+
# @example
|
|
295
|
+
# HTTP::URI.parse("http://example.com").http?
|
|
296
|
+
#
|
|
297
|
+
# @api public
|
|
298
|
+
# @return [True] if URI is HTTP
|
|
299
|
+
# @return [False] otherwise
|
|
300
|
+
def http?
|
|
301
|
+
HTTP_SCHEME.eql?(@scheme)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# Checks whether the URI scheme is HTTPS
|
|
305
|
+
#
|
|
306
|
+
# @example
|
|
307
|
+
# HTTP::URI.parse("https://example.com").https?
|
|
308
|
+
#
|
|
309
|
+
# @api public
|
|
310
|
+
# @return [True] if URI is HTTPS
|
|
311
|
+
# @return [False] otherwise
|
|
312
|
+
def https?
|
|
313
|
+
HTTPS_SCHEME.eql?(@scheme)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Duplicates the URI object
|
|
317
|
+
#
|
|
318
|
+
# @example
|
|
319
|
+
# HTTP::URI.parse("http://example.com").dup
|
|
320
|
+
#
|
|
321
|
+
# @api public
|
|
322
|
+
# @return [HTTP::URI] duplicated URI
|
|
323
|
+
def dup
|
|
324
|
+
self.class.new(
|
|
325
|
+
scheme: @scheme, user: @user, password: @password, host: @raw_host,
|
|
326
|
+
port: @port, path: @path, query: @query, fragment: @fragment
|
|
327
|
+
)
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
# Convert an HTTP::URI to a String
|
|
331
|
+
#
|
|
332
|
+
# @example
|
|
333
|
+
# HTTP::URI.parse("http://example.com").to_s
|
|
334
|
+
#
|
|
335
|
+
# @api public
|
|
336
|
+
# @return [String] URI serialized as a String
|
|
337
|
+
def to_s
|
|
338
|
+
str = +""
|
|
339
|
+
str << "#{@scheme}:" if @scheme
|
|
340
|
+
str << authority_string if @raw_host
|
|
341
|
+
str << @path
|
|
342
|
+
str << "?#{@query}" if @query
|
|
343
|
+
str << "##{@fragment}" if @fragment
|
|
344
|
+
str
|
|
345
|
+
end
|
|
346
|
+
alias to_str to_s
|
|
347
|
+
|
|
348
|
+
# Returns human-readable representation of URI
|
|
349
|
+
#
|
|
350
|
+
# @example
|
|
351
|
+
# HTTP::URI.parse("http://example.com").inspect
|
|
352
|
+
#
|
|
353
|
+
# @api public
|
|
354
|
+
# @return [String] human-readable representation of URI
|
|
355
|
+
def inspect
|
|
356
|
+
format("#<%s:0x%014x URI:%s>", self.class, object_id << 1, self)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# Pattern matching interface
|
|
360
|
+
#
|
|
361
|
+
# @example
|
|
362
|
+
# uri.deconstruct_keys(%i[scheme host])
|
|
363
|
+
#
|
|
364
|
+
# @param keys [Array<Symbol>, nil] keys to extract, or nil for all
|
|
365
|
+
# @return [Hash{Symbol => Object}]
|
|
366
|
+
# @api public
|
|
367
|
+
def deconstruct_keys(keys)
|
|
368
|
+
hash = { scheme: @scheme, host: @host, port: port, path: @path,
|
|
369
|
+
query: @query, fragment: @fragment, user: @user, password: @password }
|
|
370
|
+
keys ? hash.slice(*keys) : hash
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
require "http/uri/parsing"
|
|
376
|
+
require "http/uri/normalizer"
|
data/lib/http/version.rb
ADDED
data/lib/http.rb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "http/errors"
|
|
4
|
+
require "http/timeout/null"
|
|
5
|
+
require "http/timeout/per_operation"
|
|
6
|
+
require "http/timeout/global"
|
|
7
|
+
require "http/chainable"
|
|
8
|
+
require "http/session"
|
|
9
|
+
require "http/client"
|
|
10
|
+
require "http/connection"
|
|
11
|
+
require "http/options"
|
|
12
|
+
require "http/feature"
|
|
13
|
+
require "http/request"
|
|
14
|
+
require "http/request/writer"
|
|
15
|
+
require "http/response"
|
|
16
|
+
require "http/response/body"
|
|
17
|
+
require "http/response/parser"
|
|
18
|
+
|
|
19
|
+
# HTTP should be easy
|
|
20
|
+
module HTTP
|
|
21
|
+
extend Chainable
|
|
22
|
+
|
|
23
|
+
class << self
|
|
24
|
+
# Set default headers and return a chainable session
|
|
25
|
+
#
|
|
26
|
+
# @example
|
|
27
|
+
# HTTP[:accept => "text/html"].get("https://example.com")
|
|
28
|
+
#
|
|
29
|
+
# @param headers [Hash] headers to set
|
|
30
|
+
#
|
|
31
|
+
# @return [HTTP::Session]
|
|
32
|
+
#
|
|
33
|
+
# @api public
|
|
34
|
+
alias [] headers
|
|
35
|
+
end
|
|
36
|
+
end
|
data/sig/deps.rbs
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Overrides for stdlib RBS signatures
|
|
2
|
+
|
|
3
|
+
class ::StringIO
|
|
4
|
+
# Override: Ruby's StringIO#read accepts nil outbuf
|
|
5
|
+
def read: (?int? length, ?string? buf) -> String?
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
class ::File
|
|
9
|
+
# Override: Ruby's File.new accepts keyword args like binmode:
|
|
10
|
+
def initialize: (string | _ToPath | int file_name, ?string | int mode, ?int perm, **untyped) -> void
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class ::Pathname
|
|
14
|
+
# Override: Ruby's Pathname#open accepts keyword args like binmode:
|
|
15
|
+
def open: (?string | int mode, ?int perm, **untyped) -> ::File
|
|
16
|
+
| [T] (?string | int mode, ?int perm, **untyped) { (::File) -> T } -> T
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Stubs for external dependencies without RBS definitions
|
|
20
|
+
|
|
21
|
+
module Addressable
|
|
22
|
+
class URI
|
|
23
|
+
class InvalidURIError < StandardError
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.parse: (untyped) -> Addressable::URI
|
|
27
|
+
def self.form_encode: (untyped, ?bool) -> String
|
|
28
|
+
def self.normalize_path: (untyped) -> String
|
|
29
|
+
|
|
30
|
+
def initialize: (?untyped) -> void
|
|
31
|
+
def scheme: () -> String?
|
|
32
|
+
def scheme=: (untyped) -> untyped
|
|
33
|
+
def normalized_scheme: () -> String?
|
|
34
|
+
def authority: () -> String?
|
|
35
|
+
def normalized_authority: () -> String?
|
|
36
|
+
def user: () -> String?
|
|
37
|
+
def user=: (untyped) -> untyped
|
|
38
|
+
def password: () -> String?
|
|
39
|
+
def password=: (untyped) -> untyped
|
|
40
|
+
def host: () -> String?
|
|
41
|
+
def host=: (untyped) -> untyped
|
|
42
|
+
def normalized_host: () -> String?
|
|
43
|
+
def port: () -> Integer?
|
|
44
|
+
def port=: (untyped) -> untyped
|
|
45
|
+
def normalized_port: () -> Integer?
|
|
46
|
+
def path: () -> String
|
|
47
|
+
def path=: (untyped) -> untyped
|
|
48
|
+
def normalized_path: () -> String
|
|
49
|
+
def query: () -> String?
|
|
50
|
+
def query=: (untyped) -> untyped
|
|
51
|
+
def query_values: (?untyped?) -> untyped
|
|
52
|
+
def query_values=: (untyped) -> untyped
|
|
53
|
+
def normalized_query: () -> String?
|
|
54
|
+
def request_uri: () -> String
|
|
55
|
+
def request_uri=: (untyped) -> untyped
|
|
56
|
+
def fragment: () -> String?
|
|
57
|
+
def normalized_fragment: () -> String?
|
|
58
|
+
def fragment=: (untyped) -> untyped
|
|
59
|
+
def omit: (*Symbol) -> Addressable::URI
|
|
60
|
+
def join: (untyped) -> Addressable::URI
|
|
61
|
+
def normalize: () -> Addressable::URI
|
|
62
|
+
def origin: () -> String
|
|
63
|
+
def default_port: () -> Integer?
|
|
64
|
+
def to_s: () -> String
|
|
65
|
+
def ==: (untyped) -> bool
|
|
66
|
+
def eql?: (untyped) -> bool
|
|
67
|
+
def hash: () -> Integer
|
|
68
|
+
def dup: () -> Addressable::URI
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Override: stdlib zlib RBS incorrectly marks level/strategy as required
|
|
73
|
+
module Zlib
|
|
74
|
+
class GzipWriter
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def initialize: (untyped io, ?Integer? level, ?Integer? strategy, **untyped opts) -> void
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
module LLHttp
|
|
82
|
+
class Error < StandardError
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
class Parser
|
|
86
|
+
def initialize: (untyped, ?type: Symbol) -> void
|
|
87
|
+
def reset: () -> void
|
|
88
|
+
def <<: (String) -> void
|
|
89
|
+
def status_code: () -> Integer
|
|
90
|
+
def http_major: () -> Integer
|
|
91
|
+
def http_minor: () -> Integer
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class Delegate
|
|
95
|
+
def initialize: () -> void
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Supplement: Numeric#to_i and #to_f are not in the stdlib RBS
|
|
100
|
+
class Numeric
|
|
101
|
+
def to_i: () -> Integer
|
|
102
|
+
def to_f: () -> Float
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
module IO::WaitReadable
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
module IO::WaitWritable
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class IO
|
|
112
|
+
# Missing from rbs core (available since Ruby 3.2)
|
|
113
|
+
class TimeoutError < IOError
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
class EAGAINWaitReadable < Errno::EAGAIN
|
|
117
|
+
include IO::WaitReadable
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def wait_readable: (?Numeric?) -> (IO | true | nil)
|
|
121
|
+
def wait_writable: (?Numeric?) -> (IO | true | nil)
|
|
122
|
+
end
|