httpx 1.8.3 → 1.8.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5faeb9a08adff992ddd2661b4ccd5176cb2c49d17dbb6a0ea593e1a00c10f35b
4
- data.tar.gz: 04f81429bbe03762c641531f0886c9b133f8fa04f8607943534ae36736f705e7
3
+ metadata.gz: daca70f040a0f0afcc413a6eb3b2e586ae56a5405477c0045cf226aaddf5b49c
4
+ data.tar.gz: 53910e19b4bf264a2d3cf4aed4298de57c4c6373f868e3d9e187140c15f2ed63
5
5
  SHA512:
6
- metadata.gz: e750874b2e206ff8604e804fa526847cc40c5511608d818c3a4a7c3136b383f5ca7c8baffbc856bd080ca0b77becc9ebc10d88e7743b5a757c7dd00b49a7e57c
7
- data.tar.gz: 0e6e2f5aaf85be60d2fc044cad8ad7e215ae9a7768c11681f0ea5a5bcb264f3f7b8fb3aaf5a21bb2c94a8b03445ac26e0972e637ebc3a30d4f204238d79dbb96
6
+ metadata.gz: 8b19e3219fb672bfbb45c4e5427c68b9f7ba715003f5b39796a2314bd8b991b58c5bc185767e303557159f04d61d84c19523f25b953b604a74753e55859defb8
7
+ data.tar.gz: 844bf656335bdbc5599003d6ee9724ff54b05478bfa9de37d5e251acff788154d4d7cea4b866b56c7d4c42d07b1afa8ece6982b02c5236d981843f092ee25ceb
@@ -0,0 +1,13 @@
1
+ # 1.8.4
2
+
3
+ ## Improvements
4
+
5
+ * send requests which were not sent, or were not processed by the server, when the server sends back a GOAWAY frame (which is deemed recoverable, like when there's no error), after forcing a reconnection (instead of bubbling up the GOAWAY error for all of them).
6
+
7
+ ## Bugfixes
8
+
9
+ * `:retries` plugin: also retry requests which failed due to a RST_STREAM frame with REFUSED_STREAM error code.
10
+ * `:retries` plugin: resend requests which were piped to a closed connection internally.
11
+ * `:proxy` plugin: fix issue related with reconnecting inactive connections shut down by the peer, when used with the `:persistent` plugin, where the CONNECT request wasn't being sent to establish the tunnel.
12
+ * fixed compatibility issue starting with the `json` gem 3.0.0, when calling `HTTPX::Response#json`.
13
+ * avoid bookkepping issue in session, where the `on_response_arrived` on a request may be called more than once (which it can happen in the `:follow_redirects` plugin, where a request may have completed due to an error, while the request is waiting to be resent due to `retry-after`).
@@ -14,9 +14,9 @@ module HTTPX
14
14
  end
15
15
  end
16
16
 
17
- def emit(type, *args)
17
+ def emit(type, ...)
18
18
  log { "emit #{type.inspect} callbacks" } if respond_to?(:log)
19
- callbacks(type).delete_if { |pr| :delete == pr.call(*args) } # rubocop:disable Style/YodaCondition
19
+ callbacks(type).delete_if { |pr| :delete == pr.call(...) } # rubocop:disable Style/YodaCondition
20
20
  end
21
21
 
22
22
  def callbacks_for?(type)
@@ -13,8 +13,8 @@ module HTTPX
13
13
  end
14
14
 
15
15
  # delegates to the default session (see HTTPX::Session#request).
16
- def request(*args, **options)
17
- branch(default_options).request(*args, **options)
16
+ def request(...)
17
+ branch(default_options).request(...)
18
18
  end
19
19
 
20
20
  def accept(type)
@@ -23,9 +23,29 @@ module HTTPX
23
23
  end
24
24
 
25
25
  class GoawayError < Error
26
- def initialize(code = :no_error)
26
+ UNRECOVERABLE_ERRORS = %i[settings_timeout inadequate_security].freeze
27
+
28
+ def initialize(code, last_stream_id)
29
+ @code = code
30
+ @last_stream_id = last_stream_id
27
31
  super(0, code)
28
32
  end
33
+
34
+ def last_stream_id
35
+ return Float::INFINITY if unrecoverable?
36
+
37
+ @last_stream_id
38
+ end
39
+
40
+ def unrecoverable?
41
+ UNRECOVERABLE_ERRORS.include?(@code)
42
+ end
43
+ end
44
+
45
+ class RstStreamError < Error
46
+ end
47
+
48
+ class RefusedStreamError < RstStreamError
29
49
  end
30
50
 
31
51
  attr_reader :streams, :pending
@@ -149,18 +169,43 @@ module HTTPX
149
169
  end
150
170
 
151
171
  def handle_error(ex, request = nil)
152
- if ex.is_a?(OperationTimeoutError) && !@handshake_completed && @connection.state != :closed
153
- @connection.goaway(:settings_timeout, "closing due to settings timeout")
154
- emit(:close_handshake)
155
- settings_ex = SettingsTimeoutError.new(ex.timeout, ex.message)
156
- settings_ex.set_backtrace(ex.backtrace)
157
- ex = settings_ex
158
- end
159
- while (req, _ = @streams.shift)
172
+ last_stream_id = Float::INFINITY
173
+ case ex
174
+ when OperationTimeoutError
175
+ if !@handshake_completed && @connection.state != :closed
176
+ @connection.goaway(:settings_timeout, "closing due to settings timeout")
177
+ emit(:close_handshake)
178
+ settings_ex = SettingsTimeoutError.new(ex.timeout, ex.message)
179
+ settings_ex.set_backtrace(ex.backtrace)
180
+ ex = settings_ex
181
+ end
182
+ when GoawayError
183
+ last_stream_id = ex.last_stream_id
184
+ end
185
+
186
+ inflight_unprocessed_requests = [] #: Array[Request]
187
+
188
+ while (req, stream = @streams.shift)
160
189
  next if request && request == req
161
190
 
191
+ if stream.id > last_stream_id
192
+ req.transition(:idle)
193
+ # unprocessed request
194
+ inflight_unprocessed_requests << req
195
+
196
+ next
197
+ end
198
+
162
199
  emit(:error, req, ex)
163
200
  end
201
+
202
+ if ex.is_a?(GoawayError) && !ex.unrecoverable?
203
+ # resend unprocessed requests on a different connection
204
+ @pending.unshift(*inflight_unprocessed_requests) if inflight_unprocessed_requests.any?
205
+ emit(:exhausted, ex) if @pending.any?
206
+ return
207
+ end
208
+
164
209
  while (req = @pending.shift)
165
210
  next if request && request == req
166
211
 
@@ -395,7 +440,14 @@ module HTTPX
395
440
  when :http_1_1_required
396
441
  emit(:error, request, error)
397
442
  else
398
- ex = Error.new(stream.id, error)
443
+ ex =
444
+ case error
445
+ when :refused_stream
446
+ RefusedStreamError.new(stream.id, error)
447
+ else
448
+ RstStreamError.new(stream.id, error)
449
+ end
450
+
399
451
  ex.set_backtrace(caller)
400
452
  response = ErrorResponse.new(request, ex)
401
453
  request.response = response
@@ -432,7 +484,7 @@ module HTTPX
432
484
  send_pending
433
485
  end
434
486
 
435
- def on_close(_last_frame, error, _payload)
487
+ def on_close(last_stream_id, error, _payload)
436
488
  is_connection_closed = @connection.closed?
437
489
  if error
438
490
  @buffer.clear if is_connection_closed
@@ -442,12 +494,11 @@ module HTTPX
442
494
  emit(:error, request, error)
443
495
  end
444
496
  else
445
- ex = GoawayError.new(error)
497
+ ex = GoawayError.new(error, last_stream_id)
446
498
  ex.set_backtrace(caller)
447
499
 
448
500
  handle_error(ex)
449
501
  teardown
450
-
451
502
  end
452
503
  end
453
504
  return unless is_connection_closed && @streams.empty?
@@ -51,7 +51,10 @@ module HTTPX
51
51
  @callbacks = @ping_timer = @family =
52
52
  @io = @ssl_session = @timeout = @connected_at = @response_received_at = nil
53
53
 
54
- @exhausted = @cloned = @main_sibling = false
54
+ @exhausted = @cloned = @main_sibling =
55
+ # variable used to gate against a potential endless loop where the peer continuously closes the connection with
56
+ # GOAWAY frames without ever processing a request.
57
+ @previously_exhausted_with_error = false
55
58
 
56
59
  @options = Options.new(options)
57
60
  @type = initialize_type(uri, @options)
@@ -711,6 +714,7 @@ module HTTPX
711
714
  AltSvc.emit(request, response) do |alt_origin, origin, alt_params|
712
715
  build_altsvc_connection(alt_origin, origin, alt_params)
713
716
  end
717
+ @previously_exhausted_with_error = false
714
718
  @response_received_at = Utils.now
715
719
  @no_more_requests_counter = 0
716
720
  @inflight -= 1
@@ -726,9 +730,19 @@ module HTTPX
726
730
  parser.on(:promise) do |request, stream|
727
731
  request.emit(:promise, parser, stream)
728
732
  end
729
- parser.on(:exhausted) do
733
+ parser.on(:exhausted) do |error|
730
734
  enqueue_pending_requests_from_parser(parser)
731
735
 
736
+ if error
737
+ if @previously_exhausted_with_error
738
+ @previously_exhausted_with_error = false
739
+ on_error(error)
740
+ next
741
+ else
742
+ @previously_exhausted_with_error = true
743
+ end
744
+ end
745
+
732
746
  @exhausted = true
733
747
  parser.close
734
748
 
@@ -68,7 +68,7 @@ module HTTPX
68
68
  end
69
69
 
70
70
  class << self
71
- def new(cookie, *args)
71
+ def new(cookie, *)
72
72
  case cookie
73
73
  when self
74
74
  cookie
@@ -46,8 +46,8 @@ module HTTPX
46
46
 
47
47
  # factory method to return a Jar to the user, which can then manipulate
48
48
  # externally to the session.
49
- def make_jar(*args)
50
- Jar.new(*args)
49
+ def make_jar(...)
50
+ Jar.new(...)
51
51
  end
52
52
 
53
53
  private
@@ -75,9 +75,12 @@ module HTTPX
75
75
 
76
76
  max_redirects = redirect_request.max_redirects
77
77
 
78
- return response unless response.is_a?(Response)
79
- return response unless REDIRECT_STATUS.include?(response.status) && response.headers.key?("location")
80
- return response unless max_redirects.positive?
78
+ return response unless response.is_a?(Response) &&
79
+ # it's a redirect response with location
80
+ REDIRECT_STATUS.include?(response.status) &&
81
+ response.headers.key?("location") &&
82
+ # maximum number of redirects hasn't been reached yet
83
+ max_redirects.positive?
81
84
 
82
85
  redirect_uri = __get_location_from_response(response)
83
86
 
@@ -190,8 +193,7 @@ module HTTPX
190
193
 
191
194
  # :nodoc:
192
195
  def __get_location_from_response(response)
193
- # @type var location_uri: http_uri
194
- location_uri = URI(response.headers["location"])
196
+ location_uri = URI(response.headers["location"]) #: http_uri
195
197
  location_uri = response.uri.merge(location_uri) if location_uri.relative?
196
198
  location_uri
197
199
  end
@@ -48,12 +48,12 @@ module HTTPX
48
48
  end
49
49
  end
50
50
 
51
- def respond_to_missing?(meth, *args, &blk)
52
- grpc_response.respond_to?(meth, *args) || super
51
+ def respond_to_missing?(meth, ...)
52
+ grpc_response.respond_to?(meth, ...) || super
53
53
  end
54
54
 
55
- def method_missing(meth, *args, &blk)
56
- return grpc_response.__send__(meth, *args, &blk) if grpc_response.respond_to?(meth)
55
+ def method_missing(meth, ...)
56
+ return grpc_response.__send__(meth, ...) if grpc_response.respond_to?(meth)
57
57
 
58
58
  super
59
59
  end
@@ -78,8 +78,8 @@ module HTTPX
78
78
  end
79
79
  end
80
80
 
81
- def self.encode(*args, **kwargs)
82
- Deflater.new(*args, **kwargs)
81
+ def self.encode(...)
82
+ Deflater.new(...)
83
83
  end
84
84
 
85
85
  def self.decode(response)
@@ -46,6 +46,11 @@ module HTTPX
46
46
  end
47
47
 
48
48
  module ConnectionMethods
49
+ def initialize(*)
50
+ @tunnel_parser = nil
51
+ super
52
+ end
53
+
49
54
  def force_close(*)
50
55
  if @state == :connecting
51
56
  # proxy connect related requests should not be reenqueed
@@ -59,6 +64,12 @@ module HTTPX
59
64
 
60
65
  private
61
66
 
67
+ def purge_after_closed
68
+ super
69
+
70
+ @tunnel_parser = nil
71
+ end
72
+
62
73
  def handle_transition(nextstate)
63
74
  return super unless @options.proxy && @options.proxy.uri.scheme == "http"
64
75
 
@@ -69,8 +80,15 @@ module HTTPX
69
80
  @io.connect
70
81
  return unless @io.connected?
71
82
 
72
- @parser || begin
73
- @parser = parser = parser_type(@io.protocol).new(@write_buffer, @options.merge(max_concurrent_requests: 1))
83
+ @tunnel_parser || begin
84
+ if @parser
85
+ # in case this happens, requests from @parser need to be reenqueued for delivery.
86
+ enqueue_pending_requests_from_parser(@parser)
87
+ @parser = nil
88
+ end
89
+
90
+ @tunnel_parser = @parser = parser =
91
+ parser_type(@io.protocol).new(@write_buffer, @options.merge(max_concurrent_requests: 1))
74
92
  parser.extend(ProxyParser)
75
93
  parser.on(:response, &method(:__http_on_connect))
76
94
  parser.on(:close) do
@@ -86,6 +104,9 @@ module HTTPX
86
104
 
87
105
  initial_state = @state
88
106
 
107
+ # because #reset will nillify @parser...
108
+ tunnel_parser = @parser
109
+
89
110
  reset
90
111
 
91
112
  if @pending.empty?
@@ -98,8 +119,8 @@ module HTTPX
98
119
  connect_request = parser = nil
99
120
 
100
121
  if initial_state == :connecting
101
- parser = @parser
102
- @parser.reset
122
+ parser = tunnel_parser
123
+ parser.reset
103
124
  if @pending.first.is_a?(ConnectRequest)
104
125
  connect_request = @pending.shift # this happened when reenqueing
105
126
  end
@@ -107,7 +128,7 @@ module HTTPX
107
128
 
108
129
  idling
109
130
 
110
- @parser = parser
131
+ @tunnel_parser = @parser = parser
111
132
  if connect_request
112
133
  @inflight += 1
113
134
  parser.send(connect_request)
@@ -124,7 +145,7 @@ module HTTPX
124
145
  case @state
125
146
  when :connecting
126
147
  parser = @parser
127
- @parser = nil
148
+ @tunnel_parser = @parser = nil
128
149
  parser.close
129
150
  when :idle
130
151
  @parser.callbacks.clear
@@ -92,16 +92,16 @@ module HTTPX
92
92
  @authenticator = load_authenticator(scheme, @username, @password)
93
93
  end
94
94
 
95
- def can_authenticate?(*args)
95
+ def can_authenticate?(...)
96
96
  return false unless @authenticator && @authenticator.respond_to?(:can_authenticate?)
97
97
 
98
- @authenticator.can_authenticate?(*args)
98
+ @authenticator.can_authenticate?(...)
99
99
  end
100
100
 
101
- def authenticate(*args)
101
+ def authenticate(...)
102
102
  return unless @authenticator
103
103
 
104
- @authenticator.authenticate(*args)
104
+ @authenticator.authenticate(...)
105
105
  end
106
106
 
107
107
  def ==(other)
@@ -31,11 +31,21 @@ module HTTPX
31
31
  TLSError,
32
32
  Zlib::BufError,
33
33
  PingTimeoutError,
34
+ # HTTP/2 GOAWAY or RST_STREAM errors guaranteed to be retriable for all
35
+ # types of requests.
36
+ Connection::HTTP2::RefusedStreamError,
34
37
  Connection::HTTP2::GoawayError,
35
38
  Connection::HTTP2::PingError,
39
+
40
+ # happens if connections were somehow sent to a closed or closing
41
+ # HTTP2::Connection, request guaranteed to not have been processed.
42
+ ::HTTP2::Error::ConnectionClosed,
36
43
  ].freeze
37
44
 
38
45
  RETRYABLE_ERRORS = (RECONNECTABLE_ERRORS + [
46
+ # most RST_STREAM errors aren't safely retriable, as request may have
47
+ # been partially processed.
48
+ Connection::HTTP2::RstStreamError,
39
49
  Parser::Error,
40
50
  TimeoutError,
41
51
  ]).freeze
@@ -256,7 +266,7 @@ module HTTPX
256
266
  attr_writer :partial_response
257
267
 
258
268
  # initializes the request instance, sets the number of retries for the request.
259
- def initialize(*args)
269
+ def initialize(*)
260
270
  super
261
271
  @retries = @options.max_retries
262
272
  @partial_response = nil
@@ -40,7 +40,7 @@ module HTTPX
40
40
  end
41
41
 
42
42
  module InstanceMethods
43
- def request(*args, **options)
43
+ def request(*, **options)
44
44
  options[:stream] = true if options[:event_stream]
45
45
 
46
46
  super
@@ -111,10 +111,10 @@ module HTTPX
111
111
  end || super
112
112
  end
113
113
 
114
- def method_missing(meth, *args, **kwargs, &block)
114
+ def method_missing(meth, ...)
115
115
  return super unless response.respond_to?(meth)
116
116
 
117
- response.__send__(meth, *args, **kwargs, &block)
117
+ response.__send__(meth, ...)
118
118
  end
119
119
  end
120
120
 
@@ -36,9 +36,9 @@ module HTTPX::Plugins
36
36
  %i[start finish reset enabled?].each do |callback|
37
37
  class_eval(<<-OUT, __FILE__, __LINE__ + 1)
38
38
  # proxies ##{callback} calls to wrapper tracers.
39
- def #{callback}(*args) # def start(*args)
40
- @tracers.each { |t| t.#{callback}(*args) } # @tracers.each { |t| t.start(*args) }
41
- end # end
39
+ def #{callback}(...) # def start(...)
40
+ @tracers.each { |t| t.#{callback}(...) } # @tracers.each { |t| t.start(....) }
41
+ end # end
42
42
  OUT
43
43
  end
44
44
  end
data/lib/httpx/request.rb CHANGED
@@ -107,7 +107,7 @@ module HTTPX
107
107
  @connection = @response =
108
108
  @drainer = @peer_address = @callbacks =
109
109
  @informational_status = @on_response_arrived = nil
110
- @ping = @started = false
110
+ @ping = @started = @complete = false
111
111
  @persistent = @options.persistent
112
112
  @active_timeouts = []
113
113
  end
@@ -121,8 +121,11 @@ module HTTPX
121
121
  end
122
122
 
123
123
  def complete!(response = @response)
124
+ return false if @complete
125
+
124
126
  emit(:complete, response)
125
127
  reset_timers(true)
128
+ @complete = true
126
129
  end
127
130
 
128
131
  # whether request has been buffered with a ping
@@ -296,7 +299,7 @@ module HTTPX
296
299
  case nextstate
297
300
  when :idle
298
301
  @body.rewind
299
- @ping = false
302
+ @ping = @complete = false
300
303
  @response = @drainer = nil
301
304
 
302
305
  # request may be sent to a different connection and will be
@@ -35,8 +35,8 @@ module HTTPX
35
35
  @resolvers.each { |r| r.current_session = s }
36
36
  end
37
37
 
38
- def log(*args, **kwargs, &blk)
39
- @resolvers.each { |r| r.log(*args, **kwargs, &blk) }
38
+ def log(...)
39
+ @resolvers.each { |r| r.log(...) }
40
40
  end
41
41
 
42
42
  def closed?
@@ -56,9 +56,9 @@ module HTTPX
56
56
  call
57
57
  end
58
58
 
59
- def force_close(*args)
59
+ def force_close(...)
60
60
  while (connection = @connections.shift)
61
- connection.force_close(*args)
61
+ connection.force_close(...)
62
62
  end
63
63
  end
64
64
 
@@ -69,7 +69,7 @@ module HTTPX
69
69
  end
70
70
 
71
71
  # reads a chunk from the payload (implementation of the IO reader protocol).
72
- def read(*args)
72
+ def read(...)
73
73
  return unless @buffer
74
74
 
75
75
  unless @reader
@@ -77,7 +77,7 @@ module HTTPX
77
77
  @reader = @buffer
78
78
  end
79
79
 
80
- @reader.read(*args)
80
+ @reader.read(...)
81
81
  end
82
82
 
83
83
  # size of the decoded response payload. May differ from "content-length" header if
@@ -176,8 +176,8 @@ module HTTPX
176
176
  #
177
177
  # response.json #≈> { "foo" => "bar" } for "{\"foo\":\"bar\"}" payload
178
178
  # response.json(symbolize_names: true) #≈> { foo: "bar" } for "{\"foo\":\"bar\"}" payload
179
- def json(*args)
180
- decode(Transcoder::JSON, *args)
179
+ def json(...)
180
+ decode(Transcoder::JSON, ...)
181
181
  end
182
182
 
183
183
  # decodes the response payload into a ruby object **if** the payload is valid
@@ -200,7 +200,7 @@ module HTTPX
200
200
  #
201
201
  # +transcoder+ must implement the internal transcoder API, i.e. respond to <tt>decode(HTTPX::Response response)</tt>,
202
202
  # which returns a decoder which responds to <tt>call(HTTPX::Response response, **kwargs)</tt>
203
- def decode(transcoder, *args)
203
+ def decode(transcoder, ...)
204
204
  # TODO: check if content-type is a valid format, i.e. "application/json" for json parsing
205
205
 
206
206
  decoder = transcoder.decode(self)
@@ -209,7 +209,7 @@ module HTTPX
209
209
 
210
210
  @body.rewind
211
211
 
212
- decoder.call(self, *args)
212
+ decoder.call(self, ...)
213
213
  end
214
214
  end
215
215
 
data/lib/httpx/session.rb CHANGED
@@ -355,7 +355,8 @@ module HTTPX
355
355
  # making the next loop cheaper (because we're dropping).
356
356
  next unless response
357
357
 
358
- request.complete!(response)
358
+ next unless request.complete!(response)
359
+
359
360
  responses[idx] = response
360
361
  request.on_response_arrived = nil
361
362
  pending -= 1
@@ -24,8 +24,8 @@ module HTTPX::Transcoder
24
24
  yield "0#{CRLF}"
25
25
  end
26
26
 
27
- def respond_to_missing?(meth, *args)
28
- @raw.respond_to?(meth, *args) || super
27
+ def respond_to_missing?(...)
28
+ @raw.respond_to?(...) || super
29
29
  end
30
30
  end
31
31
 
@@ -53,18 +53,18 @@ module HTTPX::Transcoder
53
53
 
54
54
  # rubocop:disable-next Style/SingleLineMethods
55
55
  if defined?(MultiJson)
56
- def json_load(*args); MultiJson.load(*args); end
57
- def json_dump(*args); MultiJson.dump(*args); end
56
+ def json_load(...); MultiJson.load(...); end
57
+ def json_dump(...); MultiJson.dump(...); end
58
58
  elsif defined?(Oj)
59
- def json_load(response, *args); Oj.load(response.to_s, *args); end
59
+ def json_load(response, ...); Oj.load(response.to_s, ...); end
60
60
  def json_dump(obj, options = {}); Oj.dump(obj, { mode: :compat }.merge(options)); end
61
61
  elsif defined?(Yajl)
62
- def json_load(response, *args); Yajl::Parser.new(*args).parse(response.to_s); end
63
- def json_dump(*args); Yajl::Encoder.encode(*args); end
62
+ def json_load(response, ...); Yajl::Parser.new(...).parse(response.to_s); end
63
+ def json_dump(...); Yajl::Encoder.encode(...); end
64
64
  else
65
65
  require "json"
66
- def json_load(*args); ::JSON.parse(*args); end
67
- def json_dump(*args); ::JSON.generate(*args); end
66
+ def json_load(...); ::JSON.parse(...); end
67
+ def json_dump(...); ::JSON.generate(...); end
68
68
  end
69
69
  end
70
70
  end
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.8.3"
4
+ VERSION = "1.8.4"
5
5
  end
@@ -116,11 +116,25 @@ module HTTPX
116
116
  end
117
117
 
118
118
  class GoawayError < Error
119
- def initialize: (?Symbol code) -> void
119
+ UNRECOVERABLE_ERRORS: Array[Symbol]
120
+
121
+ @code: Symbol
122
+
123
+ def initialize: (Symbol code, Integer last_stream_id) -> void
124
+
125
+ def last_stream_id: () -> Numeric
126
+
127
+ def unrecoverable?: () -> bool
120
128
  end
121
129
 
122
130
  class PingError < Error
123
131
  def initialize: () -> void
124
132
  end
133
+
134
+ class RstStreamError < Error
135
+ end
136
+
137
+ class RefusedStreamError < Error
138
+ end
125
139
  end
126
140
  end
data/sig/connection.rbs CHANGED
@@ -47,6 +47,7 @@ module HTTPX
47
47
  @response_received_at: Float
48
48
  @exhausted: bool
49
49
  @cloned: bool
50
+ @previously_exhausted_with_error: bool
50
51
  @coalesced_connection: instance?
51
52
  @altsvc_connection: instance?
52
53
  @sibling: instance?
@@ -12,6 +12,8 @@ module HTTPX
12
12
  end
13
13
 
14
14
  module ConnectionMethods
15
+ @tunnel_parser: Connection::HTTP1 | Connection::HTTP2
16
+
15
17
  def __http_proxy_connect: (Connection::_Parser parser) -> void
16
18
  def __http_on_connect: (top, Response) -> void
17
19
  end
data/sig/request.rbs CHANGED
@@ -32,10 +32,11 @@ module HTTPX
32
32
  @query: String?
33
33
  @drainer: Enumerator[String, void]?
34
34
  @started: bool
35
+ @complete: bool
35
36
 
36
37
  def initialize: (Symbol | String verb, generic_uri uri, Options options, ?request_params params) -> untyped
37
38
 
38
- def complete!: (?response response) -> void
39
+ def complete!: (?response response) -> bool
39
40
 
40
41
  def started?: () -> bool
41
42
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.3
4
+ version: 1.8.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
@@ -172,6 +172,7 @@ extra_rdoc_files:
172
172
  - doc/release_notes/1_8_1.md
173
173
  - doc/release_notes/1_8_2.md
174
174
  - doc/release_notes/1_8_3.md
175
+ - doc/release_notes/1_8_4.md
175
176
  files:
176
177
  - LICENSE.txt
177
178
  - README.md
@@ -316,6 +317,7 @@ files:
316
317
  - doc/release_notes/1_8_1.md
317
318
  - doc/release_notes/1_8_2.md
318
319
  - doc/release_notes/1_8_3.md
320
+ - doc/release_notes/1_8_4.md
319
321
  - lib/httpx.rb
320
322
  - lib/httpx/adapters/datadog.rb
321
323
  - lib/httpx/adapters/faraday.rb