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 +4 -4
- data/doc/release_notes/1_4_4.md +14 -0
- data/lib/httpx/adapters/webmock.rb +2 -0
- data/lib/httpx/connection.rb +4 -1
- data/lib/httpx/io/ssl.rb +6 -3
- data/lib/httpx/plugins/retries.rb +1 -1
- data/lib/httpx/plugins/stream.rb +42 -18
- data/lib/httpx/request.rb +15 -3
- data/lib/httpx/session.rb +3 -6
- data/lib/httpx/version.rb +1 -1
- data/sig/plugins/stream.rbs +3 -0
- data/sig/request.rbs +5 -0
- metadata +4 -6
- data/lib/httpx/session2.rb +0 -23
- data/lib/httpx/transcoder/utils/inflater.rb +0 -21
- data/sig/plugins/query.rbs +0 -18
- data/sig/transcoder/utils/inflater.rbs +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4aa5b1cfd43d05f50fc7246219d6a90cb5591e11c8bfeee1f1cf62ffa91993fc
|
4
|
+
data.tar.gz: 58f96325ac13b8caddb708464a75ee6dafcfe7b8284f0825803ac3d0c4d8ccc1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/lib/httpx/connection.rb
CHANGED
@@ -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
|
-
|
96
|
-
|
97
|
-
|
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
|
data/lib/httpx/plugins/stream.rb
CHANGED
@@ -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
|
-
@
|
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
|
-
|
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
|
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
|
-
|
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,
|
81
|
-
response.
|
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
|
-
#
|
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
|
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
|
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
data/sig/plugins/stream.rbs
CHANGED
@@ -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.
|
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
|
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:
|
data/lib/httpx/session2.rb
DELETED
@@ -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
|
data/sig/plugins/query.rbs
DELETED
@@ -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
|