httpx 0.22.5 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/doc/release_notes/0_23_0.md +42 -0
- data/doc/release_notes/0_23_1.md +5 -0
- data/lib/httpx/adapters/datadog.rb +1 -1
- data/lib/httpx/adapters/faraday.rb +1 -1
- data/lib/httpx/adapters/sentry.rb +4 -4
- data/lib/httpx/adapters/webmock.rb +2 -2
- data/lib/httpx/buffer.rb +4 -0
- data/lib/httpx/chainable.rb +4 -4
- data/lib/httpx/connection/http1.rb +2 -2
- data/lib/httpx/connection/http2.rb +2 -3
- data/lib/httpx/connection.rb +29 -10
- data/lib/httpx/io/udp.rb +2 -0
- data/lib/httpx/io/unix.rb +1 -5
- data/lib/httpx/io.rb +0 -10
- data/lib/httpx/options.rb +16 -2
- data/lib/httpx/plugins/authentication/digest.rb +1 -1
- data/lib/httpx/plugins/aws_sdk_authentication.rb +1 -3
- data/lib/httpx/plugins/aws_sigv4.rb +1 -1
- data/lib/httpx/plugins/compression/brotli.rb +4 -4
- data/lib/httpx/plugins/compression/deflate.rb +12 -7
- data/lib/httpx/plugins/compression/gzip.rb +7 -5
- data/lib/httpx/plugins/compression.rb +9 -8
- data/lib/httpx/plugins/digest_authentication.rb +1 -4
- data/lib/httpx/plugins/follow_redirects.rb +1 -1
- data/lib/httpx/plugins/grpc/message.rb +3 -1
- data/lib/httpx/plugins/grpc.rb +3 -3
- data/lib/httpx/plugins/h2c.rb +5 -9
- data/lib/httpx/plugins/internal_telemetry.rb +16 -0
- data/lib/httpx/plugins/multipart.rb +14 -2
- data/lib/httpx/plugins/proxy/http.rb +4 -4
- data/lib/httpx/plugins/proxy.rb +65 -31
- data/lib/httpx/plugins/response_cache.rb +2 -2
- data/lib/httpx/plugins/retries.rb +49 -2
- data/lib/httpx/plugins/upgrade/h2.rb +3 -3
- data/lib/httpx/plugins/upgrade.rb +4 -7
- data/lib/httpx/plugins/webdav.rb +7 -7
- data/lib/httpx/pool.rb +1 -1
- data/lib/httpx/request.rb +23 -13
- data/lib/httpx/resolver/https.rb +37 -20
- data/lib/httpx/resolver/native.rb +131 -35
- data/lib/httpx/resolver.rb +26 -14
- data/lib/httpx/response.rb +14 -16
- data/lib/httpx/session.rb +1 -0
- data/lib/httpx/transcoder/body.rb +0 -1
- data/lib/httpx/transcoder/chunker.rb +0 -1
- data/lib/httpx/transcoder/form.rb +0 -1
- data/lib/httpx/transcoder/json.rb +0 -1
- data/lib/httpx/transcoder/xml.rb +0 -1
- data/lib/httpx/transcoder.rb +0 -2
- data/lib/httpx/version.rb +1 -1
- data/lib/httpx.rb +0 -1
- data/sig/buffer.rbs +1 -0
- data/sig/chainable.rbs +3 -3
- data/sig/connection.rbs +17 -6
- data/sig/errors.rbs +9 -0
- data/sig/httpx.rbs +3 -3
- data/sig/io/ssl.rbs +17 -0
- data/sig/io/tcp.rbs +57 -0
- data/sig/io/udp.rbs +20 -0
- data/sig/io/unix.rbs +10 -0
- data/sig/options.rbs +5 -1
- data/sig/plugins/compression.rbs +6 -2
- data/sig/plugins/cookies/jar.rbs +2 -2
- data/sig/plugins/grpc.rbs +3 -3
- data/sig/plugins/h2c.rbs +1 -1
- data/sig/plugins/proxy.rbs +1 -5
- data/sig/plugins/response_cache.rbs +1 -1
- data/sig/plugins/retries.rbs +28 -8
- data/sig/plugins/upgrade.rbs +5 -3
- data/sig/request.rbs +6 -2
- data/sig/resolver/https.rbs +3 -1
- data/sig/resolver/native.rbs +7 -2
- data/sig/resolver/resolver.rbs +0 -2
- data/sig/resolver/system.rbs +2 -0
- data/sig/resolver.rbs +8 -4
- data/sig/response.rbs +6 -2
- data/sig/session.rbs +10 -10
- data/sig/transcoder/xml.rbs +1 -1
- data/sig/transcoder.rbs +4 -5
- metadata +11 -5
- data/lib/httpx/registry.rb +0 -85
- data/sig/registry.rbs +0 -13
@@ -33,6 +33,7 @@ module HTTPX
|
|
33
33
|
super
|
34
34
|
@ns_index = 0
|
35
35
|
@resolver_options = DEFAULTS.merge(@options.resolver_options)
|
36
|
+
@socket_type = @resolver_options.fetch(:socket_type, :udp)
|
36
37
|
@nameserver = Array(@resolver_options[:nameserver]) if @resolver_options[:nameserver]
|
37
38
|
@ndots = @resolver_options[:ndots]
|
38
39
|
@search = Array(@resolver_options[:search]).map { |srch| srch.scan(/[^.]+/) }
|
@@ -156,7 +157,7 @@ module HTTPX
|
|
156
157
|
else
|
157
158
|
|
158
159
|
@timeouts.delete(host)
|
159
|
-
|
160
|
+
reset_hostname(h, reset_candidates: false)
|
160
161
|
|
161
162
|
return unless @queries.empty?
|
162
163
|
|
@@ -169,10 +170,49 @@ module HTTPX
|
|
169
170
|
|
170
171
|
def dread(wsize = @resolver_options[:packet_size])
|
171
172
|
loop do
|
173
|
+
wsize = @large_packet.capacity if @large_packet
|
174
|
+
|
172
175
|
siz = @io.read(wsize, @read_buffer)
|
173
|
-
return unless siz && siz.positive?
|
174
176
|
|
175
|
-
|
177
|
+
unless siz
|
178
|
+
ex = EOFError.new("descriptor closed")
|
179
|
+
ex.set_backtrace(caller)
|
180
|
+
raise ex
|
181
|
+
end
|
182
|
+
|
183
|
+
return unless siz.positive?
|
184
|
+
|
185
|
+
if @socket_type == :tcp
|
186
|
+
# packet may be incomplete, need to keep draining from the socket
|
187
|
+
if @large_packet
|
188
|
+
# large packet buffer already exists, continue pumping
|
189
|
+
@large_packet << @read_buffer
|
190
|
+
|
191
|
+
next unless @large_packet.full?
|
192
|
+
|
193
|
+
parse(@large_packet.to_s)
|
194
|
+
|
195
|
+
@socket_type = @resolver_options.fetch(:socket_type, :udp)
|
196
|
+
@large_packet = nil
|
197
|
+
transition(:closed)
|
198
|
+
return
|
199
|
+
else
|
200
|
+
size = @read_buffer[0, 2].unpack1("n")
|
201
|
+
|
202
|
+
if size > @read_buffer.bytesize
|
203
|
+
# only do buffer logic if it's worth it, and the whole packet isn't here already
|
204
|
+
@large_packet = Buffer.new(size)
|
205
|
+
@large_packet << @read_buffer.byteslice(2..-1)
|
206
|
+
|
207
|
+
next
|
208
|
+
else
|
209
|
+
parse(@read_buffer)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
else # udp
|
213
|
+
parse(@read_buffer)
|
214
|
+
end
|
215
|
+
|
176
216
|
return if @state == :closed
|
177
217
|
end
|
178
218
|
end
|
@@ -182,41 +222,67 @@ module HTTPX
|
|
182
222
|
return if @write_buffer.empty?
|
183
223
|
|
184
224
|
siz = @io.write(@write_buffer)
|
185
|
-
|
225
|
+
|
226
|
+
unless siz
|
227
|
+
ex = EOFError.new("descriptor closed")
|
228
|
+
ex.set_backtrace(caller)
|
229
|
+
raise ex
|
230
|
+
end
|
231
|
+
|
232
|
+
return unless siz.positive?
|
186
233
|
|
187
234
|
return if @state == :closed
|
188
235
|
end
|
189
236
|
end
|
190
237
|
|
191
238
|
def parse(buffer)
|
192
|
-
|
193
|
-
addresses = Resolver.decode_dns_answer(buffer)
|
194
|
-
rescue Resolv::DNS::DecodeError => e
|
195
|
-
hostname, connection = @queries.first
|
196
|
-
@queries.delete(hostname)
|
197
|
-
@timeouts.delete(hostname)
|
198
|
-
@connections.delete(connection)
|
199
|
-
ex = NativeResolveError.new(connection, connection.origin.host, e.message)
|
200
|
-
ex.set_backtrace(e.backtrace)
|
201
|
-
raise ex
|
202
|
-
end
|
239
|
+
code, result = Resolver.decode_dns_answer(buffer)
|
203
240
|
|
204
|
-
|
241
|
+
case code
|
242
|
+
when :ok
|
243
|
+
parse_addresses(result)
|
244
|
+
when :no_domain_found
|
205
245
|
# Indicates no such domain was found.
|
206
246
|
hostname, connection = @queries.first
|
207
|
-
|
208
|
-
@timeouts.delete(hostname)
|
247
|
+
reset_hostname(hostname, reset_candidates: false)
|
209
248
|
|
210
249
|
unless @queries.value?(connection)
|
211
250
|
@connections.delete(connection)
|
212
|
-
raise NativeResolveError.new(connection, connection.origin.host)
|
251
|
+
raise NativeResolveError.new(connection, connection.origin.host, "name or service not known")
|
213
252
|
end
|
214
|
-
|
253
|
+
|
254
|
+
resolve
|
255
|
+
when :message_truncated
|
256
|
+
# TODO: what to do if it's already tcp??
|
257
|
+
return if @socket_type == :tcp
|
258
|
+
|
259
|
+
@socket_type = :tcp
|
260
|
+
|
261
|
+
hostname, _ = @queries.first
|
262
|
+
reset_hostname(hostname)
|
263
|
+
transition(:closed)
|
264
|
+
when :dns_error
|
265
|
+
hostname, connection = @queries.first
|
266
|
+
reset_hostname(hostname)
|
267
|
+
@connections.delete(connection)
|
268
|
+
ex = NativeResolveError.new(connection, connection.origin.host, "unknown DNS error (error code #{result})")
|
269
|
+
ex.set_backtrace(e.backtrace)
|
270
|
+
raise ex
|
271
|
+
when :decode_error
|
272
|
+
hostname, connection = @queries.first
|
273
|
+
reset_hostname(hostname)
|
274
|
+
@connections.delete(connection)
|
275
|
+
ex = NativeResolveError.new(connection, connection.origin.host, result.message)
|
276
|
+
ex.set_backtrace(result.backtrace)
|
277
|
+
raise ex
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
def parse_addresses(addresses)
|
282
|
+
if addresses.empty?
|
215
283
|
# no address found, eliminate candidates
|
216
284
|
_, connection = @queries.first
|
217
|
-
|
218
|
-
@queries.delete_if { |hs, _| candidates.include?(hs) }
|
219
|
-
@timeouts.delete_if { |hs, _| candidates.include?(hs) }
|
285
|
+
reset_hostname(hostname)
|
220
286
|
@connections.delete(connection)
|
221
287
|
raise NativeResolveError.new(connection, connection.origin.host)
|
222
288
|
else
|
@@ -226,20 +292,21 @@ module HTTPX
|
|
226
292
|
connection = @queries.delete(name)
|
227
293
|
|
228
294
|
unless connection
|
295
|
+
orig_name = name
|
229
296
|
# absolute name
|
230
297
|
name_labels = Resolv::DNS::Name.create(name).to_a
|
231
|
-
name = @queries.
|
298
|
+
name = @queries.each_key.first { |hname| name_labels == Resolv::DNS::Name.create(hname).to_a }
|
232
299
|
|
233
300
|
# probably a retried query for which there's an answer
|
234
|
-
|
301
|
+
unless name
|
302
|
+
@timeouts.delete(orig_name)
|
303
|
+
return
|
304
|
+
end
|
235
305
|
|
236
306
|
address["name"] = name
|
237
307
|
connection = @queries.delete(name)
|
238
308
|
end
|
239
309
|
|
240
|
-
# eliminate other candidates
|
241
|
-
@queries.delete_if { |_, conn| connection == conn }
|
242
|
-
|
243
310
|
if address.key?("alias") # CNAME
|
244
311
|
# clean up intermediate queries
|
245
312
|
@timeouts.delete(name) unless connection.origin.host == name
|
@@ -265,6 +332,7 @@ module HTTPX
|
|
265
332
|
|
266
333
|
def resolve(connection = @connections.first, hostname = nil)
|
267
334
|
raise Error, "no URI to resolve" unless connection
|
335
|
+
|
268
336
|
return unless @write_buffer.empty?
|
269
337
|
|
270
338
|
hostname ||= @queries.key(connection)
|
@@ -281,12 +349,19 @@ module HTTPX
|
|
281
349
|
end
|
282
350
|
log { "resolver: query #{@record_type.name.split("::").last} for #{hostname}" }
|
283
351
|
begin
|
284
|
-
@write_buffer <<
|
352
|
+
@write_buffer << encode_dns_query(hostname)
|
285
353
|
rescue Resolv::DNS::EncodeError => e
|
286
354
|
emit_resolve_error(connection, hostname, e)
|
287
355
|
end
|
288
356
|
end
|
289
357
|
|
358
|
+
def encode_dns_query(hostname)
|
359
|
+
message_id = Resolver.generate_id
|
360
|
+
msg = Resolver.encode_dns_query(hostname, type: @record_type, message_id: message_id)
|
361
|
+
msg[0, 2] = [msg.size, message_id].pack("nn") if @socket_type == :tcp
|
362
|
+
msg
|
363
|
+
end
|
364
|
+
|
290
365
|
def generate_candidates(name)
|
291
366
|
return [name] if name.end_with?(".")
|
292
367
|
|
@@ -294,18 +369,25 @@ module HTTPX
|
|
294
369
|
name_parts = name.scan(/[^.]+/)
|
295
370
|
candidates = [name] if @ndots <= name_parts.size - 1
|
296
371
|
candidates.concat(@search.map { |domain| [*name_parts, *domain].join(".") })
|
297
|
-
|
372
|
+
fname = "#{name}."
|
373
|
+
candidates << fname unless candidates.include?(fname)
|
298
374
|
|
299
375
|
candidates
|
300
376
|
end
|
301
377
|
|
302
378
|
def build_socket
|
303
|
-
return if @io
|
304
|
-
|
305
379
|
ip, port = @nameserver[@ns_index]
|
306
380
|
port ||= DNS_PORT
|
307
|
-
|
308
|
-
|
381
|
+
|
382
|
+
case @socket_type
|
383
|
+
when :udp
|
384
|
+
log { "resolver: server: udp://#{ip}:#{port}..." }
|
385
|
+
UDP.new(ip, port, @options)
|
386
|
+
when :tcp
|
387
|
+
log { "resolver: server: tcp://#{ip}:#{port}..." }
|
388
|
+
origin = URI("tcp://#{ip}:#{port}")
|
389
|
+
TCP.new(origin, [ip], @options)
|
390
|
+
end
|
309
391
|
end
|
310
392
|
|
311
393
|
def transition(nextstate)
|
@@ -319,7 +401,7 @@ module HTTPX
|
|
319
401
|
when :open
|
320
402
|
return unless @state == :idle
|
321
403
|
|
322
|
-
build_socket
|
404
|
+
@io ||= build_socket
|
323
405
|
|
324
406
|
@io.connect
|
325
407
|
return unless @io.connected?
|
@@ -346,5 +428,19 @@ module HTTPX
|
|
346
428
|
end
|
347
429
|
end
|
348
430
|
end
|
431
|
+
|
432
|
+
def reset_hostname(hostname, reset_candidates: true)
|
433
|
+
@timeouts.delete(hostname)
|
434
|
+
connection = @queries.delete(hostname)
|
435
|
+
@timeouts.delete(hostname)
|
436
|
+
|
437
|
+
return unless connection && reset_candidates
|
438
|
+
|
439
|
+
# eliminate other candidates
|
440
|
+
candidates = @queries.select { |_, conn| connection == conn }.keys
|
441
|
+
@queries.delete_if { |h, _| candidates.include?(h) }
|
442
|
+
# reset timeouts
|
443
|
+
@timeouts.delete_if { |h, _| candidates.include?(h) }
|
444
|
+
end
|
349
445
|
end
|
350
446
|
end
|
data/lib/httpx/resolver.rb
CHANGED
@@ -5,8 +5,6 @@ require "ipaddr"
|
|
5
5
|
|
6
6
|
module HTTPX
|
7
7
|
module Resolver
|
8
|
-
extend Registry
|
9
|
-
|
10
8
|
RESOLVE_TIMEOUT = 5
|
11
9
|
|
12
10
|
require "httpx/resolver/resolver"
|
@@ -15,10 +13,6 @@ module HTTPX
|
|
15
13
|
require "httpx/resolver/https"
|
16
14
|
require "httpx/resolver/multi"
|
17
15
|
|
18
|
-
register :system, System
|
19
|
-
register :native, Native
|
20
|
-
register :https, HTTPS
|
21
|
-
|
22
16
|
@lookup_mutex = Mutex.new
|
23
17
|
@lookups = Hash.new { |h, k| h[k] = [] }
|
24
18
|
|
@@ -28,6 +22,18 @@ module HTTPX
|
|
28
22
|
|
29
23
|
module_function
|
30
24
|
|
25
|
+
def resolver_for(resolver_type)
|
26
|
+
case resolver_type
|
27
|
+
when :native then Native
|
28
|
+
when :system then System
|
29
|
+
when :https then HTTPS
|
30
|
+
else
|
31
|
+
return resolver_type if resolver_type.is_a?(Class) && resolver_type < Resolver
|
32
|
+
|
33
|
+
raise Error, "unsupported resolver type (#{resolver_type})"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
31
37
|
def nolookup_resolve(hostname)
|
32
38
|
ip_resolve(hostname) || cached_lookup(hostname) || system_resolve(hostname)
|
33
39
|
end
|
@@ -98,24 +104,29 @@ module HTTPX
|
|
98
104
|
@identifier_mutex.synchronize { @identifier = (@identifier + 1) & 0xFFFF }
|
99
105
|
end
|
100
106
|
|
101
|
-
def encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A)
|
107
|
+
def encode_dns_query(hostname, type: Resolv::DNS::Resource::IN::A, message_id: generate_id)
|
102
108
|
Resolv::DNS::Message.new.tap do |query|
|
103
|
-
query.id =
|
109
|
+
query.id = message_id
|
104
110
|
query.rd = 1
|
105
111
|
query.add_question(hostname, type)
|
106
112
|
end.encode
|
107
113
|
end
|
108
114
|
|
109
115
|
def decode_dns_answer(payload)
|
110
|
-
|
116
|
+
begin
|
117
|
+
message = Resolv::DNS::Message.decode(payload)
|
118
|
+
rescue Resolv::DNS::DecodeError => e
|
119
|
+
return :decode_error, e
|
120
|
+
end
|
111
121
|
|
112
122
|
# no domain was found
|
113
|
-
return if message.rcode == Resolv::DNS::RCode::NXDomain
|
123
|
+
return :no_domain_found if message.rcode == Resolv::DNS::RCode::NXDomain
|
114
124
|
|
115
|
-
|
125
|
+
return :message_truncated if message.tc == 1
|
116
126
|
|
117
|
-
|
118
|
-
|
127
|
+
return :dns_error, message.rcode if message.rcode != Resolv::DNS::RCode::NoError
|
128
|
+
|
129
|
+
addresses = []
|
119
130
|
|
120
131
|
message.each_answer do |question, _, value|
|
121
132
|
case value
|
@@ -134,7 +145,8 @@ module HTTPX
|
|
134
145
|
}
|
135
146
|
end
|
136
147
|
end
|
137
|
-
|
148
|
+
|
149
|
+
[:ok, addresses]
|
138
150
|
end
|
139
151
|
end
|
140
152
|
end
|
data/lib/httpx/response.rb
CHANGED
@@ -56,12 +56,12 @@ module HTTPX
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def bodyless?
|
59
|
-
@request.verb ==
|
59
|
+
@request.verb == "HEAD" ||
|
60
60
|
no_data?
|
61
61
|
end
|
62
62
|
|
63
63
|
def complete?
|
64
|
-
bodyless? || (@request.verb ==
|
64
|
+
bodyless? || (@request.verb == "CONNECT" && @status == 200)
|
65
65
|
end
|
66
66
|
|
67
67
|
# :nocov:
|
@@ -87,32 +87,27 @@ module HTTPX
|
|
87
87
|
end
|
88
88
|
|
89
89
|
def json(*args)
|
90
|
-
decode(
|
90
|
+
decode(Transcoder::JSON, *args)
|
91
91
|
end
|
92
92
|
|
93
93
|
def form
|
94
|
-
decode(
|
94
|
+
decode(Transcoder::Form)
|
95
95
|
end
|
96
96
|
|
97
97
|
def xml
|
98
|
-
decode(
|
98
|
+
decode(Transcoder::Xml)
|
99
99
|
end
|
100
100
|
|
101
101
|
private
|
102
102
|
|
103
|
-
def decode(
|
103
|
+
def decode(transcoder, *args)
|
104
104
|
# TODO: check if content-type is a valid format, i.e. "application/json" for json parsing
|
105
|
-
transcoder = Transcoder.registry(format)
|
106
|
-
|
107
|
-
raise Error, "no decoder available for \"#{format}\"" unless transcoder.respond_to?(:decode)
|
108
105
|
|
109
106
|
decoder = transcoder.decode(self)
|
110
107
|
|
111
|
-
raise Error, "no decoder available for \"#{
|
108
|
+
raise Error, "no decoder available for \"#{transcoder}\"" unless decoder
|
112
109
|
|
113
110
|
decoder.call(self, *args)
|
114
|
-
rescue Registry::Error
|
115
|
-
raise Error, "no decoder available for \"#{format}\""
|
116
111
|
end
|
117
112
|
|
118
113
|
def no_data?
|
@@ -203,10 +198,8 @@ module HTTPX
|
|
203
198
|
rescue ArgumentError # ex: unknown encoding name - utf
|
204
199
|
content
|
205
200
|
end
|
206
|
-
when nil
|
207
|
-
"".b
|
208
201
|
else
|
209
|
-
|
202
|
+
"".b
|
210
203
|
end
|
211
204
|
end
|
212
205
|
alias_method :to_str, :to_s
|
@@ -334,12 +327,13 @@ module HTTPX
|
|
334
327
|
include Loggable
|
335
328
|
extend Forwardable
|
336
329
|
|
337
|
-
attr_reader :request, :error
|
330
|
+
attr_reader :request, :response, :error
|
338
331
|
|
339
332
|
def_delegator :@request, :uri
|
340
333
|
|
341
334
|
def initialize(request, error, options)
|
342
335
|
@request = request
|
336
|
+
@response = request.response if request.response.is_a?(Response)
|
343
337
|
@error = error
|
344
338
|
@options = Options.new(options)
|
345
339
|
log_exception(@error)
|
@@ -361,6 +355,10 @@ module HTTPX
|
|
361
355
|
end
|
362
356
|
end
|
363
357
|
|
358
|
+
def close
|
359
|
+
@response.close if @response.respond_to?(:close)
|
360
|
+
end
|
361
|
+
|
364
362
|
def finished?
|
365
363
|
true
|
366
364
|
end
|
data/lib/httpx/session.rb
CHANGED
data/lib/httpx/transcoder/xml.rb
CHANGED
data/lib/httpx/transcoder.rb
CHANGED
data/lib/httpx/version.rb
CHANGED
data/lib/httpx.rb
CHANGED
data/sig/buffer.rbs
CHANGED
data/sig/chainable.rbs
CHANGED
@@ -2,9 +2,9 @@ module HTTPX
|
|
2
2
|
module Chainable
|
3
3
|
def request: (*Request, **untyped) -> Array[response]
|
4
4
|
| (Request, **untyped) -> response
|
5
|
-
| (verb
|
6
|
-
| (Array[[verb
|
7
|
-
| (verb
|
5
|
+
| (verb, uri | [uri], **untyped) -> response
|
6
|
+
| (Array[[verb, uri] | [verb, uri, options]], **untyped) -> Array[response]
|
7
|
+
| (verb, _Each[uri | [uri, options]], **untyped) -> Array[response]
|
8
8
|
|
9
9
|
def accept: (String) -> Session
|
10
10
|
def wrap: () { (Session) -> void } -> void
|
data/sig/connection.rbs
CHANGED
@@ -17,9 +17,7 @@ module HTTPX
|
|
17
17
|
extend Forwardable
|
18
18
|
include Loggable
|
19
19
|
include Callbacks
|
20
|
-
include HTTPX::Registry[String, Class]
|
21
20
|
|
22
|
-
BUFFER_SIZE: Integer
|
23
21
|
|
24
22
|
attr_reader type: io_type
|
25
23
|
attr_reader origin: URI::Generic
|
@@ -36,7 +34,13 @@ module HTTPX
|
|
36
34
|
@write_buffer: Buffer
|
37
35
|
@inflight: Integer
|
38
36
|
@keep_alive_timeout: Numeric?
|
37
|
+
@timeout: Numeric?
|
38
|
+
@current_timeout: Numeric?
|
39
39
|
@total_timeout: Numeric?
|
40
|
+
@io: TCP | SSL | UNIX
|
41
|
+
@parser: HTTP1 | HTTP2 | _Parser
|
42
|
+
@connected_at: Float
|
43
|
+
@response_received_at: Float
|
40
44
|
|
41
45
|
def addresses: () -> Array[ipaddr]?
|
42
46
|
|
@@ -77,6 +81,8 @@ module HTTPX
|
|
77
81
|
|
78
82
|
def deactivate: () -> void
|
79
83
|
|
84
|
+
def open?: () -> bool
|
85
|
+
|
80
86
|
def raise_timeout_error: (Numeric interval) -> void
|
81
87
|
|
82
88
|
private
|
@@ -91,17 +97,20 @@ module HTTPX
|
|
91
97
|
|
92
98
|
def send_pending: () -> void
|
93
99
|
|
94
|
-
def parser: () -> _Parser
|
100
|
+
def parser: () -> (HTTP1 | HTTP2 | _Parser)
|
95
101
|
|
96
102
|
def send_request_to_parser: (Request request) -> void
|
97
103
|
|
98
|
-
def build_parser: () ->
|
99
|
-
| (String) -> _Parser
|
104
|
+
def build_parser: (?String protocol) -> (HTTP1 | HTTP2)
|
100
105
|
|
101
|
-
def set_parser_callbacks: (
|
106
|
+
def set_parser_callbacks: (HTTP1 | HTTP2 parser) -> void
|
102
107
|
|
103
108
|
def transition: (Symbol) -> void
|
104
109
|
|
110
|
+
def handle_transition: (Symbol) -> void
|
111
|
+
|
112
|
+
def build_socket: (?Array[ipaddr]? addrs) -> (TCP | SSL | UNIX)
|
113
|
+
|
105
114
|
def on_error: (HTTPX::TimeoutError | Error | StandardError) -> void
|
106
115
|
|
107
116
|
def handle_error: (StandardError) -> void
|
@@ -113,5 +122,7 @@ module HTTPX
|
|
113
122
|
def write_timeout_callback: (Request request, Numeric write_timeout) -> void
|
114
123
|
|
115
124
|
def read_timeout_callback: (Request request, Numeric read_timeout, ?singleton(RequestTimeoutError) error_type) -> void
|
125
|
+
|
126
|
+
def self.parser_type: (String protocol) -> (singleton(HTTP1) | singleton(HTTP2))
|
116
127
|
end
|
117
128
|
end
|
data/sig/errors.rbs
CHANGED
@@ -2,6 +2,12 @@ module HTTPX
|
|
2
2
|
class Error < StandardError
|
3
3
|
end
|
4
4
|
|
5
|
+
class UnsupportedSchemeError < Error
|
6
|
+
end
|
7
|
+
|
8
|
+
class ConnectionError < Error
|
9
|
+
end
|
10
|
+
|
5
11
|
class TimeoutError < Error
|
6
12
|
attr_reader timeout: Numeric
|
7
13
|
|
@@ -55,4 +61,7 @@ module HTTPX
|
|
55
61
|
|
56
62
|
def initialize: (Connection connection, String hostname, ?String message) -> untyped
|
57
63
|
end
|
64
|
+
|
65
|
+
class MisdirectedRequestError < HTTPError
|
66
|
+
end
|
58
67
|
end
|
data/sig/httpx.rbs
CHANGED
@@ -8,9 +8,9 @@ module HTTPX
|
|
8
8
|
type uri = URI::HTTP | URI::HTTPS | string
|
9
9
|
type generic_uri = String | URI::Generic
|
10
10
|
|
11
|
-
type verb =
|
12
|
-
|
13
|
-
|
11
|
+
type verb = "OPTIONS" | "GET" | "HEAD" | "POST" | "PUT" | "DELETE" | "TRACE" | "CONNECT" |
|
12
|
+
"PROPFIND" | "PROPPATCH" | "MKCOL" | "COPY" | "MOVE" | "LOCK" | "UNLOCK" | "ORDERPATCH" |
|
13
|
+
"ACL" | "REPORT" | "PATCH" | "SEARCH"
|
14
14
|
|
15
15
|
type ip_family = Integer #Socket::AF_INET6 | Socket::AF_INET
|
16
16
|
|
data/sig/io/ssl.rbs
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module HTTPX
|
2
|
+
IPRegex: Regexp
|
3
|
+
|
4
|
+
class TLSError < OpenSSL::SSL::SSLError
|
5
|
+
end
|
6
|
+
|
7
|
+
class SSL < TCP
|
8
|
+
TLS_OPTIONS: Hash[Symbol, untyped]
|
9
|
+
|
10
|
+
def can_verify_peer?: () -> bool
|
11
|
+
|
12
|
+
def verify_hostname: (String host) -> bool
|
13
|
+
|
14
|
+
# :nocov:
|
15
|
+
def try_ssl_connect: () -> void
|
16
|
+
end
|
17
|
+
end
|