httpx 1.4.2 → 1.4.3

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: 3be0d06eb9b669cc4a1ba0818d39c76bdd4cdf41e496cb82efbb83b7c6c47241
4
- data.tar.gz: bf778691f222095e080c83b16f71b3d9c8065db9f98f35498eeea317f013a686
3
+ metadata.gz: 36f5b3d4da61a1a6c86602205a6eda217f51b40411865589587a09553eb263cb
4
+ data.tar.gz: 9b705a6b8bc7ebf1ec2e308ae6b49bfcc3ede818bbca0dcf4b2fb82dde1cace6
5
5
  SHA512:
6
- metadata.gz: 26045db79f85f7a136771bdca1852d93be6ad9c84a4285d26c7a97543e0209588fdc423276ea593c9ad26db960ec81a444326a01223e24a932cca8318f08e4ab
7
- data.tar.gz: c280576f30f55590336c70c93ea63a4be1e9a8ac238318417b9c4227889518c04f2545d70c0dce74c4026465ad9a7e68f0a05ac6d9728a1035e8ba5c094036fc
6
+ metadata.gz: 72759cee17931e45580673c119fffd7339afdfe149f6a4a14afa410d11c47b0d84146a70660b5ca8ff63b1d0b6c1d16a85008416348cd48cddd3f9a9c94f3c10
7
+ data.tar.gz: 1233281adc13e03e5b754ef6d5d830e84335f5f8b3cc90dea33e27c9f5751f2e3f7d20e1d6064b9273678612a3e4505d8d54b3038b85855bc25a72c6d73d914c
@@ -0,0 +1,11 @@
1
+ # 1.4.3
2
+
3
+ ## Bugfixes
4
+
5
+ * `webmock` adapter: reassign headers to signature after callbacks are called (these may change the headers before virtual send).
6
+ * do not close request (and its body) right after sending, instead only on response close
7
+ * prevents retries from failing under the `:retries` plugin
8
+ * fixes issue when using `faraday-multipart` request bodies
9
+ * retry request with HTTP/1 when receiving an HTTP/2 GOAWAY frame with `HTTP_1_1_REQUIRED` error code.
10
+ * fix wrong method call on HTTP/2 PING frame with unrecognized code.
11
+ * fix EOFError issues on connection termination for long running connections which may have already been terminated by peer and were wrongly trying to complete the HTTP/2 termination handshake.
@@ -122,6 +122,8 @@ module WebMock
122
122
  request.transition(:done)
123
123
  request.response = response
124
124
  request.emit(:response, response)
125
+ request_signature.headers = request.headers.to_h
126
+
125
127
  response << mock_response.body.dup unless response.is_a?(HTTPX::ErrorResponse)
126
128
  elsif WebMock.net_connect_allowed?(request_signature.uri)
127
129
  if WebMock::CallbackRegistry.any_callbacks?
@@ -16,6 +16,12 @@ module HTTPX
16
16
  end
17
17
  end
18
18
 
19
+ class PingError < Error
20
+ def initialize
21
+ super(0, :ping_error)
22
+ end
23
+ end
24
+
19
25
  class GoawayError < Error
20
26
  def initialize
21
27
  super(0, :no_error)
@@ -311,17 +317,20 @@ module HTTPX
311
317
  @streams.delete(request)
312
318
 
313
319
  if error
314
- ex = Error.new(stream.id, error)
315
- ex.set_backtrace(caller)
316
- response = ErrorResponse.new(request, ex)
317
- request.response = response
318
- emit(:response, request, response)
320
+ case error
321
+ when :http_1_1_required
322
+ emit(:error, request, error)
323
+ else
324
+ ex = Error.new(stream.id, error)
325
+ ex.set_backtrace(caller)
326
+ response = ErrorResponse.new(request, ex)
327
+ request.response = response
328
+ emit(:response, request, response)
329
+ end
319
330
  else
320
331
  response = request.response
321
332
  if response && response.is_a?(Response) && response.status == 421
322
- ex = MisdirectedRequestError.new(response)
323
- ex.set_backtrace(caller)
324
- emit(:error, request, ex)
333
+ emit(:error, request, :http_1_1_required)
325
334
  else
326
335
  emit(:response, request, response)
327
336
  end
@@ -352,7 +361,12 @@ module HTTPX
352
361
  is_connection_closed = @connection.state == :closed
353
362
  if error
354
363
  @buffer.clear if is_connection_closed
355
- if error == :no_error
364
+ case error
365
+ when :http_1_1_required
366
+ while (request = @pending.shift)
367
+ emit(:error, request, error)
368
+ end
369
+ when :no_error
356
370
  ex = GoawayError.new
357
371
  @pending.unshift(*@streams.keys)
358
372
  @drains.clear
@@ -360,8 +374,11 @@ module HTTPX
360
374
  else
361
375
  ex = Error.new(0, error)
362
376
  end
363
- ex.set_backtrace(caller)
364
- handle_error(ex)
377
+
378
+ if ex
379
+ ex.set_backtrace(caller)
380
+ handle_error(ex)
381
+ end
365
382
  end
366
383
  return unless is_connection_closed && @streams.empty?
367
384
 
@@ -403,11 +420,9 @@ module HTTPX
403
420
  end
404
421
 
405
422
  def on_pong(ping)
406
- if @pings.delete(ping.to_s)
407
- emit(:pong)
408
- else
409
- close(:protocol_error, "ping payload did not match")
410
- end
423
+ raise PingError unless @pings.delete(ping.to_s)
424
+
425
+ emit(:pong)
411
426
  end
412
427
  end
413
428
  end
@@ -423,6 +423,8 @@ module HTTPX
423
423
  siz = @io.read(@window_size, @read_buffer)
424
424
  log(level: 3, color: :cyan) { "IO READ: #{siz} bytes... (wsize: #{@window_size}, rbuffer: #{@read_buffer.bytesize})" }
425
425
  unless siz
426
+ @write_buffer.clear
427
+
426
428
  ex = EOFError.new("descriptor closed")
427
429
  ex.set_backtrace(caller)
428
430
  on_error(ex)
@@ -610,9 +612,9 @@ module HTTPX
610
612
  parser.on(:timeout) do |tout|
611
613
  @timeout = tout
612
614
  end
613
- parser.on(:error) do |request, ex|
614
- case ex
615
- when MisdirectedRequestError
615
+ parser.on(:error) do |request, error|
616
+ case error
617
+ when :http_1_1_required
616
618
  current_session = @current_session
617
619
  current_selector = @current_selector
618
620
  parser.close
@@ -628,7 +630,7 @@ module HTTPX
628
630
  next unless request.active_timeouts.empty?
629
631
  end
630
632
 
631
- response = ErrorResponse.new(request, ex)
633
+ response = ErrorResponse.new(request, error)
632
634
  request.response = response
633
635
  request.emit(:response, response)
634
636
  end
data/lib/httpx/errors.rb CHANGED
@@ -115,8 +115,4 @@ module HTTPX
115
115
  @response.status
116
116
  end
117
117
  end
118
-
119
- # error raised when a request was sent a server which can't reproduce a response, and
120
- # has therefore returned an HTTP response using the 421 status code.
121
- class MisdirectedRequestError < HTTPError; end
122
118
  end
@@ -15,10 +15,10 @@ module HTTPX
15
15
 
16
16
  USE_DEBUG_LOG = ENV.key?("HTTPX_DEBUG")
17
17
 
18
- def log(level: @options.debug_level, color: nil, &msg)
19
- return unless @options.debug_level >= level
18
+ def log(level: @options.debug_level, color: nil, debug_level: @options.debug_level, debug: @options.debug, &msg)
19
+ return unless debug_level >= level
20
20
 
21
- debug_stream = @options.debug || ($stderr if USE_DEBUG_LOG)
21
+ debug_stream = debug || ($stderr if USE_DEBUG_LOG)
22
22
 
23
23
  return unless debug_stream
24
24
 
@@ -34,8 +34,8 @@ module HTTPX
34
34
  debug_stream << message
35
35
  end
36
36
 
37
- def log_exception(ex, level: @options.debug_level, color: nil)
38
- log(level: level, color: color) { ex.full_message }
37
+ def log_exception(ex, level: @options.debug_level, color: nil, debug_level: @options.debug_level, debug: @options.debug)
38
+ log(level: level, color: color, debug_level: debug_level, debug: debug) { ex.full_message }
39
39
  end
40
40
  end
41
41
  end
@@ -13,6 +13,12 @@ module HTTPX
13
13
  # by the end user in $http_init_time, different diff metrics can be shown. The "point of time" is calculated
14
14
  # using the monotonic clock.
15
15
  module InternalTelemetry
16
+ DEBUG_LEVEL = 3
17
+
18
+ def self.extra_options(options)
19
+ options.merge(debug_level: 3)
20
+ end
21
+
16
22
  module TrackTimeMethods
17
23
  private
18
24
 
@@ -28,7 +34,19 @@ module HTTPX
28
34
  after_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
29
35
  # $http_init_time = after_time
30
36
  elapsed = after_time - prev_time
31
- warn(+"\e[31m" << "[ELAPSED TIME]: #{label}: #{elapsed} (ms)" << "\e[0m")
37
+ # klass = self.class
38
+
39
+ # until (class_name = klass.name)
40
+ # klass = klass.superclass
41
+ # end
42
+ log(
43
+ level: DEBUG_LEVEL,
44
+ color: :red,
45
+ debug_level: @options ? @options.debug_level : DEBUG_LEVEL,
46
+ debug: nil
47
+ ) do
48
+ "[ELAPSED TIME]: #{label}: #{elapsed} (ms)" << "\e[0m"
49
+ end
32
50
  end
33
51
  end
34
52
 
@@ -88,6 +106,7 @@ module HTTPX
88
106
 
89
107
  module RequestMethods
90
108
  def self.included(klass)
109
+ klass.prepend Loggable
91
110
  klass.prepend TrackTimeMethods
92
111
  super
93
112
  end
@@ -114,6 +133,7 @@ module HTTPX
114
133
 
115
134
  module PoolMethods
116
135
  def self.included(klass)
136
+ klass.prepend Loggable
117
137
  klass.prepend TrackTimeMethods
118
138
  super
119
139
  end
@@ -167,7 +167,7 @@ module HTTPX
167
167
  unless response.headers.key?("accept-ranges") &&
168
168
  response.headers["accept-ranges"] == "bytes" && # there's nothing else supported though...
169
169
  (original_body = response.body)
170
- response.close if response.respond_to?(:close)
170
+ response.body.close
171
171
  return
172
172
  end
173
173
 
data/lib/httpx/request.rb CHANGED
@@ -50,6 +50,9 @@ module HTTPX
50
50
  # will be +true+ when request body has been completely flushed.
51
51
  def_delegator :@body, :empty?
52
52
 
53
+ # closes the body
54
+ def_delegator :@body, :close
55
+
53
56
  # initializes the instance with the given +verb+ (an upppercase String, ex. 'GEt'),
54
57
  # an absolute or relative +uri+ (either as String or URI::HTTP object), the
55
58
  # request +options+ (instance of HTTPX::Options) and an optional Hash of +params+.
@@ -273,7 +276,6 @@ module HTTPX
273
276
  when :done
274
277
  return if @state == :expect
275
278
 
276
- @body.close
277
279
  end
278
280
  @state = nextstate
279
281
  emit(@state, self)
@@ -52,9 +52,6 @@ module HTTPX
52
52
  # copies the response body to a different location.
53
53
  def_delegator :@body, :copy_to
54
54
 
55
- # closes the body.
56
- def_delegator :@body, :close
57
-
58
55
  # the corresponding request uri.
59
56
  def_delegator :@request, :uri
60
57
 
@@ -74,6 +71,12 @@ module HTTPX
74
71
  @content_type = nil
75
72
  end
76
73
 
74
+ # closes the respective +@request+ and +@body+.
75
+ def close
76
+ @request.close
77
+ @body.close
78
+ end
79
+
77
80
  # merges headers defined in +h+ into the response headers.
78
81
  def merge_headers(h)
79
82
  @headers = @headers.merge(h)
@@ -264,7 +267,7 @@ module HTTPX
264
267
 
265
268
  # closes the error resources.
266
269
  def close
267
- @response.close if @response && @response.respond_to?(:close)
270
+ @response.close if @response
268
271
  end
269
272
 
270
273
  # always true for error responses.
@@ -279,6 +282,8 @@ module HTTPX
279
282
 
280
283
  # buffers lost chunks to error response
281
284
  def <<(data)
285
+ return unless @response
286
+
282
287
  @response << data
283
288
  end
284
289
  end
@@ -11,6 +11,7 @@ module HTTPX
11
11
  @buffer = "".b
12
12
 
13
13
  @form = form
14
+ @bytesize = 0
14
15
  @parts = to_parts(form)
15
16
  end
16
17
 
@@ -42,6 +43,7 @@ module HTTPX
42
43
  aux << [key, val]
43
44
  end
44
45
  @form = form
46
+ @bytesize = 0
45
47
  @parts = to_parts(form)
46
48
  @part_index = 0
47
49
  end
@@ -49,7 +51,6 @@ module HTTPX
49
51
  private
50
52
 
51
53
  def to_parts(form)
52
- @bytesize = 0
53
54
  params = form.each_with_object([]) do |(key, val), aux|
54
55
  Transcoder.normalize_keys(key, val, MULTIPART_VALUE_COND) do |k, v|
55
56
  next if v.nil?
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.2"
4
+ VERSION = "1.4.3"
5
5
  end
@@ -8,6 +8,7 @@ module HTTPX
8
8
  attr_reader streams: Hash[Request, ::HTTP2::Stream]
9
9
  attr_reader pending: Array[Request]
10
10
 
11
+ @connection: HTTP2::Client
11
12
  @options: Options
12
13
  @settings: Hash[Symbol, Integer | bool]
13
14
  @max_concurrent_requests: Integer
@@ -95,5 +96,8 @@ module HTTPX
95
96
 
96
97
  class GoawayError < Error
97
98
  end
99
+
100
+ class PingError < Error
101
+ end
98
102
  end
99
103
  end
data/sig/errors.rbs CHANGED
@@ -67,7 +67,4 @@ module HTTPX
67
67
 
68
68
  def initialize: (Connection connection, String hostname, ?String message) -> untyped
69
69
  end
70
-
71
- class MisdirectedRequestError < HTTPError
72
- end
73
70
  end
data/sig/loggable.rbs CHANGED
@@ -8,8 +8,8 @@ module HTTPX
8
8
 
9
9
  COLORS: Hash[Symbol, Integer]
10
10
 
11
- def log: (?level: Integer?, ?color: Symbol?) { () -> String } -> void
11
+ def log: (?level: Integer?, ?color: Symbol?, ?debug_level: Integer, ?debug: _IOLogger?) { () -> String } -> void
12
12
 
13
- def log_exception: (Exception error, ?level: Integer, ?color: Symbol) -> void
13
+ def log_exception: (Exception error, ?level: Integer, ?color: Symbol, ?debug_level: Integer, ?debug: _IOLogger?) -> void
14
14
  end
15
15
  end
@@ -0,0 +1,18 @@
1
+ module HTTPX
2
+ module Plugins
3
+ module Query
4
+ def self.subplugins: () -> Hash[Symbol, Module]
5
+
6
+ module InstanceMethods
7
+ def query: (uri | [uri], **untyped) -> response
8
+ | (_Each[uri | [uri, request_params]], **untyped) -> Array[response]
9
+ end
10
+
11
+ module QueryRetries
12
+ module InstanceMethods
13
+ end
14
+ end
15
+ end
16
+ type sessionQuery = Session & Query::InstanceMethods
17
+ end
18
+ end
data/sig/pool.rbs CHANGED
@@ -5,6 +5,8 @@ module HTTPX
5
5
  }
6
6
 
7
7
  class Pool
8
+ POOL_TIMEOUT: Integer
9
+
8
10
  type resolver_manager = Resolver::Multi | Resolver::System
9
11
 
10
12
  @max_connections_per_origin: Integer
data/sig/request.rbs CHANGED
@@ -28,6 +28,10 @@ module HTTPX
28
28
 
29
29
  def initialize: (Symbol | String verb, generic_uri uri, Options options, ?request_params params) -> untyped
30
30
 
31
+ def empty?: () -> bool
32
+
33
+ def close: () -> void
34
+
31
35
  def interests: () -> (:r | :w)
32
36
 
33
37
  def merge_headers: (_Each[[String, headers_value]]) -> void
data/sig/response.rbs CHANGED
@@ -1,5 +1,7 @@
1
1
  module HTTPX
2
2
  interface _Response
3
+ def <<: (String data) -> void
4
+
3
5
  def finished?: () -> bool
4
6
 
5
7
  def raise_for_status: () -> self
@@ -23,6 +25,7 @@ module HTTPX
23
25
  @options: Options
24
26
  @request: Request
25
27
  @content_type: ContentType
28
+ @finished: bool
26
29
 
27
30
  def copy_to: (_ToPath | _Writer destination) -> void
28
31
 
@@ -38,9 +41,11 @@ module HTTPX
38
41
 
39
42
  def content_type: () -> ContentType
40
43
 
44
+ def finish!: () -> void
45
+
41
46
  def complete?: () -> bool
42
47
 
43
- def json: (?json_options opts) -> untyped
48
+ def json: (?JSON::options opts) -> untyped
44
49
 
45
50
  def form: () -> Hash[String, untyped]
46
51
 
@@ -77,9 +82,9 @@ module HTTPX
77
82
  @options: Options
78
83
  @error: Exception
79
84
 
80
- attr_reader request: Request
85
+ %a{pure} attr_reader request: Request
81
86
 
82
- attr_reader response: Response?
87
+ %a{pure} attr_reader response: Response?
83
88
 
84
89
  def status: () -> (Integer | _ToS)
85
90
 
@@ -5,7 +5,7 @@ module HTTPX::Transcoder
5
5
  def self?.encode: (_ToJson json) -> Encoder
6
6
  def self?.decode: (HTTPX::Response response) -> _Decoder
7
7
 
8
- def self?.json_load: (string source, ?json_options) -> untyped
8
+ def self?.json_load: (string source, ?JSON::options) -> untyped
9
9
  def self?.json_dump: (_ToJson obj, *untyped) -> String
10
10
 
11
11
  class Encoder
@@ -24,7 +24,7 @@ module HTTPX
24
24
  @form: Enumerable[[Symbol | string, Object & multipart_nested_value]]
25
25
  @parts: Array[Object & _Reader]
26
26
 
27
- def bytesize: () -> Integer
27
+ attr_reader bytesize: Integer
28
28
 
29
29
  def content_type: () -> String
30
30
 
@@ -5,7 +5,6 @@ module HTTPX
5
5
 
6
6
  @body: BodyReader
7
7
  @buffer: Response::Buffer?
8
- @body: BodyReader
9
8
  @closed: bool
10
9
 
11
10
  attr_reader content_type: String
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.2
4
+ version: 1.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-03-05 00:00:00.000000000 Z
10
+ date: 2025-03-25 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: http-2
@@ -152,6 +151,7 @@ extra_rdoc_files:
152
151
  - doc/release_notes/1_4_0.md
153
152
  - doc/release_notes/1_4_1.md
154
153
  - doc/release_notes/1_4_2.md
154
+ - doc/release_notes/1_4_3.md
155
155
  files:
156
156
  - LICENSE.txt
157
157
  - README.md
@@ -275,6 +275,7 @@ files:
275
275
  - doc/release_notes/1_4_0.md
276
276
  - doc/release_notes/1_4_1.md
277
277
  - doc/release_notes/1_4_2.md
278
+ - doc/release_notes/1_4_3.md
278
279
  - lib/httpx.rb
279
280
  - lib/httpx/adapters/datadog.rb
280
281
  - lib/httpx/adapters/faraday.rb
@@ -435,6 +436,7 @@ files:
435
436
  - sig/plugins/proxy/socks5.rbs
436
437
  - sig/plugins/proxy/ssh.rbs
437
438
  - sig/plugins/push_promise.rbs
439
+ - sig/plugins/query.rbs
438
440
  - sig/plugins/rate_limiter.rbs
439
441
  - sig/plugins/response_cache.rbs
440
442
  - sig/plugins/retries.rbs
@@ -480,7 +482,6 @@ metadata:
480
482
  source_code_uri: https://gitlab.com/os85/httpx
481
483
  homepage_uri: https://honeyryderchuck.gitlab.io/httpx/
482
484
  rubygems_mfa_required: 'true'
483
- post_install_message:
484
485
  rdoc_options: []
485
486
  require_paths:
486
487
  - lib
@@ -495,8 +496,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
495
496
  - !ruby/object:Gem::Version
496
497
  version: '0'
497
498
  requirements: []
498
- rubygems_version: 3.5.22
499
- signing_key:
499
+ rubygems_version: 3.6.2
500
500
  specification_version: 4
501
501
  summary: HTTPX, to the future, and beyond
502
502
  test_files: []