httpx 1.4.3 → 1.4.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: 36f5b3d4da61a1a6c86602205a6eda217f51b40411865589587a09553eb263cb
4
- data.tar.gz: 9b705a6b8bc7ebf1ec2e308ae6b49bfcc3ede818bbca0dcf4b2fb82dde1cace6
3
+ metadata.gz: 4aa5b1cfd43d05f50fc7246219d6a90cb5591e11c8bfeee1f1cf62ffa91993fc
4
+ data.tar.gz: 58f96325ac13b8caddb708464a75ee6dafcfe7b8284f0825803ac3d0c4d8ccc1
5
5
  SHA512:
6
- metadata.gz: 72759cee17931e45580673c119fffd7339afdfe149f6a4a14afa410d11c47b0d84146a70660b5ca8ff63b1d0b6c1d16a85008416348cd48cddd3f9a9c94f3c10
7
- data.tar.gz: 1233281adc13e03e5b754ef6d5d830e84335f5f8b3cc90dea33e27c9f5751f2e3f7d20e1d6064b9273678612a3e4505d8d54b3038b85855bc25a72c6d73d914c
6
+ metadata.gz: 43a032f78a86df04428af78f32077483b8c01500ebb001ec97100ac3923b4915a28b299cadb8b47fab8fa875c3897732c21eec63769ad98dfd98b901f006b051
7
+ data.tar.gz: dfff14a83428e2472ff53a50cadf5dd7a270f09523eca4c5aa66e7a3093ca8bd096c9c3d12070ed6a54ef1ddaec4966efd456653e666429f0ce47f04fe68e35a
@@ -0,0 +1,14 @@
1
+ # 1.4.4
2
+
3
+ ## Improvements
4
+
5
+ * `:stream` plugin: response will now be partially buffered in order to i.e. inspect response status or headers on the response body without buffering the full response
6
+ * this fixes an issue in the `down` gem integration when used with the `:max_size` option.
7
+ * do not unnecessarily probe for connection liveness if no more requests are inflight, including failed ones.
8
+ * when using persistent connections, do not probe for liveness right after reconnecting after a keep alive timeout.
9
+
10
+ ## Bugfixes
11
+
12
+ * `:persistent` plugin: do not exhaust retry attempts when probing for (and failing) connection liveness.
13
+ * since the introduction of per-session connection pools, and consequentially due to the possibility of multiple inactive connections for the same origin being in the pool, which may have been terminated by the peer server, requests would fail before being able to establish a new connection.
14
+ * prevent retrying to connect the TCP socket object when an SSLSocket object is already in place and connecting.
@@ -58,6 +58,8 @@ module WebMock
58
58
  super
59
59
 
60
60
  connection.once(:unmock_connection) do
61
+ next unless connection.current_session == self
62
+
61
63
  unless connection.addresses
62
64
  # reset Happy Eyeballs, fail early
63
65
  connection.sibling = nil
@@ -296,6 +296,7 @@ module HTTPX
296
296
  @pending << request
297
297
  transition(:active) if @state == :inactive
298
298
  parser.ping
299
+ request.ping!
299
300
  return
300
301
  end
301
302
 
@@ -630,6 +631,7 @@ module HTTPX
630
631
  next unless request.active_timeouts.empty?
631
632
  end
632
633
 
634
+ @inflight -= 1
633
635
  response = ErrorResponse.new(request, error)
634
636
  request.response = response
635
637
  request.emit(:response, response)
@@ -670,7 +672,7 @@ module HTTPX
670
672
  when :idle
671
673
  @timeout = @current_timeout = @options.timeout[:connect_timeout]
672
674
 
673
- @connected_at = nil
675
+ @connected_at = @response_received_at = nil
674
676
  when :open
675
677
  return if @state == :closed
676
678
 
@@ -843,6 +845,7 @@ module HTTPX
843
845
 
844
846
  return unless request
845
847
 
848
+ @inflight -= 1
846
849
  response = ErrorResponse.new(request, error)
847
850
  request.response = response
848
851
  request.emit(:response, response)
data/lib/httpx/io/ssl.rb CHANGED
@@ -92,9 +92,12 @@ module HTTPX
92
92
  end
93
93
 
94
94
  def connect
95
- super
96
- return if @state == :negotiated ||
97
- @state != :connected
95
+ return if @state == :negotiated
96
+
97
+ unless @state == :connected
98
+ super
99
+ return unless @state == :connected
100
+ end
98
101
 
99
102
  unless @io.is_a?(OpenSSL::SSL::SSLSocket)
100
103
  if (hostname_is_ip = (@ip == @sni_hostname))
@@ -110,7 +110,7 @@ module HTTPX
110
110
  )
111
111
  __try_partial_retry(request, response)
112
112
  log { "failed to get response, #{request.retries} tries to go..." }
113
- request.retries -= 1
113
+ request.retries -= 1 unless request.ping? # do not exhaust retries on connection liveness probes
114
114
  request.transition(:idle)
115
115
 
116
116
  retry_after = options.retry_after
@@ -4,27 +4,39 @@ module HTTPX
4
4
  class StreamResponse
5
5
  def initialize(request, session)
6
6
  @request = request
7
+ @options = @request.options
7
8
  @session = session
8
- @response = nil
9
+ @response_enum = nil
10
+ @buffered_chunks = []
9
11
  end
10
12
 
11
13
  def each(&block)
12
14
  return enum_for(__method__) unless block
13
15
 
16
+ if (response_enum = @response_enum)
17
+ @response_enum = nil
18
+ # streaming already started, let's finish it
19
+
20
+ while (chunk = @buffered_chunks.shift)
21
+ block.call(chunk)
22
+ end
23
+
24
+ # consume enum til the end
25
+ begin
26
+ while (chunk = response_enum.next)
27
+ block.call(chunk)
28
+ end
29
+ rescue StopIteration
30
+ return
31
+ end
32
+ end
33
+
14
34
  @request.stream = self
15
35
 
16
36
  begin
17
37
  @on_chunk = block
18
38
 
19
- if @request.response
20
- # if we've already started collecting the payload, yield it first
21
- # before proceeding.
22
- body = @request.response.body
23
-
24
- body.each do |chunk|
25
- on_chunk(chunk)
26
- end
27
- end
39
+ response = @session.request(@request)
28
40
 
29
41
  response.raise_for_status
30
42
  ensure
@@ -64,27 +76,39 @@ module HTTPX
64
76
  # :nocov:
65
77
 
66
78
  def to_s
67
- response.to_s
79
+ if @request.response
80
+ @request.response.to_s
81
+ else
82
+ @buffered_chunks.join
83
+ end
68
84
  end
69
85
 
70
86
  private
71
87
 
72
88
  def response
73
- return @response if @response
74
-
75
89
  @request.response || begin
76
- @response = @session.request(@request)
90
+ response_enum = each
91
+ while (chunk = response_enum.next)
92
+ @buffered_chunks << chunk
93
+ break if @request.response
94
+ end
95
+ @response_enum = response_enum
96
+ @request.response
77
97
  end
78
98
  end
79
99
 
80
- def respond_to_missing?(meth, *args)
81
- response.respond_to?(meth, *args) || super
100
+ def respond_to_missing?(meth, include_private)
101
+ if (response = @request.response)
102
+ response.respond_to_missing?(meth, include_private)
103
+ else
104
+ @options.response_class.method_defined?(meth) || (include_private && @options.response_class.private_method_defined?(meth))
105
+ end || super
82
106
  end
83
107
 
84
- def method_missing(meth, *args, &block)
108
+ def method_missing(meth, *args, **kwargs, &block)
85
109
  return super unless response.respond_to?(meth)
86
110
 
87
- response.__send__(meth, *args, &block)
111
+ response.__send__(meth, *args, **kwargs, &block)
88
112
  end
89
113
  end
90
114
 
data/lib/httpx/request.rb CHANGED
@@ -104,21 +104,32 @@ module HTTPX
104
104
  @state = :idle
105
105
  @response = nil
106
106
  @peer_address = nil
107
+ @ping = false
107
108
  @persistent = @options.persistent
108
109
  @active_timeouts = []
109
110
  end
110
111
 
111
- # the read timeout defined for this requet.
112
+ # whether request has been buffered with a ping
113
+ def ping?
114
+ @ping
115
+ end
116
+
117
+ # marks the request as having been buffered with a ping
118
+ def ping!
119
+ @ping = true
120
+ end
121
+
122
+ # the read timeout defined for this request.
112
123
  def read_timeout
113
124
  @options.timeout[:read_timeout]
114
125
  end
115
126
 
116
- # the write timeout defined for this requet.
127
+ # the write timeout defined for this request.
117
128
  def write_timeout
118
129
  @options.timeout[:write_timeout]
119
130
  end
120
131
 
121
- # the request timeout defined for this requet.
132
+ # the request timeout defined for this request.
122
133
  def request_timeout
123
134
  @options.timeout[:request_timeout]
124
135
  end
@@ -249,6 +260,7 @@ module HTTPX
249
260
  case nextstate
250
261
  when :idle
251
262
  @body.rewind
263
+ @ping = false
252
264
  @response = nil
253
265
  @drainer = nil
254
266
  @active_timeouts.clear
data/lib/httpx/session.rb CHANGED
@@ -188,14 +188,9 @@ module HTTPX
188
188
  else
189
189
  pin_connection(connection, selector)
190
190
  end
191
- when :closed
191
+ when :closing, :closed
192
192
  connection.idling
193
193
  select_connection(connection, selector)
194
- when :closing
195
- connection.once(:close) do
196
- connection.idling
197
- select_connection(connection, selector)
198
- end
199
194
  else
200
195
  pin_connection(connection, selector)
201
196
  end
@@ -371,6 +366,8 @@ module HTTPX
371
366
  coalesce_connections(found_connection, connection, selector, from_pool)
372
367
  else
373
368
  found_connection.once(:open) do
369
+ next unless found_connection.current_session == self
370
+
374
371
  coalesce_connections(found_connection, connection, selector, from_pool)
375
372
  end
376
373
  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.4.3"
4
+ VERSION = "1.4.4"
5
5
  end
@@ -27,7 +27,10 @@ module HTTPX
27
27
  type streamRequest = Request & Plugins::Stream::RequestMethods
28
28
 
29
29
  @request: streamRequest
30
+ @options: Options
30
31
  @session: Plugins::sessionStream
32
+ @response_enum: Enumerator[String]?
33
+ @buffered_chunks: Array[String]
31
34
  @on_chunk: ^(String) -> void | nil
32
35
 
33
36
  def each: () { (String) -> void } -> void
data/sig/request.rbs CHANGED
@@ -20,6 +20,7 @@ module HTTPX
20
20
 
21
21
  attr_writer persistent: bool
22
22
 
23
+ @ping: bool
23
24
  @query_params: Hash[interned, untyped]?
24
25
  @trailers: Headers?
25
26
  @informational_status: Integer?
@@ -28,6 +29,10 @@ module HTTPX
28
29
 
29
30
  def initialize: (Symbol | String verb, generic_uri uri, Options options, ?request_params params) -> untyped
30
31
 
32
+ def ping?: () -> bool
33
+
34
+ def ping!: () -> void
35
+
31
36
  def empty?: () -> bool
32
37
 
33
38
  def close: () -> void
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpx
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tiago Cardoso
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-25 00:00:00.000000000 Z
10
+ date: 2025-04-03 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: http-2
@@ -152,6 +152,7 @@ extra_rdoc_files:
152
152
  - doc/release_notes/1_4_1.md
153
153
  - doc/release_notes/1_4_2.md
154
154
  - doc/release_notes/1_4_3.md
155
+ - doc/release_notes/1_4_4.md
155
156
  files:
156
157
  - LICENSE.txt
157
158
  - README.md
@@ -276,6 +277,7 @@ files:
276
277
  - doc/release_notes/1_4_1.md
277
278
  - doc/release_notes/1_4_2.md
278
279
  - doc/release_notes/1_4_3.md
280
+ - doc/release_notes/1_4_4.md
279
281
  - lib/httpx.rb
280
282
  - lib/httpx/adapters/datadog.rb
281
283
  - lib/httpx/adapters/faraday.rb
@@ -364,7 +366,6 @@ files:
364
366
  - lib/httpx/response/buffer.rb
365
367
  - lib/httpx/selector.rb
366
368
  - lib/httpx/session.rb
367
- - lib/httpx/session2.rb
368
369
  - lib/httpx/session_extensions.rb
369
370
  - lib/httpx/timers.rb
370
371
  - lib/httpx/transcoder.rb
@@ -381,7 +382,6 @@ files:
381
382
  - lib/httpx/transcoder/multipart/part.rb
382
383
  - lib/httpx/transcoder/utils/body_reader.rb
383
384
  - lib/httpx/transcoder/utils/deflater.rb
384
- - lib/httpx/transcoder/utils/inflater.rb
385
385
  - lib/httpx/utils.rb
386
386
  - lib/httpx/version.rb
387
387
  - sig/altsvc.rbs
@@ -436,7 +436,6 @@ files:
436
436
  - sig/plugins/proxy/socks5.rbs
437
437
  - sig/plugins/proxy/ssh.rbs
438
438
  - sig/plugins/push_promise.rbs
439
- - sig/plugins/query.rbs
440
439
  - sig/plugins/rate_limiter.rbs
441
440
  - sig/plugins/response_cache.rbs
442
441
  - sig/plugins/retries.rbs
@@ -470,7 +469,6 @@ files:
470
469
  - sig/transcoder/multipart.rbs
471
470
  - sig/transcoder/utils/body_reader.rbs
472
471
  - sig/transcoder/utils/deflater.rbs
473
- - sig/transcoder/utils/inflater.rbs
474
472
  - sig/utils.rbs
475
473
  homepage: https://gitlab.com/os85/httpx
476
474
  licenses:
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "session"
4
- module HTTPX
5
- class Session
6
- def initialize(options = EMPTY, &blk)
7
- @options = self.class.default_options.merge(options)
8
- @responses = {}
9
- @persistent = @options.persistent
10
- wrap(&blk) if blk
11
- end
12
-
13
- def wrap
14
- begin
15
- prev_persistent = @persistent
16
- @persistent = true
17
- yield self
18
- ensure
19
- @persistent = prev_persistent
20
- end
21
- end
22
- end
23
- end
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module HTTPX
4
- module Transcoder
5
- class Inflater
6
- def initialize(bytesize)
7
- @bytesize = bytesize
8
- end
9
-
10
- def call(chunk)
11
- buffer = @inflater.inflate(chunk)
12
- @bytesize -= chunk.bytesize
13
- if @bytesize <= 0
14
- buffer << @inflater.finish
15
- @inflater.close
16
- end
17
- buffer
18
- end
19
- end
20
- end
21
- end
@@ -1,18 +0,0 @@
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
@@ -1,12 +0,0 @@
1
- module HTTPX
2
- module Transcoder
3
- class Inflater
4
- @inflater: Zlib::Inflate
5
- @bytesize: Integer
6
-
7
- def initialize: (Integer | Float bytesize) -> void
8
-
9
- def call: (String chunk) -> String
10
- end
11
- end
12
- end