httpx 1.4.3 → 1.5.0

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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/doc/release_notes/1_4_4.md +14 -0
  3. data/doc/release_notes/1_5_0.md +126 -0
  4. data/lib/httpx/adapters/datadog.rb +24 -3
  5. data/lib/httpx/adapters/webmock.rb +3 -0
  6. data/lib/httpx/buffer.rb +16 -5
  7. data/lib/httpx/connection/http1.rb +8 -9
  8. data/lib/httpx/connection/http2.rb +48 -24
  9. data/lib/httpx/connection.rb +40 -20
  10. data/lib/httpx/errors.rb +2 -11
  11. data/lib/httpx/headers.rb +24 -23
  12. data/lib/httpx/io/ssl.rb +8 -4
  13. data/lib/httpx/io/tcp.rb +9 -7
  14. data/lib/httpx/io/unix.rb +1 -1
  15. data/lib/httpx/loggable.rb +13 -1
  16. data/lib/httpx/options.rb +63 -48
  17. data/lib/httpx/parser/http1.rb +1 -1
  18. data/lib/httpx/plugins/aws_sigv4.rb +1 -0
  19. data/lib/httpx/plugins/callbacks.rb +19 -6
  20. data/lib/httpx/plugins/circuit_breaker.rb +4 -3
  21. data/lib/httpx/plugins/cookies/jar.rb +0 -2
  22. data/lib/httpx/plugins/cookies/set_cookie_parser.rb +7 -4
  23. data/lib/httpx/plugins/cookies.rb +4 -4
  24. data/lib/httpx/plugins/follow_redirects.rb +4 -2
  25. data/lib/httpx/plugins/grpc/call.rb +1 -1
  26. data/lib/httpx/plugins/h2c.rb +7 -1
  27. data/lib/httpx/plugins/persistent.rb +22 -1
  28. data/lib/httpx/plugins/proxy/http.rb +3 -1
  29. data/lib/httpx/plugins/query.rb +35 -0
  30. data/lib/httpx/plugins/response_cache/file_store.rb +115 -15
  31. data/lib/httpx/plugins/response_cache/store.rb +7 -67
  32. data/lib/httpx/plugins/response_cache.rb +179 -29
  33. data/lib/httpx/plugins/retries.rb +27 -15
  34. data/lib/httpx/plugins/stream.rb +46 -20
  35. data/lib/httpx/plugins/stream_bidi.rb +315 -0
  36. data/lib/httpx/pool.rb +58 -5
  37. data/lib/httpx/request/body.rb +1 -1
  38. data/lib/httpx/request.rb +21 -5
  39. data/lib/httpx/resolver/https.rb +10 -4
  40. data/lib/httpx/resolver/native.rb +13 -13
  41. data/lib/httpx/resolver/resolver.rb +4 -0
  42. data/lib/httpx/resolver/system.rb +37 -14
  43. data/lib/httpx/resolver.rb +2 -2
  44. data/lib/httpx/response/body.rb +10 -21
  45. data/lib/httpx/response/buffer.rb +36 -12
  46. data/lib/httpx/response.rb +11 -1
  47. data/lib/httpx/selector.rb +16 -12
  48. data/lib/httpx/session.rb +80 -23
  49. data/lib/httpx/timers.rb +24 -16
  50. data/lib/httpx/transcoder/multipart/decoder.rb +4 -2
  51. data/lib/httpx/transcoder/multipart/encoder.rb +2 -1
  52. data/lib/httpx/version.rb +1 -1
  53. data/sig/buffer.rbs +1 -1
  54. data/sig/chainable.rbs +5 -2
  55. data/sig/connection/http2.rbs +11 -2
  56. data/sig/connection.rbs +4 -4
  57. data/sig/errors.rbs +0 -3
  58. data/sig/headers.rbs +15 -10
  59. data/sig/httpx.rbs +5 -1
  60. data/sig/io/tcp.rbs +6 -0
  61. data/sig/loggable.rbs +2 -0
  62. data/sig/options.rbs +7 -1
  63. data/sig/plugins/cookies/cookie.rbs +1 -3
  64. data/sig/plugins/cookies/jar.rbs +4 -4
  65. data/sig/plugins/cookies/set_cookie_parser.rbs +22 -0
  66. data/sig/plugins/cookies.rbs +2 -0
  67. data/sig/plugins/h2c.rbs +4 -0
  68. data/sig/plugins/proxy/http.rbs +3 -0
  69. data/sig/plugins/proxy.rbs +4 -0
  70. data/sig/plugins/response_cache/file_store.rbs +19 -0
  71. data/sig/plugins/response_cache/store.rbs +13 -0
  72. data/sig/plugins/response_cache.rbs +41 -19
  73. data/sig/plugins/retries.rbs +4 -3
  74. data/sig/plugins/stream.rbs +8 -1
  75. data/sig/plugins/stream_bidi.rbs +68 -0
  76. data/sig/plugins/upgrade/h2.rbs +9 -0
  77. data/sig/plugins/upgrade.rbs +5 -0
  78. data/sig/pool.rbs +5 -0
  79. data/sig/punycode.rbs +5 -0
  80. data/sig/request.rbs +7 -0
  81. data/sig/resolver/https.rbs +3 -2
  82. data/sig/resolver/native.rbs +1 -2
  83. data/sig/resolver/resolver.rbs +11 -3
  84. data/sig/resolver/system.rbs +19 -2
  85. data/sig/resolver.rbs +11 -7
  86. data/sig/response/body.rbs +3 -4
  87. data/sig/response/buffer.rbs +2 -3
  88. data/sig/response.rbs +2 -2
  89. data/sig/selector.rbs +20 -10
  90. data/sig/session.rbs +14 -6
  91. data/sig/timers.rbs +5 -7
  92. data/sig/transcoder/multipart.rbs +4 -3
  93. metadata +14 -5
  94. data/lib/httpx/session2.rb +0 -23
  95. data/lib/httpx/transcoder/utils/inflater.rb +0 -21
  96. data/sig/transcoder/utils/inflater.rbs +0 -12
data/lib/httpx/session.rb CHANGED
@@ -15,11 +15,11 @@ module HTTPX
15
15
  # When pass a block, it'll yield itself to it, then closes after the block is evaluated.
16
16
  def initialize(options = EMPTY_HASH, &blk)
17
17
  @options = self.class.default_options.merge(options)
18
- @responses = {}
19
18
  @persistent = @options.persistent
20
19
  @pool = @options.pool_class.new(@options.pool_options)
21
20
  @wrapped = false
22
21
  @closing = false
22
+ INSTANCES[self] = self if @persistent && @options.close_on_fork && INSTANCES
23
23
  wrap(&blk) if blk
24
24
  end
25
25
 
@@ -174,11 +174,15 @@ module HTTPX
174
174
  # returns the HTTPX::Connection through which the +request+ should be sent through.
175
175
  def find_connection(request_uri, selector, options)
176
176
  if (connection = selector.find_connection(request_uri, options))
177
+ connection.idling if connection.state == :closed
178
+ connection.log(level: 2) { "found connection##{connection.object_id}(#{connection.state}) in selector##{selector.object_id}" }
177
179
  return connection
178
180
  end
179
181
 
180
182
  connection = @pool.checkout_connection(request_uri, options)
181
183
 
184
+ connection.log(level: 2) { "found connection##{connection.object_id}(#{connection.state}) in pool##{@pool.object_id}" }
185
+
182
186
  case connection.state
183
187
  when :idle
184
188
  do_init_connection(connection, selector)
@@ -188,14 +192,9 @@ module HTTPX
188
192
  else
189
193
  pin_connection(connection, selector)
190
194
  end
191
- when :closed
195
+ when :closing, :closed
192
196
  connection.idling
193
197
  select_connection(connection, selector)
194
- when :closing
195
- connection.once(:close) do
196
- connection.idling
197
- select_connection(connection, selector)
198
- end
199
198
  else
200
199
  pin_connection(connection, selector)
201
200
  end
@@ -212,11 +211,6 @@ module HTTPX
212
211
  end
213
212
  end
214
213
 
215
- # callback executed when a response for a given request has been received.
216
- def on_response(request, response)
217
- @responses[request] = response
218
- end
219
-
220
214
  # callback executed when an HTTP/2 promise frame has been received.
221
215
  def on_promise(_, stream)
222
216
  log(level: 2) { "#{stream.id}: refusing stream!" }
@@ -225,7 +219,9 @@ module HTTPX
225
219
 
226
220
  # returns the corresponding HTTP::Response to the given +request+ if it has been received.
227
221
  def fetch_response(request, _selector, _options)
228
- @responses.delete(request)
222
+ response = request.response
223
+
224
+ response if response && response.finished?
229
225
  end
230
226
 
231
227
  # sends the +request+ to the corresponding HTTPX::Connection
@@ -242,7 +238,9 @@ module HTTPX
242
238
 
243
239
  raise error unless error.is_a?(Error)
244
240
 
245
- request.emit(:response, ErrorResponse.new(request, error))
241
+ response = ErrorResponse.new(request, error)
242
+ request.response = response
243
+ request.emit(:response, response)
246
244
  end
247
245
 
248
246
  # returns a set of HTTPX::Request objects built from the given +args+ and +options+.
@@ -272,7 +270,6 @@ module HTTPX
272
270
  end
273
271
 
274
272
  def set_request_callbacks(request)
275
- request.on(:response, &method(:on_response).curry(2)[request])
276
273
  request.on(:promise, &method(:on_promise))
277
274
  end
278
275
 
@@ -367,13 +364,12 @@ module HTTPX
367
364
 
368
365
  return select_connection(connection, selector) unless found_connection
369
366
 
370
- if found_connection.open?
371
- coalesce_connections(found_connection, connection, selector, from_pool)
372
- else
373
- found_connection.once(:open) do
374
- coalesce_connections(found_connection, connection, selector, from_pool)
375
- end
367
+ connection.log(level: 2) do
368
+ "try coalescing from #{from_pool ? "pool##{@pool.object_id}" : "selector##{selector.object_id}"} " \
369
+ "(conn##{found_connection.object_id}[#{found_connection.origin}])"
376
370
  end
371
+
372
+ coalesce_connections(found_connection, connection, selector, from_pool)
377
373
  end
378
374
 
379
375
  def on_resolver_close(resolver, selector)
@@ -399,14 +395,16 @@ module HTTPX
399
395
  # (it is known via +from_pool+), then it adds its to the +selector+.
400
396
  def coalesce_connections(conn1, conn2, selector, from_pool)
401
397
  unless conn1.coalescable?(conn2)
398
+ conn2.log(level: 2) { "not coalescing with conn##{conn1.object_id}[#{conn1.origin}])" }
402
399
  select_connection(conn2, selector)
403
400
  @pool.checkin_connection(conn1) if from_pool
404
401
  return false
405
402
  end
406
403
 
407
- conn2.coalesced_connection = conn1
404
+ conn2.log(level: 2) { "coalescing with conn##{conn1.object_id}[#{conn1.origin}])" }
405
+ conn2.coalesce!(conn1)
408
406
  select_connection(conn1, selector) if from_pool
409
- deselect_connection(conn2, selector)
407
+ conn2.disconnect
410
408
  true
411
409
  end
412
410
 
@@ -451,6 +449,7 @@ module HTTPX
451
449
  # session_with_custom = session.plugin(CustomPlugin)
452
450
  #
453
451
  def plugin(pl, options = nil, &block)
452
+ label = pl
454
453
  # raise Error, "Cannot add a plugin to a frozen config" if frozen?
455
454
  pl = Plugins.load_plugin(pl) if pl.is_a?(Symbol)
456
455
  if !@plugins.include?(pl)
@@ -475,9 +474,36 @@ module HTTPX
475
474
  @default_options = pl.extra_options(@default_options) if pl.respond_to?(:extra_options)
476
475
  @default_options = @default_options.merge(options) if options
477
476
 
477
+ if pl.respond_to?(:subplugins)
478
+ pl.subplugins.transform_keys(&Plugins.method(:load_plugin)).each do |main_pl, sub_pl|
479
+ # in case the main plugin has already been loaded, then apply subplugin functionality
480
+ # immediately
481
+ next unless @plugins.include?(main_pl)
482
+
483
+ plugin(sub_pl, options, &block)
484
+ end
485
+ end
486
+
478
487
  pl.configure(self, &block) if pl.respond_to?(:configure)
479
488
 
489
+ if label.is_a?(Symbol)
490
+ # in case an already-loaded plugin complements functionality of
491
+ # the plugin currently being loaded, loaded it now
492
+ @plugins.each do |registered_pl|
493
+ next if registered_pl == pl
494
+
495
+ next unless registered_pl.respond_to?(:subplugins)
496
+
497
+ sub_pl = registered_pl.subplugins[label]
498
+
499
+ next unless sub_pl
500
+
501
+ plugin(sub_pl, options, &block)
502
+ end
503
+ end
504
+
480
505
  @default_options.freeze
506
+ set_temporary_name("#{superclass}/#{pl}") if respond_to?(:set_temporary_name) # ruby 3.4 only
481
507
  elsif options
482
508
  # this can happen when two plugins are loaded, an one of them calls the other under the hood,
483
509
  # albeit changing some default.
@@ -486,9 +512,40 @@ module HTTPX
486
512
 
487
513
  @default_options.freeze
488
514
  end
515
+
489
516
  self
490
517
  end
491
518
  end
519
+
520
+ # setup of the support for close_on_fork sessions.
521
+ # adapted from https://github.com/mperham/connection_pool/blob/main/lib/connection_pool.rb#L48
522
+ if Process.respond_to?(:fork)
523
+ INSTANCES = ObjectSpace::WeakMap.new
524
+ private_constant :INSTANCES
525
+
526
+ def self.after_fork
527
+ INSTANCES.each_value(&:close)
528
+ nil
529
+ end
530
+
531
+ if ::Process.respond_to?(:_fork)
532
+ module ForkTracker
533
+ def _fork
534
+ pid = super
535
+ Session.after_fork if pid.zero?
536
+ pid
537
+ end
538
+ end
539
+ Process.singleton_class.prepend(ForkTracker)
540
+ end
541
+ else
542
+ INSTANCES = nil
543
+ private_constant :INSTANCES
544
+
545
+ def self.after_fork
546
+ # noop
547
+ end
548
+ end
492
549
  end
493
550
 
494
551
  # session may be overridden by certain adapters.
data/lib/httpx/timers.rb CHANGED
@@ -7,17 +7,16 @@ module HTTPX
7
7
  end
8
8
 
9
9
  def after(interval_in_secs, cb = nil, &blk)
10
- return unless interval_in_secs
11
-
12
10
  callback = cb || blk
13
11
 
12
+ raise Error, "timer must have a callback" unless callback
13
+
14
14
  # I'm assuming here that most requests will have the same
15
15
  # request timeout, as in most cases they share common set of
16
16
  # options. A user setting different request timeouts for 100s of
17
17
  # requests will already have a hard time dealing with that.
18
- unless (interval = @intervals.find { |t| t.interval == interval_in_secs })
18
+ unless (interval = @intervals.bsearch { |t| t.interval == interval_in_secs })
19
19
  interval = Interval.new(interval_in_secs)
20
- interval.on_empty { @intervals.delete(interval) }
21
20
  @intervals << interval
22
21
  @intervals.sort!
23
22
  end
@@ -30,6 +29,8 @@ module HTTPX
30
29
  end
31
30
 
32
31
  def wait_interval
32
+ drop_elapsed!
33
+
33
34
  return if @intervals.empty?
34
35
 
35
36
  @next_interval_at = Utils.now
@@ -43,11 +44,25 @@ module HTTPX
43
44
 
44
45
  elapsed_time = Utils.elapsed_time(@next_interval_at)
45
46
 
47
+ drop_elapsed!(elapsed_time)
48
+
46
49
  @intervals = @intervals.drop_while { |interval| interval.elapse(elapsed_time) <= 0 }
47
50
 
48
51
  @next_interval_at = nil if @intervals.empty?
49
52
  end
50
53
 
54
+ private
55
+
56
+ def drop_elapsed!(elapsed_time = 0)
57
+ # check first, if not elapsed, then return
58
+ first_interval = @intervals.first
59
+
60
+ return unless first_interval && first_interval.elapsed?(elapsed_time)
61
+
62
+ # TODO: would be nice to have a drop_while!
63
+ @intervals = @intervals.drop_while { |interval| interval.elapse(elapsed_time) <= 0 }
64
+ end
65
+
51
66
  class Timer
52
67
  def initialize(interval, callback)
53
68
  @interval = interval
@@ -67,15 +82,6 @@ module HTTPX
67
82
  def initialize(interval)
68
83
  @interval = interval
69
84
  @callbacks = []
70
- @on_empty = nil
71
- end
72
-
73
- def on_empty(&blk)
74
- @on_empty = blk
75
- end
76
-
77
- def cancel
78
- @on_empty.call
79
85
  end
80
86
 
81
87
  def <=>(other)
@@ -98,18 +104,20 @@ module HTTPX
98
104
 
99
105
  def delete(callback)
100
106
  @callbacks.delete(callback)
101
- @on_empty.call if @callbacks.empty?
102
107
  end
103
108
 
104
109
  def no_callbacks?
105
110
  @callbacks.empty?
106
111
  end
107
112
 
108
- def elapsed?
109
- @interval <= 0
113
+ def elapsed?(elapsed = 0)
114
+ (@interval - elapsed) <= 0 || @callbacks.empty?
110
115
  end
111
116
 
112
117
  def elapse(elapsed)
118
+ # same as elapsing
119
+ return 0 if @callbacks.empty?
120
+
113
121
  @interval -= elapsed
114
122
 
115
123
  if @interval <= 0
@@ -12,6 +12,7 @@ module HTTPX
12
12
  def initialize(filename, content_type)
13
13
  @original_filename = filename
14
14
  @content_type = content_type
15
+ @current = nil
15
16
  @file = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR)
16
17
  super(@file)
17
18
  end
@@ -68,11 +69,12 @@ module HTTPX
68
69
  # raise Error, "couldn't parse part headers" unless idx
69
70
  return unless idx
70
71
 
72
+ # @type var head: String
71
73
  head = @buffer.byteslice(0..idx + 4 - 1)
72
74
 
73
75
  @buffer = @buffer.byteslice(head.bytesize..-1)
74
76
 
75
- content_type = head[MULTIPART_CONTENT_TYPE, 1]
77
+ content_type = head[MULTIPART_CONTENT_TYPE, 1] || "text/plain"
76
78
  if (name = head[MULTIPART_CONTENT_DISPOSITION, 1])
77
79
  name = /\A"(.*)"\Z/ =~ name ? Regexp.last_match(1) : name.dup
78
80
  name.gsub!(/\\(.)/, "\\1")
@@ -83,7 +85,7 @@ module HTTPX
83
85
 
84
86
  filename = HTTPX::Utils.get_filename(head)
85
87
 
86
- name = filename || +"#{content_type || "text/plain"}[]" if name.nil? || name.empty?
88
+ name = filename || +"#{content_type}[]" if name.nil? || name.empty?
87
89
 
88
90
  @current = name
89
91
 
@@ -20,7 +20,7 @@ module HTTPX
20
20
  end
21
21
 
22
22
  def to_s
23
- read
23
+ read || ""
24
24
  ensure
25
25
  rewind
26
26
  end
@@ -37,6 +37,7 @@ module HTTPX
37
37
  def rewind
38
38
  form = @form.each_with_object([]) do |(key, val), aux|
39
39
  if val.respond_to?(:path) && val.respond_to?(:reopen) && val.respond_to?(:closed?) && val.closed?
40
+ # @type var val: File
40
41
  val = val.reopen(val.path, File::RDONLY)
41
42
  end
42
43
  val.rewind if val.respond_to?(:rewind)
data/lib/httpx/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- VERSION = "1.4.3"
4
+ VERSION = "1.5.0"
5
5
  end
data/sig/buffer.rbs CHANGED
@@ -14,7 +14,7 @@ module HTTPX
14
14
  def capacity: () -> Integer
15
15
 
16
16
  # delegated
17
- def <<: (string data) -> String
17
+ def <<: (String data) -> String
18
18
  def empty?: () -> bool
19
19
  def bytesize: () -> (Integer | Float)
20
20
  def clear: () -> void
data/sig/chainable.rbs CHANGED
@@ -21,14 +21,16 @@ module HTTPX
21
21
  | (:cookies, ?options) -> Plugins::sessionCookies
22
22
  | (:expect, ?options) -> Session
23
23
  | (:follow_redirects, ?options) -> Plugins::sessionFollowRedirects
24
- | (:upgrade, ?options) -> Session
25
- | (:h2c, ?options) -> Session
24
+ | (:upgrade, ?options) -> Plugins::sessionUpgrade
25
+ | (:h2c, ?options) -> Plugins::sessionUpgrade
26
+ | (:h2, ?options) -> Plugins::sessionUpgrade
26
27
  | (:persistent, ?options) -> Plugins::sessionPersistent
27
28
  | (:proxy, ?options) -> (Plugins::sessionProxy & Plugins::httpProxy)
28
29
  | (:push_promise, ?options) -> Plugins::sessionPushPromise
29
30
  | (:retries, ?options) -> Plugins::sessionRetries
30
31
  | (:rate_limiter, ?options) -> Session
31
32
  | (:stream, ?options) -> Plugins::sessionStream
33
+ | (:stream_bidi, ?options) -> Plugins::sessionStreamBidi
32
34
  | (:aws_sigv4, ?options) -> Plugins::awsSigV4Session
33
35
  | (:grpc, ?options) -> Plugins::grpcSession
34
36
  | (:response_cache, ?options) -> Plugins::sessionResponseCache
@@ -39,6 +41,7 @@ module HTTPX
39
41
  | (:ssrf_filter, ?options) -> Plugins::sessionSsrf
40
42
  | (:webdav, ?options) -> Plugins::sessionWebDav
41
43
  | (:xml, ?options) -> Plugins::sessionXML
44
+ | (:query, ?options) -> Plugins::sessionQuery
42
45
  | (Symbol | Module, ?options) { (Class) -> void } -> Session
43
46
  | (Symbol | Module, ?options) -> Session
44
47
 
@@ -16,6 +16,8 @@ module HTTPX
16
16
  @drains: Hash[Request, String]
17
17
  @pings: Array[String]
18
18
  @buffer: Buffer
19
+ @handshake_completed: bool
20
+ @wait_for_handshake: bool
19
21
 
20
22
  def interests: () -> io_interests?
21
23
 
@@ -27,8 +29,6 @@ module HTTPX
27
29
 
28
30
  def <<: (string) -> void
29
31
 
30
- def can_buffer_more_requests?: () -> bool
31
-
32
32
  def send: (Request request, ?bool head) -> bool
33
33
 
34
34
  def consume: () -> void
@@ -45,6 +45,8 @@ module HTTPX
45
45
 
46
46
  def initialize: (Buffer buffer, Options options) -> untyped
47
47
 
48
+ def can_buffer_more_requests?: () -> bool
49
+
48
50
  def send_pending: () -> void
49
51
 
50
52
  def set_protocol_headers: (Request) -> _Each[[String, String]]
@@ -63,6 +65,10 @@ module HTTPX
63
65
 
64
66
  def join_body: (::HTTP2::Stream stream, Request request) -> void
65
67
 
68
+ def send_chunk: (Request request, ::HTTP2::Stream stream, String chunk, String? next_chunk) -> void
69
+
70
+ def end_stream?: (Request request, String? next_chunk) -> void
71
+
66
72
  def on_stream_headers: (::HTTP2::Stream stream, Request request, Array[[String, String]] headers) -> void
67
73
 
68
74
  def on_stream_trailers: (::HTTP2::Stream stream, Response response, Array[[String, String]] headers) -> void
@@ -92,12 +98,15 @@ module HTTPX
92
98
  def on_pong: (string ping) -> void
93
99
 
94
100
  class Error < ::HTTPX::Error
101
+ def initialize: (Integer id, Symbol | StandardError error) -> void
95
102
  end
96
103
 
97
104
  class GoawayError < Error
105
+ def initialize: () -> void
98
106
  end
99
107
 
100
108
  class PingError < Error
109
+ def initialize: () -> void
101
110
  end
102
111
  end
103
112
  end
data/sig/connection.rbs CHANGED
@@ -20,6 +20,7 @@ module HTTPX
20
20
 
21
21
 
22
22
  attr_reader type: io_type
23
+ attr_reader io: TCP | SSL | UNIX | nil
23
24
  attr_reader origin: http_uri
24
25
  attr_reader origins: Array[String]
25
26
  attr_reader state: Symbol
@@ -39,7 +40,6 @@ module HTTPX
39
40
  @keep_alive_timeout: Numeric?
40
41
  @timeout: Numeric?
41
42
  @current_timeout: Numeric?
42
- @io: TCP | SSL | UNIX
43
43
  @parser: Object & _Parser
44
44
  @connected_at: Float
45
45
  @response_received_at: Float
@@ -64,6 +64,8 @@ module HTTPX
64
64
 
65
65
  def mergeable?: (Connection connection) -> bool
66
66
 
67
+ def coalesce!: (instance connection) -> void
68
+
67
69
  def coalescable?: (Connection connection) -> bool
68
70
 
69
71
  def create_idle: (?Hash[Symbol, untyped] options) -> instance
@@ -104,8 +106,6 @@ module HTTPX
104
106
 
105
107
  def handle_socket_timeout: (Numeric interval) -> void
106
108
 
107
- def coalesced_connection=: (instance connection) -> void
108
-
109
109
  def sibling=: (instance? connection) -> void
110
110
 
111
111
  def handle_connect_error: (StandardError error) -> void
@@ -164,6 +164,6 @@ module HTTPX
164
164
 
165
165
  def set_request_timeout: (Symbol label, Request request, Numeric timeout, Symbol start_event, Symbol | Array[Symbol] finish_events) { () -> void } -> void
166
166
 
167
- def self.parser_type: (String protocol) -> (singleton(HTTP1) | singleton(HTTP2))
167
+ def parser_type: (String protocol) -> (singleton(HTTP1) | singleton(HTTP2))
168
168
  end
169
169
  end
data/sig/errors.rbs CHANGED
@@ -18,9 +18,6 @@ module HTTPX
18
18
  end
19
19
 
20
20
  class PoolTimeoutError < TimeoutError
21
- attr_reader origin: String
22
-
23
- def initialize: (String origin, Numeric timeout) -> void
24
21
  end
25
22
 
26
23
  class ConnectTimeoutError < TimeoutError
data/sig/headers.rbs CHANGED
@@ -2,7 +2,7 @@ module HTTPX
2
2
  class Headers
3
3
  include _ToS
4
4
 
5
- @headers: Hash[String, Array[String]]
5
+ @headers: Hash[String, Array[_ToS]]
6
6
 
7
7
  def self.new: (?untyped headers) -> instance
8
8
 
@@ -11,34 +11,39 @@ module HTTPX
11
11
  def []: (String field) -> String?
12
12
  def []=: (String field, headers_value value) -> void
13
13
 
14
- def add: (String field, string value) -> void
15
- def delete: (String field) -> Array[String]?
14
+ def add: (String field, String value) -> void
15
+ def delete: (String field) -> Array[_ToS]?
16
16
 
17
17
  def each: (?_Each[[String, String]]? extra_headers) { (String k, String v) -> void } -> void
18
18
  | (?_Each[[String, String]]? extra_headers) -> Enumerable[[String, String]]
19
19
 
20
- def get: (String field) -> Array[String]
20
+ def get: (String field) -> Array[_ToS]
21
21
  def key?: (String downcased_key) -> bool
22
22
 
23
23
  def merge: (_Each[[String, headers_value]] other) -> Headers
24
24
 
25
- def same_headers?: (untyped headers) -> bool
25
+ def empty?: () -> bool
26
26
 
27
27
  def to_a: () -> Array[[String, String]]
28
+
28
29
  def to_hash: () -> Hash[String, String]
30
+
29
31
  alias to_h to_hash
30
32
 
31
33
  def inspect: () -> String
32
34
 
33
35
  private
34
36
 
35
- def initialize: (?headers?) -> untyped
36
- def array_value: (headers_value) -> Array[String]
37
- def downcased: (_ToS field) -> String
37
+ def initialize: (?(headers_input | instance)?) -> void
38
+
39
+ def array_value: (headers_value value) -> Array[_ToS]
40
+
41
+ def downcased: (header_field field) -> String
38
42
  end
39
43
 
44
+ type header_field = string | _ToS
40
45
  type headers_value = _ToS | Array[_ToS]
41
- type headers_hash = Hash[_ToS, headers_value]
42
- type headers_input = headers_hash | Array[[_ToS, string]]
46
+ type headers_hash = Hash[header_field, headers_value]
47
+ type headers_input = headers_hash | Array[[header_field, headers_value]]
43
48
  type headers = Headers | headers_input
44
49
  end
data/sig/httpx.rbs CHANGED
@@ -2,6 +2,7 @@ module HTTPX
2
2
  extend Chainable
3
3
 
4
4
  EMPTY: Array[untyped]
5
+ EMPTY_HASH: Hash[untyped, untyped]
5
6
 
6
7
  VERSION: String
7
8
 
@@ -16,7 +17,10 @@ module HTTPX
16
17
  type ip_family = Integer #Socket::AF_INET6 | Socket::AF_INET
17
18
 
18
19
  module Plugins
19
- def self?.load_plugin: (Symbol) -> Module
20
+ self.@plugins: Hash[Symbol, Module]
21
+ self.@plugins_mutex: Thread::Mutex
22
+
23
+ def self?.load_plugin: (Symbol name) -> Module
20
24
 
21
25
  def self?.register_plugin: (Symbol, Module) -> void
22
26
  end
data/sig/io/tcp.rbs CHANGED
@@ -14,6 +14,12 @@ module HTTPX
14
14
 
15
15
  alias host ip
16
16
 
17
+ @hostname: String
18
+
19
+ @options: Options
20
+
21
+ @fallback_protocol: String
22
+
17
23
  # TODO: lift when https://github.com/ruby/rbs/issues/1497 fixed
18
24
  def initialize: (URI::Generic origin, Array[ipaddr]? addresses, Options options) ?{ (instance) -> void } -> void
19
25
 
data/sig/loggable.rbs CHANGED
@@ -11,5 +11,7 @@ module HTTPX
11
11
  def log: (?level: Integer?, ?color: Symbol?, ?debug_level: Integer, ?debug: _IOLogger?) { () -> String } -> void
12
12
 
13
13
  def log_exception: (Exception error, ?level: Integer, ?color: Symbol, ?debug_level: Integer, ?debug: _IOLogger?) -> void
14
+
15
+ def log_redact: (_ToS text, ?bool should_redact) -> String
14
16
  end
15
17
  end
data/sig/options.rbs CHANGED
@@ -13,6 +13,7 @@ module HTTPX
13
13
  KEEP_ALIVE_TIMEOUT: Integer
14
14
  SETTINGS_TIMEOUT: Integer
15
15
  CLOSE_HANDSHAKE_TIMEOUT: Integer
16
+ SET_TEMPORARY_NAME: ^(Module mod, ?Symbol pl) -> void
16
17
  DEFAULT_OPTIONS: Hash[Symbol, untyped]
17
18
  REQUEST_BODY_IVARS: Array[Symbol]
18
19
 
@@ -25,7 +26,7 @@ module HTTPX
25
26
  attr_reader uri: URI?
26
27
 
27
28
  # headers
28
- attr_reader headers: Headers?
29
+ attr_reader headers: headers?
29
30
 
30
31
  # timeout
31
32
  attr_reader timeout: timeout
@@ -89,6 +90,8 @@ module HTTPX
89
90
 
90
91
  attr_reader response_body_class: singleton(Response::Body)
91
92
 
93
+ attr_reader options_class: singleton(Options)
94
+
92
95
  attr_reader resolver_class: Symbol | Class
93
96
 
94
97
  attr_reader ssl: Hash[Symbol, untyped]
@@ -109,6 +112,9 @@ module HTTPX
109
112
  # persistent
110
113
  attr_reader persistent: bool
111
114
 
115
+ # close_on_fork
116
+ attr_reader close_on_fork: bool
117
+
112
118
  # resolver_options
113
119
  attr_reader resolver_options: Hash[Symbol, untyped]
114
120
 
@@ -1,7 +1,5 @@
1
1
  module HTTPX
2
2
  module Plugins::Cookies
3
- type cookie_attributes = Hash[Symbol | String, top]
4
-
5
3
  class Cookie
6
4
  include Comparable
7
5
 
@@ -33,7 +31,7 @@ module HTTPX
33
31
  def cookie_value: () -> String
34
32
  alias to_s cookie_value
35
33
 
36
- def valid_for_uri?: (uri) -> bool
34
+ def valid_for_uri?: (http_uri uri) -> bool
37
35
 
38
36
  def self.new: (Cookie) -> instance
39
37
  | (cookie_attributes) -> instance
@@ -11,12 +11,12 @@ module HTTPX
11
11
 
12
12
  def add: (Cookie name, ?String path) -> void
13
13
 
14
- def []: (uri) -> Array[Cookie]
14
+ def []: (http_uri) -> Array[Cookie]
15
15
 
16
- def each: (?uri?) { (Cookie) -> void } -> void
17
- | (?uri?) -> Enumerable[Cookie]
16
+ def each: (?http_uri?) { (Cookie) -> void } -> void
17
+ | (?http_uri?) -> Enumerable[Cookie]
18
18
 
19
- def merge: (_Each[cookie] cookies) -> instance
19
+ def merge: (_Each[cookie] cookies) -> self
20
20
 
21
21
  private
22
22