httpx 1.6.1 → 1.6.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 +4 -4
- data/doc/release_notes/1_6_2.md +11 -0
- data/doc/release_notes/1_6_3.md +47 -0
- data/lib/httpx/adapters/datadog.rb +15 -11
- data/lib/httpx/adapters/sentry.rb +1 -1
- data/lib/httpx/connection/http1.rb +9 -9
- data/lib/httpx/connection/http2.rb +14 -15
- data/lib/httpx/connection.rb +119 -102
- data/lib/httpx/extensions.rb +0 -14
- data/lib/httpx/io/ssl.rb +1 -1
- data/lib/httpx/loggable.rb +12 -2
- data/lib/httpx/options.rb +20 -0
- data/lib/httpx/plugins/callbacks.rb +15 -1
- data/lib/httpx/plugins/digest_auth.rb +1 -1
- data/lib/httpx/plugins/proxy/http.rb +37 -9
- data/lib/httpx/plugins/response_cache/file_store.rb +1 -0
- data/lib/httpx/plugins/response_cache.rb +13 -2
- data/lib/httpx/plugins/stream_bidi.rb +15 -6
- data/lib/httpx/pool.rb +53 -19
- data/lib/httpx/request.rb +3 -13
- data/lib/httpx/resolver/https.rb +35 -19
- data/lib/httpx/resolver/multi.rb +9 -32
- data/lib/httpx/resolver/native.rb +46 -38
- data/lib/httpx/resolver/resolver.rb +45 -28
- data/lib/httpx/resolver/system.rb +63 -39
- data/lib/httpx/selector.rb +35 -20
- data/lib/httpx/session.rb +18 -28
- data/lib/httpx/transcoder/deflate.rb +13 -8
- data/lib/httpx/transcoder/utils/body_reader.rb +1 -2
- data/lib/httpx/transcoder/utils/deflater.rb +1 -2
- data/lib/httpx/version.rb +1 -1
- data/sig/connection.rbs +12 -3
- data/sig/loggable.rbs +5 -1
- data/sig/options.rbs +5 -1
- data/sig/plugins/callbacks.rbs +3 -0
- data/sig/plugins/stream_bidi.rbs +3 -5
- data/sig/resolver/https.rbs +2 -0
- data/sig/resolver/multi.rbs +0 -9
- data/sig/resolver/native.rbs +0 -2
- data/sig/resolver/resolver.rbs +9 -8
- data/sig/resolver/system.rbs +4 -2
- data/sig/selector.rbs +2 -0
- data/sig/session.rbs +5 -3
- metadata +5 -1
|
@@ -7,7 +7,6 @@ module HTTPX
|
|
|
7
7
|
# from the Selectable API.
|
|
8
8
|
#
|
|
9
9
|
class Resolver::Resolver
|
|
10
|
-
include Callbacks
|
|
11
10
|
include Loggable
|
|
12
11
|
|
|
13
12
|
using ArrayExtensions::Intersect
|
|
@@ -39,8 +38,6 @@ module HTTPX
|
|
|
39
38
|
@record_type = RECORD_TYPES[family]
|
|
40
39
|
@options = options
|
|
41
40
|
@connections = []
|
|
42
|
-
|
|
43
|
-
set_resolver_callbacks
|
|
44
41
|
end
|
|
45
42
|
|
|
46
43
|
def each_connection(&block)
|
|
@@ -55,6 +52,12 @@ module HTTPX
|
|
|
55
52
|
|
|
56
53
|
alias_method :terminate, :close
|
|
57
54
|
|
|
55
|
+
def force_close(*args)
|
|
56
|
+
while (connection = @connections.shift)
|
|
57
|
+
connection.force_close(*args)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
58
61
|
def closed?
|
|
59
62
|
true
|
|
60
63
|
end
|
|
@@ -72,7 +75,7 @@ module HTTPX
|
|
|
72
75
|
|
|
73
76
|
# double emission check, but allow early resolution to work
|
|
74
77
|
conn_addrs = connection.addresses
|
|
75
|
-
return if !early_resolve && conn_addrs && (!conn_addrs.empty? && !addresses.intersect?(
|
|
78
|
+
return if !early_resolve && conn_addrs && (!conn_addrs.empty? && !addresses.intersect?(conn_addrs))
|
|
76
79
|
|
|
77
80
|
log do
|
|
78
81
|
"resolver #{FAMILY_TYPES[RECORD_TYPES[family]]}: " \
|
|
@@ -104,25 +107,23 @@ module HTTPX
|
|
|
104
107
|
end
|
|
105
108
|
end
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
connection.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
emit(:resolve, connection)
|
|
116
|
-
rescue StandardError => e
|
|
117
|
-
if early_resolve
|
|
118
|
-
connection.force_reset
|
|
119
|
-
throw(:resolve_error, e)
|
|
120
|
-
else
|
|
121
|
-
emit(:error, connection, e)
|
|
110
|
+
def handle_error(error)
|
|
111
|
+
if error.respond_to?(:connection) &&
|
|
112
|
+
error.respond_to?(:host)
|
|
113
|
+
@connections.delete(error.connection)
|
|
114
|
+
emit_resolve_error(error.connection, error.host, error)
|
|
115
|
+
else
|
|
116
|
+
while (connection = @connections.shift)
|
|
117
|
+
emit_resolve_error(connection, connection.peer.host, error)
|
|
122
118
|
end
|
|
123
119
|
end
|
|
124
120
|
end
|
|
125
121
|
|
|
122
|
+
def on_error(error)
|
|
123
|
+
handle_error(error)
|
|
124
|
+
disconnect
|
|
125
|
+
end
|
|
126
|
+
|
|
126
127
|
def early_resolve(connection, hostname: connection.peer.host)
|
|
127
128
|
addresses = @resolver_options[:cache] && (connection.addresses || HTTPX::Resolver.nolookup_resolve(hostname))
|
|
128
129
|
|
|
@@ -137,6 +138,25 @@ module HTTPX
|
|
|
137
138
|
true
|
|
138
139
|
end
|
|
139
140
|
|
|
141
|
+
private
|
|
142
|
+
|
|
143
|
+
def emit_resolved_connection(connection, addresses, early_resolve)
|
|
144
|
+
begin
|
|
145
|
+
connection.addresses = addresses
|
|
146
|
+
|
|
147
|
+
return if connection.state == :closed
|
|
148
|
+
|
|
149
|
+
resolve_connection(connection)
|
|
150
|
+
rescue StandardError => e
|
|
151
|
+
if early_resolve
|
|
152
|
+
connection.force_close
|
|
153
|
+
throw(:resolve_error, e)
|
|
154
|
+
else
|
|
155
|
+
emit_connection_error(connection, e)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
140
160
|
def emit_resolve_error(connection, hostname = connection.peer.host, ex = nil)
|
|
141
161
|
emit_connection_error(connection, resolve_error(hostname, ex))
|
|
142
162
|
end
|
|
@@ -150,12 +170,6 @@ module HTTPX
|
|
|
150
170
|
error
|
|
151
171
|
end
|
|
152
172
|
|
|
153
|
-
def set_resolver_callbacks
|
|
154
|
-
on(:resolve, &method(:resolve_connection))
|
|
155
|
-
on(:error, &method(:emit_connection_error))
|
|
156
|
-
on(:close, &method(:close_resolver))
|
|
157
|
-
end
|
|
158
|
-
|
|
159
173
|
def resolve_connection(connection)
|
|
160
174
|
@current_session.__send__(:on_resolver_connection, connection, @current_selector)
|
|
161
175
|
end
|
|
@@ -163,11 +177,14 @@ module HTTPX
|
|
|
163
177
|
def emit_connection_error(connection, error)
|
|
164
178
|
return connection.handle_connect_error(error) if connection.connecting?
|
|
165
179
|
|
|
166
|
-
connection.
|
|
180
|
+
connection.on_error(error)
|
|
167
181
|
end
|
|
168
182
|
|
|
169
|
-
def
|
|
170
|
-
|
|
183
|
+
def disconnect
|
|
184
|
+
return if closed?
|
|
185
|
+
|
|
186
|
+
close
|
|
187
|
+
@current_session.deselect_resolver(self, @current_selector)
|
|
171
188
|
end
|
|
172
189
|
end
|
|
173
190
|
end
|
|
@@ -56,13 +56,21 @@ module HTTPX
|
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def empty?
|
|
59
|
-
|
|
59
|
+
@connections.empty?
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def close
|
|
63
63
|
transition(:closed)
|
|
64
64
|
end
|
|
65
65
|
|
|
66
|
+
def force_close(*)
|
|
67
|
+
close
|
|
68
|
+
@queries.clear
|
|
69
|
+
@timeouts.clear
|
|
70
|
+
@ips.clear
|
|
71
|
+
super
|
|
72
|
+
end
|
|
73
|
+
|
|
66
74
|
def closed?
|
|
67
75
|
@state == :closed
|
|
68
76
|
end
|
|
@@ -86,36 +94,42 @@ module HTTPX
|
|
|
86
94
|
end
|
|
87
95
|
|
|
88
96
|
def timeout
|
|
89
|
-
return unless @queries.empty?
|
|
90
|
-
|
|
91
97
|
_, connection = @queries.first
|
|
92
98
|
|
|
93
99
|
return unless connection
|
|
94
100
|
|
|
95
|
-
@timeouts[connection.peer.host]
|
|
101
|
+
timeouts = @timeouts[connection.peer.host]
|
|
102
|
+
|
|
103
|
+
return if timeouts.empty?
|
|
104
|
+
|
|
105
|
+
log(level: 2) { "resolver #{FAMILY_TYPES[@record_type]}: next timeout #{timeouts.first} secs... (#{timeouts.size - 1} left)" }
|
|
106
|
+
|
|
107
|
+
timeouts.first
|
|
96
108
|
end
|
|
97
109
|
|
|
98
|
-
def
|
|
110
|
+
def lazy_resolve(connection)
|
|
99
111
|
@connections << connection
|
|
100
112
|
resolve
|
|
101
|
-
end
|
|
102
113
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
114
|
+
return if empty?
|
|
115
|
+
|
|
116
|
+
@current_session.select_resolver(self, @current_selector)
|
|
106
117
|
end
|
|
107
118
|
|
|
119
|
+
def early_resolve(connection, **); end
|
|
120
|
+
|
|
108
121
|
def handle_socket_timeout(interval)
|
|
109
122
|
error = HTTPX::ResolveTimeoutError.new(interval, "timed out while waiting on select")
|
|
110
123
|
error.set_backtrace(caller)
|
|
111
|
-
@queries.each do |
|
|
112
|
-
@connections.delete(connection)
|
|
113
|
-
emit_resolve_error(connection, host, error)
|
|
124
|
+
@queries.each do |_, connection| # rubocop:disable Style/HashEachMethods
|
|
125
|
+
emit_resolve_error(connection, connection.peer.host, error) if @connections.delete(connection)
|
|
114
126
|
end
|
|
115
127
|
|
|
116
128
|
while (connection = @connections.shift)
|
|
117
129
|
emit_resolve_error(connection, connection.peer.host, error)
|
|
118
130
|
end
|
|
131
|
+
|
|
132
|
+
close_or_resolve
|
|
119
133
|
end
|
|
120
134
|
|
|
121
135
|
private
|
|
@@ -140,34 +154,38 @@ module HTTPX
|
|
|
140
154
|
def consume
|
|
141
155
|
return if @connections.empty?
|
|
142
156
|
|
|
143
|
-
|
|
144
|
-
event = @pipe_read.getbyte
|
|
157
|
+
event = @pipe_read.read_nonblock(1, exception: false)
|
|
145
158
|
|
|
146
|
-
|
|
147
|
-
when DONE
|
|
148
|
-
*pair, addrs = @pipe_mutex.synchronize { @ips.pop }
|
|
149
|
-
if pair
|
|
150
|
-
@queries.delete(pair)
|
|
151
|
-
family, connection = pair
|
|
152
|
-
@connections.delete(connection)
|
|
159
|
+
return if event == :wait_readable
|
|
153
160
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
raise ResolveError, "socket pipe closed unexpectedly" if event.nil?
|
|
162
|
+
|
|
163
|
+
case event.unpack1("C")
|
|
164
|
+
when DONE
|
|
165
|
+
*pair, addrs = @pipe_mutex.synchronize { @ips.pop }
|
|
166
|
+
if pair
|
|
167
|
+
@queries.delete(pair)
|
|
168
|
+
family, connection = pair
|
|
169
|
+
@connections.delete(connection)
|
|
170
|
+
|
|
171
|
+
catch(:coalesced) { emit_addresses(connection, family, addrs) }
|
|
172
|
+
end
|
|
173
|
+
when ERROR
|
|
174
|
+
*pair, error = @pipe_mutex.synchronize { @ips.pop }
|
|
175
|
+
if pair && error
|
|
176
|
+
@queries.delete(pair)
|
|
177
|
+
_, connection = pair
|
|
178
|
+
@connections.delete(connection)
|
|
179
|
+
|
|
180
|
+
emit_resolve_error(connection, connection.peer.host, error)
|
|
165
181
|
end
|
|
166
182
|
end
|
|
167
183
|
|
|
168
|
-
return
|
|
184
|
+
return disconnect if @connections.empty?
|
|
169
185
|
|
|
170
186
|
resolve
|
|
187
|
+
rescue StandardError => e
|
|
188
|
+
on_error(e)
|
|
171
189
|
end
|
|
172
190
|
|
|
173
191
|
def resolve(connection = nil, hostname = nil)
|
|
@@ -240,16 +258,22 @@ module HTTPX
|
|
|
240
258
|
end
|
|
241
259
|
end
|
|
242
260
|
end
|
|
261
|
+
Thread.pass
|
|
243
262
|
end
|
|
244
263
|
|
|
245
|
-
def
|
|
246
|
-
|
|
247
|
-
|
|
264
|
+
def close_or_resolve
|
|
265
|
+
# drop already closed connections
|
|
266
|
+
@connections.shift until @connections.empty? || @connections.first.state != :closed
|
|
248
267
|
|
|
249
|
-
|
|
250
|
-
|
|
268
|
+
if (@connections - @queries.map(&:last)).empty?
|
|
269
|
+
disconnect
|
|
270
|
+
else
|
|
271
|
+
resolve
|
|
272
|
+
end
|
|
251
273
|
end
|
|
252
274
|
|
|
253
|
-
def
|
|
275
|
+
def __addrinfo_resolve(host, scheme)
|
|
276
|
+
Addrinfo.getaddrinfo(host, scheme, Socket::AF_UNSPEC, Socket::SOCK_STREAM)
|
|
277
|
+
end
|
|
254
278
|
end
|
|
255
279
|
end
|
data/lib/httpx/selector.rb
CHANGED
|
@@ -51,7 +51,7 @@ module HTTPX
|
|
|
51
51
|
|
|
52
52
|
begin
|
|
53
53
|
select(timeout) do |c|
|
|
54
|
-
c.log(level: 2) { "[#{c.state}] selected#{" after #{timeout} secs" unless timeout.nil?}..." }
|
|
54
|
+
c.log(level: 2) { "[#{c.state}] selected from selector##{object_id} #{" after #{timeout} secs" unless timeout.nil?}..." }
|
|
55
55
|
|
|
56
56
|
c.call
|
|
57
57
|
end
|
|
@@ -61,17 +61,6 @@ module HTTPX
|
|
|
61
61
|
@timers.fire(e)
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
|
-
rescue StandardError => e
|
|
65
|
-
each_connection do |c|
|
|
66
|
-
c.emit(:error, e)
|
|
67
|
-
end
|
|
68
|
-
rescue Exception # rubocop:disable Lint/RescueException
|
|
69
|
-
each_connection do |conn|
|
|
70
|
-
conn.force_reset
|
|
71
|
-
conn.disconnect
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
raise
|
|
75
64
|
end
|
|
76
65
|
|
|
77
66
|
def terminate
|
|
@@ -157,7 +146,9 @@ module HTTPX
|
|
|
157
146
|
|
|
158
147
|
next(is_closed) if is_closed
|
|
159
148
|
|
|
160
|
-
io.log(level: 2)
|
|
149
|
+
io.log(level: 2) do
|
|
150
|
+
"[#{io.state}] registering in selector##{object_id} for select (#{interests})#{" for #{interval} seconds" unless interval.nil?}"
|
|
151
|
+
end
|
|
161
152
|
|
|
162
153
|
if READABLE.include?(interests)
|
|
163
154
|
r = r.nil? ? io : (Array(r) << io)
|
|
@@ -206,7 +197,21 @@ module HTTPX
|
|
|
206
197
|
end
|
|
207
198
|
|
|
208
199
|
def select_many(r, w, interval, &block)
|
|
209
|
-
|
|
200
|
+
begin
|
|
201
|
+
readers, writers = ::IO.select(r, w, nil, interval)
|
|
202
|
+
rescue StandardError => e
|
|
203
|
+
(Array(r) + Array(w)).each do |sel|
|
|
204
|
+
sel.on_error(e)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
return
|
|
208
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
209
|
+
(Array(r) + Array(w)).each do |sel|
|
|
210
|
+
sel.force_close(true)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
raise e
|
|
214
|
+
end
|
|
210
215
|
|
|
211
216
|
if readers.nil? && writers.nil? && interval
|
|
212
217
|
[*r, *w].each { |io| io.handle_socket_timeout(interval) }
|
|
@@ -228,12 +233,22 @@ module HTTPX
|
|
|
228
233
|
end
|
|
229
234
|
|
|
230
235
|
def select_one(io, interests, interval)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
236
|
+
begin
|
|
237
|
+
result =
|
|
238
|
+
case interests
|
|
239
|
+
when :r then io.to_io.wait_readable(interval)
|
|
240
|
+
when :w then io.to_io.wait_writable(interval)
|
|
241
|
+
when :rw then rw_wait(io, interval)
|
|
242
|
+
end
|
|
243
|
+
rescue StandardError => e
|
|
244
|
+
io.on_error(e)
|
|
245
|
+
|
|
246
|
+
return
|
|
247
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
248
|
+
io.force_close(true)
|
|
249
|
+
|
|
250
|
+
raise e
|
|
251
|
+
end
|
|
237
252
|
|
|
238
253
|
unless result || interval.nil?
|
|
239
254
|
io.handle_socket_timeout(interval) unless @is_timer_interval
|
data/lib/httpx/session.rb
CHANGED
|
@@ -120,13 +120,16 @@ module HTTPX
|
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
def select_connection(connection, selector)
|
|
123
|
-
|
|
123
|
+
pin(connection, selector)
|
|
124
|
+
connection.log(level: 2) do
|
|
125
|
+
"registering into selector##{selector.object_id}"
|
|
126
|
+
end
|
|
124
127
|
selector.register(connection)
|
|
125
128
|
end
|
|
126
129
|
|
|
127
|
-
def
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
def pin(conn_or_resolver, selector)
|
|
131
|
+
conn_or_resolver.current_session = self
|
|
132
|
+
conn_or_resolver.current_selector = selector
|
|
130
133
|
end
|
|
131
134
|
|
|
132
135
|
alias_method :select_resolver, :select_connection
|
|
@@ -137,9 +140,6 @@ module HTTPX
|
|
|
137
140
|
end
|
|
138
141
|
selector.deregister(connection)
|
|
139
142
|
|
|
140
|
-
# when connections coalesce
|
|
141
|
-
return if connection.state == :idle
|
|
142
|
-
|
|
143
143
|
return if cloned
|
|
144
144
|
|
|
145
145
|
return if @closing && connection.state == :closed
|
|
@@ -194,7 +194,7 @@ module HTTPX
|
|
|
194
194
|
if options.io
|
|
195
195
|
select_connection(connection, selector)
|
|
196
196
|
else
|
|
197
|
-
|
|
197
|
+
pin(connection, selector)
|
|
198
198
|
end
|
|
199
199
|
when :closing, :closed
|
|
200
200
|
connection.idling
|
|
@@ -205,7 +205,7 @@ module HTTPX
|
|
|
205
205
|
resolve_connection(connection, selector)
|
|
206
206
|
end
|
|
207
207
|
else
|
|
208
|
-
|
|
208
|
+
pin(connection, selector)
|
|
209
209
|
end
|
|
210
210
|
|
|
211
211
|
connection
|
|
@@ -224,13 +224,7 @@ module HTTPX
|
|
|
224
224
|
|
|
225
225
|
# tries deactivating connections in the +selector+, deregistering the ones that have been deactivated.
|
|
226
226
|
def deactivate(selector)
|
|
227
|
-
selector.each_connection.
|
|
228
|
-
c.deactivate
|
|
229
|
-
|
|
230
|
-
c.state == :inactive
|
|
231
|
-
end.each do |c| # rubocop:disable Style/MultilineBlockChain
|
|
232
|
-
deselect_connection(c, selector)
|
|
233
|
-
end
|
|
227
|
+
selector.each_connection.each(&:deactivate)
|
|
234
228
|
end
|
|
235
229
|
|
|
236
230
|
# callback executed when an HTTP/2 promise frame has been received.
|
|
@@ -395,6 +389,7 @@ module HTTPX
|
|
|
395
389
|
|
|
396
390
|
resolver = find_resolver_for(connection, selector)
|
|
397
391
|
|
|
392
|
+
pin(connection, selector)
|
|
398
393
|
resolver.early_resolve(connection) || resolver.lazy_resolve(connection)
|
|
399
394
|
end
|
|
400
395
|
|
|
@@ -402,6 +397,9 @@ module HTTPX
|
|
|
402
397
|
from_pool = false
|
|
403
398
|
found_connection = selector.find_mergeable_connection(connection) || begin
|
|
404
399
|
from_pool = true
|
|
400
|
+
connection.log(level: 2) do
|
|
401
|
+
"try finding a mergeable connection in pool##{@pool.object_id}"
|
|
402
|
+
end
|
|
405
403
|
@pool.checkout_mergeable_connection(connection)
|
|
406
404
|
end
|
|
407
405
|
|
|
@@ -409,19 +407,12 @@ module HTTPX
|
|
|
409
407
|
|
|
410
408
|
connection.log(level: 2) do
|
|
411
409
|
"try coalescing from #{from_pool ? "pool##{@pool.object_id}" : "selector##{selector.object_id}"} " \
|
|
412
|
-
"(
|
|
410
|
+
"(connection##{found_connection.object_id}[#{found_connection.origin}])"
|
|
413
411
|
end
|
|
414
412
|
|
|
415
413
|
coalesce_connections(found_connection, connection, selector, from_pool)
|
|
416
414
|
end
|
|
417
415
|
|
|
418
|
-
def on_resolver_close(resolver, selector)
|
|
419
|
-
return if resolver.closed?
|
|
420
|
-
|
|
421
|
-
deselect_resolver(resolver, selector)
|
|
422
|
-
resolver.close unless resolver.closed?
|
|
423
|
-
end
|
|
424
|
-
|
|
425
416
|
def find_resolver_for(connection, selector)
|
|
426
417
|
if (resolver = selector.find_resolver(connection.options))
|
|
427
418
|
resolver.log(level: 2) { "found resolver##{connection.object_id}(#{connection.state}) in selector##{selector.object_id}" }
|
|
@@ -430,8 +421,7 @@ module HTTPX
|
|
|
430
421
|
|
|
431
422
|
resolver = @pool.checkout_resolver(connection.options)
|
|
432
423
|
resolver.log(level: 2) { "found resolver##{connection.object_id}(#{connection.state}) in pool##{@pool.object_id}" }
|
|
433
|
-
resolver
|
|
434
|
-
resolver.current_selector = selector
|
|
424
|
+
pin(resolver, selector)
|
|
435
425
|
|
|
436
426
|
resolver
|
|
437
427
|
end
|
|
@@ -449,9 +439,9 @@ module HTTPX
|
|
|
449
439
|
return false
|
|
450
440
|
end
|
|
451
441
|
|
|
452
|
-
conn2.log(level: 2) { "coalescing with
|
|
453
|
-
conn2.coalesce!(conn1)
|
|
442
|
+
conn2.log(level: 2) { "coalescing with connection##{conn1.object_id}[#{conn1.origin}])" }
|
|
454
443
|
select_connection(conn1, selector) if from_pool
|
|
444
|
+
conn2.coalesce!(conn1)
|
|
455
445
|
conn2.disconnect
|
|
456
446
|
true
|
|
457
447
|
end
|
|
@@ -10,15 +10,20 @@ module HTTPX
|
|
|
10
10
|
def deflate(chunk)
|
|
11
11
|
@deflater ||= Zlib::Deflate.new
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
else
|
|
20
|
-
@deflater.deflate(chunk)
|
|
13
|
+
unless chunk.nil?
|
|
14
|
+
chunk = @deflater.deflate(chunk)
|
|
15
|
+
|
|
16
|
+
# deflate call may return nil, while still
|
|
17
|
+
# retaining the last chunk in the deflater.
|
|
18
|
+
return chunk unless chunk.empty?
|
|
21
19
|
end
|
|
20
|
+
|
|
21
|
+
return if @deflater.closed?
|
|
22
|
+
|
|
23
|
+
last = @deflater.finish
|
|
24
|
+
@deflater.close
|
|
25
|
+
|
|
26
|
+
last unless last.empty?
|
|
22
27
|
end
|
|
23
28
|
end
|
|
24
29
|
|
data/lib/httpx/version.rb
CHANGED
data/sig/connection.rbs
CHANGED
|
@@ -46,6 +46,7 @@ module HTTPX
|
|
|
46
46
|
@exhausted: bool
|
|
47
47
|
@cloned: bool
|
|
48
48
|
@coalesced_connection: instance?
|
|
49
|
+
@altsvc_connection: instance?
|
|
49
50
|
@sibling: instance?
|
|
50
51
|
@main_sibling: bool
|
|
51
52
|
|
|
@@ -66,6 +67,8 @@ module HTTPX
|
|
|
66
67
|
|
|
67
68
|
def coalesce!: (instance connection) -> void
|
|
68
69
|
|
|
70
|
+
def coalesced?: () -> boolish
|
|
71
|
+
|
|
69
72
|
def coalescable?: (Connection connection) -> bool
|
|
70
73
|
|
|
71
74
|
def create_idle: (?Hash[Symbol, untyped] options) -> instance
|
|
@@ -76,7 +79,9 @@ module HTTPX
|
|
|
76
79
|
|
|
77
80
|
def connecting?: () -> bool
|
|
78
81
|
|
|
79
|
-
def
|
|
82
|
+
def current_context?: () -> bool
|
|
83
|
+
|
|
84
|
+
def io_connected?: () -> boolish
|
|
80
85
|
|
|
81
86
|
def inflight?: () -> boolish
|
|
82
87
|
|
|
@@ -90,6 +95,8 @@ module HTTPX
|
|
|
90
95
|
|
|
91
96
|
def close: () -> void
|
|
92
97
|
|
|
98
|
+
def force_close: (?bool delete_pending) -> void
|
|
99
|
+
|
|
93
100
|
def force_reset: (?bool cloned) -> void
|
|
94
101
|
|
|
95
102
|
def reset: () -> void
|
|
@@ -112,6 +119,8 @@ module HTTPX
|
|
|
112
119
|
|
|
113
120
|
def disconnect: () -> void
|
|
114
121
|
|
|
122
|
+
def on_error: (HTTPX::TimeoutError | Error | StandardError error, ?Request? request) -> void
|
|
123
|
+
|
|
115
124
|
private
|
|
116
125
|
|
|
117
126
|
def initialize: (http_uri uri, Options options) -> void
|
|
@@ -130,6 +139,8 @@ module HTTPX
|
|
|
130
139
|
|
|
131
140
|
def send_request_to_parser: (Request request) -> void
|
|
132
141
|
|
|
142
|
+
def enqueue_pending_requests_from_parser: (HTTP1 | HTTP2 parser) -> void
|
|
143
|
+
|
|
133
144
|
def build_parser: (?String protocol) -> (Object & _Parser)
|
|
134
145
|
|
|
135
146
|
def set_parser_callbacks: (HTTP1 | HTTP2 parser) -> void
|
|
@@ -142,8 +153,6 @@ module HTTPX
|
|
|
142
153
|
|
|
143
154
|
def build_socket: (?Array[Resolver::Entry]? addrs) -> (TCP | SSL | UNIX)
|
|
144
155
|
|
|
145
|
-
def on_error: (HTTPX::TimeoutError | Error | StandardError error, ?Request? request) -> void
|
|
146
|
-
|
|
147
156
|
def handle_error: (StandardError error, ?Request? request) -> void
|
|
148
157
|
|
|
149
158
|
def close_sibling: () -> void
|
data/sig/loggable.rbs
CHANGED
|
@@ -12,6 +12,10 @@ module HTTPX
|
|
|
12
12
|
|
|
13
13
|
def log_exception: (Exception error, ?level: Integer, ?color: Symbol, ?debug_level: Integer, ?debug: _IOLogger?) -> void
|
|
14
14
|
|
|
15
|
-
def
|
|
15
|
+
def log_redact_headers: (_ToS text) -> String
|
|
16
|
+
|
|
17
|
+
def log_redact_body: (_ToS text) -> String
|
|
18
|
+
|
|
19
|
+
def log_redact: (_ToS text, bool should_redact) -> String
|
|
16
20
|
end
|
|
17
21
|
end
|
data/sig/options.rbs
CHANGED
|
@@ -17,9 +17,11 @@ module HTTPX
|
|
|
17
17
|
|
|
18
18
|
DEFAULT_OPTIONS: Hash[Symbol, untyped]
|
|
19
19
|
REQUEST_BODY_IVARS: Array[Symbol]
|
|
20
|
+
USER_AGENT: String
|
|
20
21
|
|
|
21
22
|
type timeout_type = :connect_timeout | :settings_timeout | :close_handshake_timeout | :operation_timeout | :keep_alive_timeout | :read_timeout | :write_timeout | :request_timeout
|
|
22
23
|
type timeout = Hash[timeout_type, Numeric?]
|
|
24
|
+
type redact_value = :headers | :body | bool
|
|
23
25
|
|
|
24
26
|
def self.new: (?options) -> instance
|
|
25
27
|
|
|
@@ -146,6 +148,8 @@ module HTTPX
|
|
|
146
148
|
|
|
147
149
|
def initialize: (?options options) -> void
|
|
148
150
|
|
|
151
|
+
def do_initialize: (?options options) -> void
|
|
152
|
+
|
|
149
153
|
def access_option: (Hash[Symbol, untyped] | Object | nil obj, Symbol k, Hash[Symbol, Symbol]? ivar_map) -> untyped
|
|
150
154
|
|
|
151
155
|
# integer
|
|
@@ -175,7 +179,7 @@ module HTTPX
|
|
|
175
179
|
def option_io: (io_option value) -> io_option
|
|
176
180
|
def option_fallback_protocol: (String value) -> String
|
|
177
181
|
def option_debug: (_IOLogger value) -> _IOLogger
|
|
178
|
-
def option_debug_redact: (
|
|
182
|
+
def option_debug_redact: (redact_value value) -> redact_value
|
|
179
183
|
def option_compress_request_body: (bool value) -> bool
|
|
180
184
|
def option_decompress_response_body: (bool value) -> bool
|
|
181
185
|
def option_persistent: (bool value) -> bool
|