httpx 0.18.5 → 0.19.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -1
  3. data/doc/release_notes/0_18_5.md +2 -2
  4. data/doc/release_notes/0_18_6.md +5 -0
  5. data/doc/release_notes/0_18_7.md +5 -0
  6. data/doc/release_notes/0_19_0.md +39 -0
  7. data/doc/release_notes/0_19_1.md +5 -0
  8. data/lib/httpx/adapters/faraday.rb +7 -3
  9. data/lib/httpx/connection/http1.rb +5 -5
  10. data/lib/httpx/connection/http2.rb +1 -5
  11. data/lib/httpx/connection.rb +22 -10
  12. data/lib/httpx/extensions.rb +16 -0
  13. data/lib/httpx/headers.rb +0 -2
  14. data/lib/httpx/io/tcp.rb +27 -6
  15. data/lib/httpx/options.rb +44 -11
  16. data/lib/httpx/plugins/cookies.rb +5 -7
  17. data/lib/httpx/plugins/internal_telemetry.rb +1 -1
  18. data/lib/httpx/plugins/multipart/mime_type_detector.rb +7 -1
  19. data/lib/httpx/plugins/proxy/http.rb +10 -23
  20. data/lib/httpx/plugins/proxy/socks4.rb +1 -1
  21. data/lib/httpx/plugins/proxy/socks5.rb +1 -1
  22. data/lib/httpx/plugins/proxy.rb +20 -12
  23. data/lib/httpx/plugins/retries.rb +1 -1
  24. data/lib/httpx/pool.rb +40 -20
  25. data/lib/httpx/resolver/https.rb +32 -42
  26. data/lib/httpx/resolver/multi.rb +79 -0
  27. data/lib/httpx/resolver/native.rb +28 -36
  28. data/lib/httpx/resolver/resolver.rb +92 -0
  29. data/lib/httpx/resolver/system.rb +175 -19
  30. data/lib/httpx/resolver.rb +37 -11
  31. data/lib/httpx/response.rb +4 -2
  32. data/lib/httpx/session.rb +1 -15
  33. data/lib/httpx/session_extensions.rb +26 -0
  34. data/lib/httpx/timers.rb +1 -1
  35. data/lib/httpx/transcoder/chunker.rb +0 -1
  36. data/lib/httpx/version.rb +1 -1
  37. data/lib/httpx.rb +3 -0
  38. data/sig/connection/http1.rbs +0 -2
  39. data/sig/connection/http2.rbs +2 -2
  40. data/sig/connection.rbs +1 -0
  41. data/sig/errors.rbs +8 -0
  42. data/sig/headers.rbs +0 -2
  43. data/sig/httpx.rbs +4 -0
  44. data/sig/options.rbs +10 -7
  45. data/sig/parser/http1.rbs +14 -5
  46. data/sig/pool.rbs +17 -9
  47. data/sig/registry.rbs +3 -0
  48. data/sig/request.rbs +11 -0
  49. data/sig/resolver/https.rbs +15 -27
  50. data/sig/resolver/multi.rbs +7 -0
  51. data/sig/resolver/native.rbs +3 -12
  52. data/sig/resolver/resolver.rbs +36 -0
  53. data/sig/resolver/system.rbs +3 -9
  54. data/sig/resolver.rbs +12 -10
  55. data/sig/response.rbs +15 -5
  56. data/sig/selector.rbs +3 -3
  57. data/sig/timers.rbs +5 -2
  58. data/sig/transcoder/chunker.rbs +16 -5
  59. data/sig/transcoder/json.rbs +5 -0
  60. data/sig/transcoder.rbs +3 -1
  61. metadata +15 -4
  62. data/lib/httpx/resolver/resolver_mixin.rb +0 -75
  63. data/sig/resolver/resolver_mixin.rbs +0 -26
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "resolv"
4
+ require "ipaddr"
5
+
6
+ module HTTPX
7
+ class Resolver::Resolver
8
+ include Callbacks
9
+ include Loggable
10
+
11
+ RECORD_TYPES = {
12
+ Socket::AF_INET6 => Resolv::DNS::Resource::IN::AAAA,
13
+ Socket::AF_INET => Resolv::DNS::Resource::IN::A,
14
+ }.freeze
15
+
16
+ FAMILY_TYPES = {
17
+ Resolv::DNS::Resource::IN::AAAA => "AAAA",
18
+ Resolv::DNS::Resource::IN::A => "A",
19
+ }.freeze
20
+
21
+ class << self
22
+ def multi?
23
+ true
24
+ end
25
+ end
26
+
27
+ attr_reader :family
28
+
29
+ attr_writer :pool
30
+
31
+ def initialize(family, options)
32
+ @family = family
33
+ @record_type = RECORD_TYPES[family]
34
+ @options = Options.new(options)
35
+ end
36
+
37
+ def close; end
38
+
39
+ def closed?
40
+ true
41
+ end
42
+
43
+ def empty?
44
+ true
45
+ end
46
+
47
+ def emit_addresses(connection, family, addresses)
48
+ addresses.map! do |address|
49
+ address.is_a?(IPAddr) ? address : IPAddr.new(address.to_s)
50
+ end
51
+ log { "resolver: answer #{connection.origin.host}: #{addresses.inspect}" }
52
+ if !connection.io &&
53
+ connection.options.ip_families.size > 1 &&
54
+ family == Socket::AF_INET &&
55
+ addresses.first.to_s != connection.origin.host.to_s
56
+ log { "resolver: A response, applying resolution delay..." }
57
+ @pool.after(0.05) do
58
+ connection.addresses = addresses
59
+ emit(:resolve, connection)
60
+ end
61
+ else
62
+ connection.addresses = addresses
63
+ emit(:resolve, connection)
64
+ end
65
+ end
66
+
67
+ private
68
+
69
+ def early_resolve(connection, hostname: connection.origin.host)
70
+ addresses = @resolver_options[:cache] && (connection.addresses || HTTPX::Resolver.nolookup_resolve(hostname))
71
+
72
+ return unless addresses
73
+
74
+ addresses.select! { |addr| addr.family == @family }
75
+
76
+ emit_addresses(connection, @family, addresses)
77
+ end
78
+
79
+ def emit_resolve_error(connection, hostname = connection.origin.host, ex = nil)
80
+ emit(:error, connection, resolve_error(hostname, ex))
81
+ end
82
+
83
+ def resolve_error(hostname, ex = nil)
84
+ return ex if ex.is_a?(ResolveError)
85
+
86
+ message = ex ? ex.message : "Can't resolve #{hostname}"
87
+ error = ResolveError.new(message)
88
+ error.set_backtrace(ex ? ex.backtrace : caller)
89
+ error
90
+ end
91
+ end
92
+ end
@@ -4,48 +4,204 @@ require "forwardable"
4
4
  require "resolv"
5
5
 
6
6
  module HTTPX
7
- class Resolver::System
8
- include Resolver::ResolverMixin
7
+ class Resolver::System < Resolver::Resolver
8
+ using URIExtensions
9
+ extend Forwardable
9
10
 
10
11
  RESOLV_ERRORS = [Resolv::ResolvError,
11
12
  Resolv::DNS::Requester::RequestError,
12
13
  Resolv::DNS::EncodeError,
13
14
  Resolv::DNS::DecodeError].freeze
14
15
 
16
+ DONE = 1
17
+ ERROR = 2
18
+
19
+ class << self
20
+ def multi?
21
+ false
22
+ end
23
+ end
24
+
15
25
  attr_reader :state
16
26
 
27
+ def_delegator :@connections, :empty?
28
+
17
29
  def initialize(options)
18
- @options = Options.new(options)
30
+ super(nil, options)
19
31
  @resolver_options = @options.resolver_options
20
- @state = :idle
21
32
  resolv_options = @resolver_options.dup
22
- timeouts = resolv_options.delete(:timeouts)
33
+ timeouts = resolv_options.delete(:timeouts) || Resolver::RESOLVE_TIMEOUT
34
+ @_timeouts = Array(timeouts)
35
+ @timeouts = Hash.new { |tims, host| tims[host] = @_timeouts.dup }
23
36
  resolv_options.delete(:cache)
24
- @resolver = Resolv::DNS.new(resolv_options.empty? ? nil : resolv_options)
25
- @resolver.timeouts = timeouts || Resolver::RESOLVE_TIMEOUT
37
+ @connections = []
38
+ @queries = []
39
+ @ips = []
40
+ @pipe_mutex = Thread::Mutex.new
41
+ @state = :idle
42
+ end
43
+
44
+ def resolvers
45
+ return enum_for(__method__) unless block_given?
46
+
47
+ yield self
48
+ end
49
+
50
+ def connections
51
+ EMPTY
52
+ end
53
+
54
+ def close
55
+ transition(:closed)
26
56
  end
27
57
 
28
58
  def closed?
29
- true
59
+ @state == :closed
60
+ end
61
+
62
+ def to_io
63
+ @pipe_read.to_io
64
+ end
65
+
66
+ def call
67
+ case @state
68
+ when :open
69
+ consume
70
+ end
71
+ nil
30
72
  end
31
73
 
32
- def empty?
33
- true
74
+ def interests
75
+ return if @queries.empty?
76
+
77
+ :r
78
+ end
79
+
80
+ def timeout
81
+ return unless @queries.empty?
82
+
83
+ _, connection = @queries.first
84
+
85
+ @timeouts[connection.origin.host].first
34
86
  end
35
87
 
36
88
  def <<(connection)
89
+ @connections << connection
90
+ resolve
91
+ end
92
+
93
+ private
94
+
95
+ def transition(nextstate)
96
+ case nextstate
97
+ when :idle
98
+ @timeouts.clear
99
+ when :open
100
+ return unless @state == :idle
101
+
102
+ @pipe_read, @pipe_write = ::IO.pipe
103
+ when :closed
104
+ return unless @state == :open
105
+
106
+ @pipe_write.close
107
+ @pipe_read.close
108
+ end
109
+ @state = nextstate
110
+ end
111
+
112
+ def consume
113
+ return if @connections.empty?
114
+
115
+ while @pipe_read.ready? && (event = @pipe_read.getbyte)
116
+ case event
117
+ when DONE
118
+ *pair, addrs = @pipe_mutex.synchronize { @ips.pop }
119
+ @queries.delete(pair)
120
+
121
+ family, connection = pair
122
+ emit_addresses(connection, family, addrs)
123
+ when ERROR
124
+ *pair, error = @pipe_mutex.synchronize { @ips.pop }
125
+ @queries.delete(pair)
126
+
127
+ family, connection = pair
128
+ emit_resolve_error(connection, connection.origin.host, error)
129
+ end
130
+
131
+ @connections.delete(connection) if @queries.empty?
132
+ end
133
+
134
+ return emit(:close, self) if @connections.empty?
135
+
136
+ resolve
137
+ end
138
+
139
+ def resolve(connection = @connections.first)
140
+ raise Error, "no URI to resolve" unless connection
141
+ return unless @queries.empty?
142
+
37
143
  hostname = connection.origin.host
38
- addresses = connection.addresses ||
39
- ip_resolve(hostname) ||
40
- system_resolve(hostname) ||
41
- @resolver.getaddresses(hostname)
42
- throw(:resolve_error, resolve_error(hostname)) if addresses.empty?
144
+ scheme = connection.origin.scheme
145
+ log { "resolver: resolve IDN #{connection.origin.non_ascii_hostname} as #{hostname}" } if connection.origin.non_ascii_hostname
146
+
147
+ transition(:open)
43
148
 
44
- emit_addresses(connection, addresses)
45
- rescue Errno::EHOSTUNREACH, *RESOLV_ERRORS => e
46
- emit_resolve_error(connection, hostname, e)
149
+ connection.options.ip_families.each do |family|
150
+ @queries << [family, connection]
151
+ end
152
+ async_resolve(connection, hostname, scheme)
153
+ consume
47
154
  end
48
155
 
49
- def uncache(*); end
156
+ def async_resolve(connection, hostname, scheme)
157
+ families = connection.options.ip_families
158
+ log { "resolver: query for #{hostname}" }
159
+ resolve_timeout = @timeouts[connection.origin.host].first
160
+
161
+ Thread.start do
162
+ Thread.current.report_on_exception = false
163
+ begin
164
+ addrs = if resolve_timeout
165
+ Timeout.timeout(resolve_timeout) do
166
+ __addrinfo_resolve(hostname, scheme)
167
+ end
168
+ else
169
+ __addrinfo_resolve(hostname, scheme)
170
+ end
171
+ addrs = addrs.sort_by(&:afamily).group_by(&:afamily)
172
+ families.each do |family|
173
+ addresses = addrs[family]
174
+ next unless addresses
175
+
176
+ addresses.map!(&:ip_address)
177
+ addresses.uniq!
178
+ @pipe_mutex.synchronize do
179
+ @ips.unshift([family, connection, addresses])
180
+ @pipe_write.putc(DONE) unless @pipe_write.closed?
181
+ end
182
+ end
183
+ rescue Timeout::Error => e
184
+ ex = ResolveTimeoutError.new(resolve_timeout, e.message)
185
+ ex.set_backtrace(ex.backtrace)
186
+ @pipe_mutex.synchronize do
187
+ families.each do |family|
188
+ @ips.unshift([family, connection, ex])
189
+ @pipe_write.putc(ERROR) unless @pipe_write.closed?
190
+ end
191
+ end
192
+ rescue StandardError => e
193
+ @pipe_mutex.synchronize do
194
+ families.each do |family|
195
+ @ips.unshift([family, connection, e])
196
+ @pipe_write.putc(ERROR) unless @pipe_write.closed?
197
+ end
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ def __addrinfo_resolve(host, scheme)
204
+ Addrinfo.getaddrinfo(host, scheme, Socket::AF_UNSPEC, Socket::SOCK_STREAM)
205
+ end
50
206
  end
51
207
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "resolv"
4
+ require "ipaddr"
4
5
 
5
6
  module HTTPX
6
7
  module Resolver
@@ -8,10 +9,11 @@ module HTTPX
8
9
 
9
10
  RESOLVE_TIMEOUT = 5
10
11
 
11
- require "httpx/resolver/resolver_mixin"
12
+ require "httpx/resolver/resolver"
12
13
  require "httpx/resolver/system"
13
14
  require "httpx/resolver/native"
14
15
  require "httpx/resolver/https"
16
+ require "httpx/resolver/multi"
15
17
 
16
18
  register :system, System
17
19
  register :native, Native
@@ -22,9 +24,27 @@ module HTTPX
22
24
 
23
25
  @identifier_mutex = Mutex.new
24
26
  @identifier = 1
27
+ @system_resolver = Resolv::Hosts.new
25
28
 
26
29
  module_function
27
30
 
31
+ def nolookup_resolve(hostname)
32
+ ip_resolve(hostname) || cached_lookup(hostname) || system_resolve(hostname)
33
+ end
34
+
35
+ def ip_resolve(hostname)
36
+ [IPAddr.new(hostname)]
37
+ rescue ArgumentError
38
+ end
39
+
40
+ def system_resolve(hostname)
41
+ ips = @system_resolver.getaddresses(hostname)
42
+ return if ips.empty?
43
+
44
+ ips.map { |ip| IPAddr.new(ip) }
45
+ rescue IOError
46
+ end
47
+
28
48
  def cached_lookup(hostname)
29
49
  now = Utils.now
30
50
  @lookup_mutex.synchronize do
@@ -32,25 +52,31 @@ module HTTPX
32
52
  end
33
53
  end
34
54
 
35
- def cached_lookup_set(hostname, entries)
55
+ def cached_lookup_set(hostname, family, entries)
36
56
  now = Utils.now
37
57
  entries.each do |entry|
38
58
  entry["TTL"] += now
39
59
  end
40
60
  @lookup_mutex.synchronize do
41
- @lookups[hostname] += entries
61
+ case family
62
+ when Socket::AF_INET6
63
+ @lookups[hostname].concat(entries)
64
+ when Socket::AF_INET
65
+ @lookups[hostname].unshift(*entries)
66
+ end
42
67
  entries.each do |entry|
43
- @lookups[entry["name"]] << entry if entry["name"] != hostname
68
+ next unless entry["name"] != hostname
69
+
70
+ case family
71
+ when Socket::AF_INET6
72
+ @lookups[entry["name"]] << entry
73
+ when Socket::AF_INET
74
+ @lookups[entry["name"]].unshift(entry)
75
+ end
44
76
  end
45
77
  end
46
78
  end
47
79
 
48
- def uncache(hostname)
49
- @lookup_mutex.synchronize do
50
- @lookups.delete(hostname)
51
- end
52
- end
53
-
54
80
  # do not use directly!
55
81
  def lookup(hostname, ttl)
56
82
  return unless @lookups.key?(hostname)
@@ -62,7 +88,7 @@ module HTTPX
62
88
  if address.key?("alias")
63
89
  lookup(address["alias"], ttl)
64
90
  else
65
- address["data"]
91
+ IPAddr.new(address["data"])
66
92
  end
67
93
  end
68
94
  ips unless ips.empty?
@@ -173,7 +173,7 @@ module HTTPX
173
173
  rescue ArgumentError
174
174
  @buffer.string
175
175
  end
176
- when Tempfile, File
176
+ when Tempfile
177
177
  rewind
178
178
  content = _with_same_buffer_pos { @buffer.read }
179
179
  begin
@@ -253,6 +253,7 @@ module HTTPX
253
253
  @buffer = StringIO.new("".b)
254
254
  end
255
255
  when :memory
256
+ # @type ivar @buffer: StringIO | Tempfile
256
257
  if @length > @threshold_size
257
258
  aux = @buffer
258
259
  @buffer = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR)
@@ -272,11 +273,12 @@ module HTTPX
272
273
  def _with_same_buffer_pos
273
274
  return yield unless @buffer && @buffer.respond_to?(:pos)
274
275
 
276
+ # @type ivar @buffer: StringIO | Tempfile
275
277
  current_pos = @buffer.pos
276
278
  @buffer.rewind
277
279
  begin
278
280
  yield
279
- rescue StandardError
281
+ ensure
280
282
  @buffer.pos = current_pos
281
283
  end
282
284
  end
data/lib/httpx/session.rb CHANGED
@@ -207,7 +207,7 @@ module HTTPX
207
207
 
208
208
  return responses unless request
209
209
 
210
- pool.next_tick until (response = fetch_response(request, connections, request.options))
210
+ catch(:coalesced) { pool.next_tick } until (response = fetch_response(request, connections, request.options))
211
211
 
212
212
  responses << response
213
213
  requests.shift
@@ -309,18 +309,4 @@ module HTTPX
309
309
  # :nocov:
310
310
  end
311
311
  end
312
-
313
- unless ENV.grep(/https?_proxy$/i).empty?
314
- proxy_session = plugin(:proxy)
315
- ::HTTPX.send(:remove_const, :Session)
316
- ::HTTPX.send(:const_set, :Session, proxy_session.class)
317
- end
318
-
319
- # :nocov:
320
- if Session.default_options.debug_level > 2
321
- proxy_session = plugin(:internal_telemetry)
322
- ::HTTPX.send(:remove_const, :Session)
323
- ::HTTPX.send(:const_set, :Session, proxy_session.class)
324
- end
325
- # :nocov:
326
312
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ unless ENV.keys.grep(/\Ahttps?_proxy\z/i).empty?
5
+ proxy_session = plugin(:proxy)
6
+ remove_const(:Session)
7
+ const_set(:Session, proxy_session.class)
8
+
9
+ # redefine the default options static var, which needs to
10
+ # refresh options_class
11
+ options = proxy_session.class.default_options.to_hash
12
+ options.freeze
13
+ original_verbosity = $VERBOSE
14
+ $VERBOSE = nil
15
+ Options.send(:const_set, :DEFAULT_OPTIONS, options)
16
+ $VERBOSE = original_verbosity
17
+ end
18
+
19
+ # :nocov:
20
+ if Session.default_options.debug_level > 2
21
+ proxy_session = plugin(:internal_telemetry)
22
+ remove_const(:Session)
23
+ const_set(:Session, proxy_session.class)
24
+ end
25
+ # :nocov:
26
+ end
data/lib/httpx/timers.rb CHANGED
@@ -64,7 +64,7 @@ module HTTPX
64
64
  end
65
65
 
66
66
  def to_f
67
- @interval
67
+ Float(@interval)
68
68
  end
69
69
 
70
70
  def <<(callback)
@@ -40,7 +40,6 @@ module HTTPX::Transcoder
40
40
 
41
41
  def initialize(buffer, trailers = false)
42
42
  @buffer = buffer
43
- @chunk_length = nil
44
43
  @chunk_buffer = "".b
45
44
  @finished = false
46
45
  @state = :length
data/lib/httpx/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
- VERSION = "0.18.5"
4
+ VERSION = "0.19.1"
5
5
  end
data/lib/httpx.rb CHANGED
@@ -25,6 +25,8 @@ require "mutex_m"
25
25
  # Top-Level Namespace
26
26
  #
27
27
  module HTTPX
28
+ EMPTY = [].freeze
29
+
28
30
  # All plugins should be stored under this module/namespace. Can register and load
29
31
  # plugins.
30
32
  #
@@ -64,3 +66,4 @@ module HTTPX
64
66
  end
65
67
 
66
68
  require "httpx/session"
69
+ require "httpx/session_extensions"
@@ -67,8 +67,6 @@ module HTTPX
67
67
 
68
68
  def set_protocol_headers: (Request) -> _Each[[String, String]]
69
69
 
70
- def headline_uri: (Request) -> String
71
-
72
70
  def handle: (Request request) -> void
73
71
 
74
72
  def join_headers: (Request request) -> void
@@ -46,8 +46,6 @@ module HTTPX
46
46
 
47
47
  def send_pending: () -> void
48
48
 
49
- def headline_uri: (Request) -> String
50
-
51
49
  def set_protocol_headers: (Request) -> _Each[[String, String]]
52
50
 
53
51
  def handle: (Request request, HTTP2Next::Stream stream) -> void
@@ -56,6 +54,8 @@ module HTTPX
56
54
 
57
55
  def handle_stream: (HTTP2Next::Stream stream, Request request) -> void
58
56
 
57
+ def join_headline: (Request request) -> String
58
+
59
59
  def join_headers: (HTTP2Next::Stream stream, Request request) -> void
60
60
 
61
61
  def join_trailers: (HTTP2Next::Stream stream, Request request) -> void
data/sig/connection.rbs CHANGED
@@ -22,6 +22,7 @@ module HTTPX
22
22
  BUFFER_SIZE: Integer
23
23
 
24
24
  attr_reader origin: URI::Generic
25
+ attr_reader origins: Array[String]
25
26
  attr_reader state: Symbol
26
27
  attr_reader pending: Array[Request]
27
28
  attr_reader options: Options
data/sig/errors.rbs CHANGED
@@ -26,6 +26,14 @@ module HTTPX
26
26
  class ResolveError < Error
27
27
  end
28
28
 
29
+ class HTTPError < Error
30
+ attr_reader response: Response
31
+
32
+ private
33
+
34
+ def initialize: (Response response) -> void
35
+ end
36
+
29
37
  class NativeResolveError < ResolveError
30
38
  attr_reader connection: Connection
31
39
  attr_reader host: String
data/sig/headers.rbs CHANGED
@@ -2,8 +2,6 @@ module HTTPX
2
2
  class Headers
3
3
  include _ToS
4
4
 
5
- EMPTY: Array[untyped]
6
-
7
5
  @headers: Hash[String, Array[String]]
8
6
 
9
7
  def self.new: (?untyped headers) -> instance
data/sig/httpx.rbs CHANGED
@@ -1,6 +1,8 @@
1
1
  module HTTPX
2
2
  extend Chainable
3
3
 
4
+ EMPTY: Array[untyped]
5
+
4
6
  VERSION: String
5
7
 
6
8
  type uri = URI::HTTP | URI::HTTPS | string
@@ -10,6 +12,8 @@ module HTTPX
10
12
  :propfind | :proppatch | :mkcol | :copy | :move | :lock | :unlock | :orderpatch |
11
13
  :acl | :report | :patch | :search
12
14
 
15
+ type ip_family = Integer #Socket::AF_INET6 | Socket::AF_INET
16
+
13
17
  module Plugins
14
18
  def self?.load_plugin: (Symbol) -> Module
15
19
 
data/sig/options.rbs CHANGED
@@ -83,18 +83,16 @@ module HTTPX
83
83
 
84
84
  attr_reader response_body_class: singleton(Response::Body)
85
85
 
86
- attr_reader ssl: Hash[Symbol, untyped]
86
+ attr_reader resolver_class: Symbol | Class
87
87
 
88
- # request_class response_class headers_class request_body_class
89
- # response_body_class connection_class
90
- # resolver_class resolver_options
88
+ attr_reader ssl: Hash[Symbol, untyped]
91
89
 
92
90
  # io
93
91
  type io_option = _ToIO | Hash[String, _ToIO]
94
92
  attr_reader io: io_option?
95
93
 
96
94
  # fallback_protocol
97
- attr_reader fallback_protocol: String?
95
+ attr_reader fallback_protocol: String
98
96
 
99
97
  # debug
100
98
  attr_reader debug: _IOLogger?
@@ -103,10 +101,13 @@ module HTTPX
103
101
  attr_reader debug_level: Integer
104
102
 
105
103
  # persistent
106
- attr_reader persistent: bool?
104
+ attr_reader persistent: bool
107
105
 
108
106
  # resolver_options
109
- attr_reader resolver_options: Hash[Symbol, untyped]?
107
+ attr_reader resolver_options: Hash[Symbol, untyped]
108
+
109
+ # ip_families
110
+ attr_reader ip_families: Array[ip_family]
110
111
 
111
112
  def ==: (untyped other) -> bool
112
113
  def merge: (_ToHash[Symbol, untyped] other) -> instance
@@ -117,6 +118,8 @@ module HTTPX
117
118
  REQUEST_IVARS: Array[Symbol]
118
119
 
119
120
  def initialize: (?options options) -> untyped
121
+
122
+ def __initialize__: (?options options) -> untyped
120
123
  end
121
124
 
122
125
  type options = Options | Hash[Symbol, untyped]