httpx 1.0.2 → 1.1.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/doc/release_notes/1_1_0.md +32 -0
  4. data/doc/release_notes/1_1_1.md +17 -0
  5. data/lib/httpx/adapters/faraday.rb +28 -19
  6. data/lib/httpx/connection/http1.rb +13 -6
  7. data/lib/httpx/connection/http2.rb +1 -1
  8. data/lib/httpx/connection.rb +53 -15
  9. data/lib/httpx/domain_name.rb +6 -2
  10. data/lib/httpx/errors.rb +32 -0
  11. data/lib/httpx/io/ssl.rb +3 -1
  12. data/lib/httpx/io/tcp.rb +4 -2
  13. data/lib/httpx/io.rb +5 -1
  14. data/lib/httpx/options.rb +48 -1
  15. data/lib/httpx/plugins/expect.rb +10 -8
  16. data/lib/httpx/plugins/proxy/http.rb +0 -1
  17. data/lib/httpx/pool.rb +0 -4
  18. data/lib/httpx/request/body.rb +22 -9
  19. data/lib/httpx/request.rb +63 -4
  20. data/lib/httpx/resolver/native.rb +2 -2
  21. data/lib/httpx/resolver/resolver.rb +5 -2
  22. data/lib/httpx/resolver/system.rb +5 -2
  23. data/lib/httpx/resolver.rb +6 -4
  24. data/lib/httpx/response/body.rb +30 -5
  25. data/lib/httpx/response/buffer.rb +20 -14
  26. data/lib/httpx/response.rb +95 -16
  27. data/lib/httpx/selector.rb +2 -2
  28. data/lib/httpx/session.rb +64 -2
  29. data/lib/httpx/timers.rb +35 -8
  30. data/lib/httpx/transcoder/json.rb +1 -1
  31. data/lib/httpx/transcoder/utils/inflater.rb +19 -0
  32. data/lib/httpx/version.rb +1 -1
  33. data/sig/connection/http1.rbs +3 -3
  34. data/sig/connection/http2.rbs +1 -1
  35. data/sig/connection.rbs +4 -1
  36. data/sig/io/tcp.rbs +1 -1
  37. data/sig/options.rbs +2 -2
  38. data/sig/pool.rbs +1 -1
  39. data/sig/request/body.rbs +0 -2
  40. data/sig/request.rbs +9 -3
  41. data/sig/resolver/native.rbs +1 -1
  42. data/sig/resolver.rbs +1 -1
  43. data/sig/response/body.rbs +0 -1
  44. data/sig/response.rbs +11 -3
  45. data/sig/timers.rbs +17 -7
  46. data/sig/transcoder/utils/inflater.rbs +12 -0
  47. metadata +8 -2
@@ -7,24 +7,48 @@ require "fileutils"
7
7
  require "forwardable"
8
8
 
9
9
  module HTTPX
10
+ # Defines a HTTP response is handled internally, with a few properties exposed as attributes,
11
+ # implements (indirectly, via the +body+) the IO write protocol to internally buffer payloads,
12
+ # implements the IO reader protocol in order for users to buffer/stream it, acts as an enumerable
13
+ # (of payload chunks).
10
14
  class Response
11
15
  extend Forwardable
12
16
  include Callbacks
13
17
 
14
- attr_reader :status, :headers, :body, :version
18
+ # the HTTP response status code
19
+ attr_reader :status
15
20
 
21
+ # an HTTPX::Headers object containing the response HTTP headers.
22
+ attr_reader :headers
23
+
24
+ # a HTTPX::Response::Body object wrapping the response body.
25
+ attr_reader :body
26
+
27
+ # The HTTP protocol version used to fetch the response.
28
+ attr_reader :version
29
+
30
+ # returns the response body buffered in a string.
16
31
  def_delegator :@body, :to_s
17
32
 
18
33
  def_delegator :@body, :to_str
19
34
 
35
+ # implements the IO reader +#read+ interface.
20
36
  def_delegator :@body, :read
21
37
 
38
+ # copies the response body to a different location.
22
39
  def_delegator :@body, :copy_to
23
40
 
41
+ # closes the body.
24
42
  def_delegator :@body, :close
25
43
 
44
+ # the corresponding request uri.
26
45
  def_delegator :@request, :uri
27
46
 
47
+ # the IP address of the peer server.
48
+ def_delegator :@request, :peer_address
49
+
50
+ # inits the instance with the corresponding +request+ to this response, an the
51
+ # response HTTP +status+, +version+ and HTTPX::Headers instance of +headers+.
28
52
  def initialize(request, status, version, headers)
29
53
  @request = request
30
54
  @options = request.options
@@ -33,32 +57,49 @@ module HTTPX
33
57
  @headers = @options.headers_class.new(headers)
34
58
  @body = @options.response_body_class.new(self, @options)
35
59
  @finished = complete?
60
+ @content_type = nil
36
61
  end
37
62
 
63
+ # merges headers defined in +h+ into the response headers.
38
64
  def merge_headers(h)
39
65
  @headers = @headers.merge(h)
40
66
  end
41
67
 
68
+ # writes +data+ chunk into the response body.
42
69
  def <<(data)
43
70
  @body.write(data)
44
71
  end
45
72
 
73
+ # returns the response mime type, as per what's declared in the content-type header.
74
+ #
75
+ # response.content_type #=> "text/plain"
46
76
  def content_type
47
77
  @content_type ||= ContentType.new(@headers["content-type"])
48
78
  end
49
79
 
80
+ # returns whether the response has been fully fetched.
50
81
  def finished?
51
82
  @finished
52
83
  end
53
84
 
85
+ # marks the response as finished, freezes the headers.
54
86
  def finish!
55
87
  @finished = true
56
88
  @headers.freeze
57
89
  end
58
90
 
91
+ # returns whether the response contains body payload.
59
92
  def bodyless?
60
93
  @request.verb == "HEAD" ||
61
- no_data?
94
+ @status < 200 || # informational response
95
+ @status == 204 ||
96
+ @status == 205 ||
97
+ @status == 304 || begin
98
+ content_length = @headers["content-length"]
99
+ return false if content_length.nil?
100
+
101
+ content_length == "0"
102
+ end
62
103
  end
63
104
 
64
105
  def complete?
@@ -75,32 +116,53 @@ module HTTPX
75
116
  end
76
117
  # :nocov:
77
118
 
119
+ # returns an instance of HTTPX::HTTPError if the response has a 4xx or 5xx
120
+ # status code, or nothing.
121
+ #
122
+ # ok_response.error #=> nil
123
+ # not_found_response.error #=> HTTPX::HTTPError instance, status 404
78
124
  def error
79
125
  return if @status < 400
80
126
 
81
127
  HTTPError.new(self)
82
128
  end
83
129
 
130
+ # it raises the exception returned by +error+, or itself otherwise.
131
+ #
132
+ # ok_response.raise_for_status #=> ok_response
133
+ # not_found_response.raise_for_status #=> raises HTTPX::HTTPError exception
84
134
  def raise_for_status
85
135
  return self unless (err = error)
86
136
 
87
137
  raise err
88
138
  end
89
139
 
140
+ # decodes the response payload into a ruby object **if** the payload is valid json.
141
+ #
142
+ # response.json #≈> { "foo" => "bar" } for "{\"foo\":\"bar\"}" payload
143
+ # response.json(symbolize_names: true) #≈> { foo: "bar" } for "{\"foo\":\"bar\"}" payload
90
144
  def json(*args)
91
145
  decode(Transcoder::JSON, *args)
92
146
  end
93
147
 
148
+ # decodes the response payload into a ruby object **if** the payload is valid
149
+ # "application/x-www-urlencoded" or "multipart/form-data".
94
150
  def form
95
151
  decode(Transcoder::Form)
96
152
  end
97
153
 
154
+ # decodes the response payload into a Nokogiri::XML::Node object **if** the payload is valid
155
+ # "application/xml" (requires the "nokogiri" gem).
98
156
  def xml
99
157
  decode(Transcoder::Xml)
100
158
  end
101
159
 
102
160
  private
103
161
 
162
+ # decodes the response payload using the given +transcoder+, which implements the decoding logic.
163
+ #
164
+ # +transcoder+ must implement the internal transcoder API, i.e. respond to <tt>decode(HTTPX::Response response)</tt>,
165
+ # which returns a decoder which responds to <tt>call(HTTPX::Response response, **kwargs)</tt>
104
166
  def decode(transcoder, *args)
105
167
  # TODO: check if content-type is a valid format, i.e. "application/json" for json parsing
106
168
 
@@ -112,20 +174,9 @@ module HTTPX
112
174
 
113
175
  decoder.call(self, *args)
114
176
  end
115
-
116
- def no_data?
117
- @status < 200 || # informational response
118
- @status == 204 ||
119
- @status == 205 ||
120
- @status == 304 || begin
121
- content_length = @headers["content-length"]
122
- return false if content_length.nil?
123
-
124
- content_length == "0"
125
- end
126
- end
127
177
  end
128
178
 
179
+ # Helper class which decodes the HTTP "content-type" header.
129
180
  class ContentType
130
181
  MIME_TYPE_RE = %r{^([^/]+/[^;]+)(?:$|;)}.freeze
131
182
  CHARSET_RE = /;\s*charset=([^;]+)/i.freeze
@@ -134,6 +185,9 @@ module HTTPX
134
185
  @header_value = header_value
135
186
  end
136
187
 
188
+ # returns the mime type declared in the header.
189
+ #
190
+ # ContentType.new("application/json; charset=utf-8").mime_type #=> "application/json"
137
191
  def mime_type
138
192
  return @mime_type if defined?(@mime_type)
139
193
 
@@ -141,6 +195,10 @@ module HTTPX
141
195
  m && @mime_type = m.strip.downcase
142
196
  end
143
197
 
198
+ # returns the charset declared in the header.
199
+ #
200
+ # ContentType.new("application/json; charset=utf-8").charset #=> "utf-8"
201
+ # ContentType.new("text/plain").charset #=> nil
144
202
  def charset
145
203
  return @charset if defined?(@charset)
146
204
 
@@ -149,14 +207,31 @@ module HTTPX
149
207
  end
150
208
  end
151
209
 
210
+ # Wraps an error which has happened while processing an HTTP Request. It has partial
211
+ # public API parity with HTTPX::Response, so users should rely on it to infer whether
212
+ # the returned response is one or the other.
213
+ #
214
+ # response = HTTPX.get("https://some-domain/path") #=> response is HTTPX::Response or HTTPX::ErrorResponse
215
+ # response.raise_for_status #=> raises if it wraps an error
152
216
  class ErrorResponse
153
217
  include Loggable
154
218
  extend Forwardable
155
219
 
156
- attr_reader :request, :response, :error
220
+ # the corresponding HTTPX::Request instance.
221
+ attr_reader :request
157
222
 
223
+ # the HTTPX::Response instance, when there is one (i.e. error happens fetching the response).
224
+ attr_reader :response
225
+
226
+ # the wrapped exception.
227
+ attr_reader :error
228
+
229
+ # the request uri
158
230
  def_delegator :@request, :uri
159
231
 
232
+ # the IP address of the peer server.
233
+ def_delegator :@request, :peer_address
234
+
160
235
  def initialize(request, error, options)
161
236
  @request = request
162
237
  @response = request.response if request.response.is_a?(Response)
@@ -165,18 +240,22 @@ module HTTPX
165
240
  log_exception(@error)
166
241
  end
167
242
 
243
+ # returns the exception full message.
168
244
  def to_s
169
245
  @error.full_message(highlight: false)
170
246
  end
171
247
 
248
+ # closes the error resources.
172
249
  def close
173
- @response.close if @response.respond_to?(:close)
250
+ @response.close if @response && @response.respond_to?(:close)
174
251
  end
175
252
 
253
+ # always true for error responses.
176
254
  def finished?
177
255
  true
178
256
  end
179
257
 
258
+ # raises the wrapped exception.
180
259
  def raise_for_status
181
260
  raise @error
182
261
  end
@@ -73,7 +73,7 @@ class HTTPX::Selector
73
73
  readers, writers = IO.select(r, w, nil, interval)
74
74
 
75
75
  if readers.nil? && writers.nil? && interval
76
- [*r, *w].each { |io| io.raise_timeout_error(interval) }
76
+ [*r, *w].each { |io| io.handle_socket_timeout(interval) }
77
77
  return
78
78
  end
79
79
  rescue IOError, SystemCallError
@@ -110,7 +110,7 @@ class HTTPX::Selector
110
110
  end
111
111
 
112
112
  unless result || interval.nil?
113
- io.raise_timeout_error(interval)
113
+ io.handle_socket_timeout(interval)
114
114
  return
115
115
  end
116
116
  # raise HTTPX::TimeoutError.new(interval, "timed out while waiting on select")
data/lib/httpx/session.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTPX
4
+ # Class implementing the APIs being used publicly.
5
+ #
6
+ # HTTPX.get(..) #=> delegating to an internal HTTPX::Session object.
7
+ # HTTPX.plugin(..).get(..) #=> creating an intermediate HTTPX::Session with plugin, then sending the GET request
4
8
  class Session
5
9
  include Loggable
6
10
  include Chainable
@@ -8,6 +12,10 @@ module HTTPX
8
12
 
9
13
  EMPTY_HASH = {}.freeze
10
14
 
15
+ # initializes the session with a set of +options+, which will be shared by all
16
+ # requests sent from it.
17
+ #
18
+ # When pass a block, it'll yield itself to it, then closes after the block is evaluated.
11
19
  def initialize(options = EMPTY_HASH, &blk)
12
20
  @options = self.class.default_options.merge(options)
13
21
  @responses = {}
@@ -15,6 +23,11 @@ module HTTPX
15
23
  wrap(&blk) if blk
16
24
  end
17
25
 
26
+ # Yields itself the block, then closes it after the block is evaluated.
27
+ #
28
+ # session.wrap do |http|
29
+ # http.get("https://wikipedia.com")
30
+ # end # wikipedia connection closes here
18
31
  def wrap
19
32
  begin
20
33
  prev_persistent = @persistent
@@ -26,10 +39,31 @@ module HTTPX
26
39
  end
27
40
  end
28
41
 
42
+ # closes all the active connections from the session
29
43
  def close(*args)
30
44
  pool.close(*args)
31
45
  end
32
46
 
47
+ # performs one, or multple requests; it accepts:
48
+ #
49
+ # 1. one or multiple HTTPX::Request objects;
50
+ # 2. an HTTP verb, then a sequence of URIs or URI/options tuples;
51
+ # 3. one or multiple HTTP verb / uri / (optional) options tuples;
52
+ #
53
+ # when present, the set of +options+ kwargs is applied to all of the
54
+ # sent requests.
55
+ #
56
+ # respectively returns a single HTTPX::Response response, or all of them in an Array, in the same order.
57
+ #
58
+ # resp1 = session.request(req1)
59
+ # resp1, resp2 = session.request(req1, req2)
60
+ # resp1 = session.request("GET", "https://server.org/a")
61
+ # resp1, resp2 = session.request("GET", ["https://server.org/a", "https://server.org/b"])
62
+ # resp1, resp2 = session.request(["GET", "https://server.org/a"], ["GET", "https://server.org/b"])
63
+ # resp1 = session.request("POST", "https://server.org/a", form: { "foo" => "bar" })
64
+ # resp1, resp2 = session.request(["POST", "https://server.org/a", form: { "foo" => "bar" }], ["GET", "https://server.org/b"])
65
+ # resp1, resp2 = session.request("GET", ["https://server.org/a", "https://server.org/b"], headers: { "x-api-token" => "TOKEN" })
66
+ #
33
67
  def request(*args, **options)
34
68
  raise ArgumentError, "must perform at least one request" if args.empty?
35
69
 
@@ -40,10 +74,17 @@ module HTTPX
40
74
  responses
41
75
  end
42
76
 
77
+ # returns a HTTP::Request instance built from the HTTP +verb+, the request +uri+, and
78
+ # the optional set of request-specific +options+. This request **must** be sent through
79
+ # the same session it was built from.
80
+ #
81
+ # req = session.build_request("GET", "https://server.com")
82
+ # resp = session.request(req)
43
83
  def build_request(verb, uri, options = EMPTY_HASH)
44
84
  rklass = @options.request_class
45
85
  options = @options.merge(options) unless options.is_a?(Options)
46
- request = rklass.new(verb, uri, options.merge(persistent: @persistent))
86
+ request = rklass.new(verb, uri, options)
87
+ request.persistent = @persistent
47
88
  request.on(:response, &method(:on_response).curry(2)[request])
48
89
  request.on(:promise, &method(:on_promise))
49
90
 
@@ -76,23 +117,29 @@ module HTTPX
76
117
 
77
118
  private
78
119
 
120
+ # returns the HTTPX::Pool object which manages the networking required to
121
+ # perform requests.
79
122
  def pool
80
123
  Thread.current[:httpx_connection_pool] ||= Pool.new
81
124
  end
82
125
 
126
+ # callback executed when a response for a given request has been received.
83
127
  def on_response(request, response)
84
128
  @responses[request] = response
85
129
  end
86
130
 
131
+ # callback executed when an HTTP/2 promise frame has been received.
87
132
  def on_promise(_, stream)
88
133
  log(level: 2) { "#{stream.id}: refusing stream!" }
89
134
  stream.refuse
90
135
  end
91
136
 
137
+ # returns the corresponding HTTP::Response to the given +request+ if it has been received.
92
138
  def fetch_response(request, _, _)
93
139
  @responses.delete(request)
94
140
  end
95
141
 
142
+ # returns the HTTPX::Connection through which the +request+ should be sent through.
96
143
  def find_connection(request, connections, options)
97
144
  uri = request.uri
98
145
 
@@ -104,6 +151,8 @@ module HTTPX
104
151
  connection
105
152
  end
106
153
 
154
+ # sets the callbacks on the +connection+ required to process certain specific
155
+ # connection lifecycle events which deal with request rerouting.
107
156
  def set_connection_callbacks(connection, connections, options)
108
157
  connection.only(:misdirected) do |misdirected_request|
109
158
  other_connection = connection.create_idle(ssl: { alpn_protocols: %w[http/1.1] })
@@ -131,6 +180,7 @@ module HTTPX
131
180
  end
132
181
  end
133
182
 
183
+ # returns an HTTPX::Connection for the negotiated Alternative Service (or none).
134
184
  def build_altsvc_connection(existing_connection, connections, alt_origin, origin, alt_params, options)
135
185
  # do not allow security downgrades on altsvc negotiation
136
186
  return if existing_connection.origin.scheme == "https" && alt_origin.scheme != "https"
@@ -166,6 +216,7 @@ module HTTPX
166
216
  nil
167
217
  end
168
218
 
219
+ # returns a set of HTTPX::Request objects built from the given +args+ and +options+.
169
220
  def build_requests(*args, options)
170
221
  request_options = @options.merge(options)
171
222
 
@@ -189,6 +240,7 @@ module HTTPX
189
240
  requests
190
241
  end
191
242
 
243
+ # returns a new HTTPX::Connection object for the given +uri+ and set of +options+.
192
244
  def build_connection(uri, options)
193
245
  type = options.transport || begin
194
246
  case uri.scheme
@@ -208,7 +260,9 @@ module HTTPX
208
260
  connection.on(:open) do
209
261
  emit(:connection_opened, connection.origin, connection.io.socket)
210
262
  # only run close callback if it opened
211
- connection.on(:close) { emit(:connection_closed, connection.origin, connection.io.socket) }
263
+ end
264
+ connection.on(:close) do
265
+ emit(:connection_closed, connection.origin, connection.io.socket) if connection.used?
212
266
  end
213
267
  catch(:coalesced) do
214
268
  pool.init_connection(connection, options)
@@ -216,11 +270,13 @@ module HTTPX
216
270
  end
217
271
  end
218
272
 
273
+ # sends an array of HTTPX::Request +requests+, returns the respective array of HTTPX::Response objects.
219
274
  def send_requests(*requests)
220
275
  connections = _send_requests(requests)
221
276
  receive_requests(requests, connections)
222
277
  end
223
278
 
279
+ # sends an array of HTTPX::Request objects
224
280
  def _send_requests(requests)
225
281
  connections = []
226
282
 
@@ -237,6 +293,7 @@ module HTTPX
237
293
  connections
238
294
  end
239
295
 
296
+ # returns the array of HTTPX::Response objects corresponding to the array of HTTPX::Request +requests+.
240
297
  def receive_requests(requests, connections)
241
298
  # @type var responses: Array[response]
242
299
  responses = []
@@ -290,6 +347,11 @@ module HTTPX
290
347
  klass.instance_variable_set(:@callbacks, @callbacks.dup)
291
348
  end
292
349
 
350
+ # returns a new HTTPX::Session instance, with the plugin pointed by +pl+ loaded.
351
+ #
352
+ # session_with_retries = session.plugin(:retries)
353
+ # session_with_custom = session.plugin(CustomPlugin)
354
+ #
293
355
  def plugin(pl, options = nil, &block)
294
356
  # raise Error, "Cannot add a plugin to a frozen config" if frozen?
295
357
  pl = Plugins.load_plugin(pl) if pl.is_a?(Symbol)
data/lib/httpx/timers.rb CHANGED
@@ -6,20 +6,27 @@ module HTTPX
6
6
  @intervals = []
7
7
  end
8
8
 
9
- def after(interval_in_secs, &blk)
9
+ def after(interval_in_secs, cb = nil, &blk)
10
10
  return unless interval_in_secs
11
11
 
12
+ callback = cb || blk
13
+
12
14
  # I'm assuming here that most requests will have the same
13
15
  # request timeout, as in most cases they share common set of
14
16
  # options. A user setting different request timeouts for 100s of
15
17
  # requests will already have a hard time dealing with that.
16
- unless (interval = @intervals.find { |t| t == interval_in_secs })
18
+ unless (interval = @intervals.find { |t| t.interval == interval_in_secs })
17
19
  interval = Interval.new(interval_in_secs)
20
+ interval.on_empty { @intervals.delete(interval) }
18
21
  @intervals << interval
19
22
  @intervals.sort!
20
23
  end
21
24
 
22
- interval << blk
25
+ interval << callback
26
+
27
+ @next_interval_at = nil
28
+
29
+ interval
23
30
  end
24
31
 
25
32
  def wait_interval
@@ -41,11 +48,6 @@ module HTTPX
41
48
  @next_interval_at = nil if @intervals.empty?
42
49
  end
43
50
 
44
- def cancel
45
- @next_interval_at = nil
46
- @intervals.clear
47
- end
48
-
49
51
  class Interval
50
52
  include Comparable
51
53
 
@@ -54,6 +56,11 @@ module HTTPX
54
56
  def initialize(interval)
55
57
  @interval = interval
56
58
  @callbacks = []
59
+ @on_empty = nil
60
+ end
61
+
62
+ def on_empty(&blk)
63
+ @on_empty = blk
57
64
  end
58
65
 
59
66
  def <=>(other)
@@ -74,6 +81,26 @@ module HTTPX
74
81
  @callbacks << callback
75
82
  end
76
83
 
84
+ if RUBY_ENGINE == "jruby" && JRUBY_VERSION < "9.4.5.0"
85
+ # https://github.com/jruby/jruby/issues/7976
86
+ def delete(callback)
87
+ @callbacks.delete(callback)
88
+ end
89
+ else
90
+ def delete(callback)
91
+ @callbacks.delete(callback)
92
+ @on_empty.call if @callbacks.empty?
93
+ end
94
+ end
95
+
96
+ def no_callbacks?
97
+ @callbacks.empty?
98
+ end
99
+
100
+ def elapsed?
101
+ @interval <= 0
102
+ end
103
+
77
104
  def elapse(elapsed)
78
105
  @interval -= elapsed
79
106
 
@@ -6,7 +6,7 @@ module HTTPX::Transcoder
6
6
  module JSON
7
7
  module_function
8
8
 
9
- JSON_REGEX = %r{\bapplication/(?:vnd\.api\+)?json\b}i.freeze
9
+ JSON_REGEX = %r{\bapplication/(?:vnd\.api\+|hal\+)?json\b}i.freeze
10
10
 
11
11
  class Encoder
12
12
  extend Forwardable
@@ -0,0 +1,19 @@
1
+ module HTTPX
2
+ module Transcoder
3
+ class Inflater
4
+ def initialize(bytesize)
5
+ @bytesize = bytesize
6
+ end
7
+
8
+ def call(chunk)
9
+ buffer = @inflater.inflate(chunk)
10
+ @bytesize -= chunk.bytesize
11
+ if @bytesize <= 0
12
+ buffer << @inflater.finish
13
+ @inflater.close
14
+ end
15
+ buffer
16
+ end
17
+ end
18
+ end
19
+ 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.0.2"
4
+ VERSION = "1.1.1"
5
5
  end
@@ -53,19 +53,19 @@ module HTTPX
53
53
 
54
54
  def ping: () -> void
55
55
 
56
- def timeout: () -> Numeric
56
+ def timeout: () -> Numeric?
57
57
 
58
58
  private
59
59
 
60
60
  def initialize: (Buffer, options) -> untyped
61
61
 
62
- def manage_connection: (Response) -> void
62
+ def manage_connection: (Request request, Response response) -> void
63
63
 
64
64
  def disable: () -> void
65
65
 
66
66
  def disable_pipelining: () -> void
67
67
 
68
- def set_protocol_headers: (Request) -> _Each[[String, String]]
68
+ def set_protocol_headers: (Request request) -> _Each[[String, String]]
69
69
 
70
70
  def handle: (Request request) -> void
71
71
 
@@ -38,7 +38,7 @@ module HTTPX
38
38
 
39
39
  alias reset init_connection
40
40
 
41
- def timeout: () -> Numeric
41
+ def timeout: () -> Numeric?
42
42
 
43
43
  private
44
44
 
data/sig/connection.rbs CHANGED
@@ -40,6 +40,7 @@ module HTTPX
40
40
  @parser: HTTP1 | HTTP2 | _Parser
41
41
  @connected_at: Float
42
42
  @response_received_at: Float
43
+ @intervals: Array[Timers::Interval]
43
44
 
44
45
  def addresses: () -> Array[ipaddr]?
45
46
 
@@ -89,7 +90,7 @@ module HTTPX
89
90
 
90
91
  def open?: () -> bool
91
92
 
92
- def raise_timeout_error: (Numeric interval) -> void
93
+ def handle_socket_timeout: (Numeric interval) -> void
93
94
 
94
95
  private
95
96
 
@@ -129,6 +130,8 @@ module HTTPX
129
130
 
130
131
  def read_timeout_callback: (Request request, Numeric read_timeout, ?singleton(RequestTimeoutError) error_type) -> void
131
132
 
133
+ def set_request_timeout: (Request request, Numeric timeout, Symbol start_event, Symbol | Array[Symbol] finish_events) { () -> void } -> void
134
+
132
135
  def self.parser_type: (String protocol) -> (singleton(HTTP1) | singleton(HTTP2))
133
136
  end
134
137
  end
data/sig/io/tcp.rbs CHANGED
@@ -2,7 +2,7 @@ module HTTPX
2
2
  class TCP
3
3
  include Loggable
4
4
 
5
- attr_reader ip: IPAddr?
5
+ attr_reader ip: ipaddr?
6
6
 
7
7
  attr_reader port: Integer
8
8
 
data/sig/options.rbs CHANGED
@@ -12,7 +12,7 @@ module HTTPX
12
12
  DEFAULT_OPTIONS: Hash[Symbol, untyped]
13
13
 
14
14
  type timeout_type = :connect_timeout | :settings_timeout | :operation_timeout | :keep_alive_timeout | :read_timeout | :write_timeout | :request_timeout
15
- type timeout = Hash[timeout_type, Numeric]
15
+ type timeout = Hash[timeout_type, Numeric?]
16
16
 
17
17
  def self.new: (?options) -> instance
18
18
 
@@ -32,7 +32,7 @@ module HTTPX
32
32
  attr_reader max_concurrent_requests: Integer?
33
33
 
34
34
  # max_requests
35
- attr_reader max_requests: Integer?
35
+ attr_reader max_requests: Numeric?
36
36
 
37
37
  # window_size
38
38
  attr_reader window_size: Integer
data/sig/pool.rbs CHANGED
@@ -45,7 +45,7 @@ module HTTPX
45
45
 
46
46
  def coalesce_connections: (Connection coalescable, Connection coalescing) -> void
47
47
 
48
- def next_timeout: () -> (Integer | Float | nil)
48
+ def next_timeout: () -> Numeric?
49
49
 
50
50
  def find_resolver_for: (Connection) { (Resolver::Resolver resolver) -> void } -> resolver_manager
51
51
  end
data/sig/request/body.rbs CHANGED
@@ -1,7 +1,5 @@
1
1
  module HTTPX
2
2
  class Request::Body
3
- attr_reader threshold_size: Integer?
4
-
5
3
  @headers: Headers
6
4
  @body: body_encoder?
7
5
  @unbounded_body: bool