httpx 1.6.2 → 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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/doc/release_notes/1_6_3.md +47 -0
  3. data/lib/httpx/adapters/sentry.rb +1 -1
  4. data/lib/httpx/connection/http1.rb +9 -9
  5. data/lib/httpx/connection/http2.rb +14 -15
  6. data/lib/httpx/connection.rb +115 -102
  7. data/lib/httpx/extensions.rb +0 -14
  8. data/lib/httpx/io/ssl.rb +1 -1
  9. data/lib/httpx/loggable.rb +12 -2
  10. data/lib/httpx/options.rb +20 -0
  11. data/lib/httpx/plugins/callbacks.rb +15 -1
  12. data/lib/httpx/plugins/digest_auth.rb +1 -1
  13. data/lib/httpx/plugins/proxy/http.rb +37 -9
  14. data/lib/httpx/plugins/response_cache/file_store.rb +1 -0
  15. data/lib/httpx/plugins/response_cache.rb +13 -2
  16. data/lib/httpx/plugins/stream_bidi.rb +15 -6
  17. data/lib/httpx/pool.rb +53 -19
  18. data/lib/httpx/request.rb +3 -13
  19. data/lib/httpx/resolver/https.rb +35 -19
  20. data/lib/httpx/resolver/multi.rb +8 -27
  21. data/lib/httpx/resolver/native.rb +46 -38
  22. data/lib/httpx/resolver/resolver.rb +45 -28
  23. data/lib/httpx/resolver/system.rb +63 -39
  24. data/lib/httpx/selector.rb +35 -20
  25. data/lib/httpx/session.rb +18 -28
  26. data/lib/httpx/transcoder/deflate.rb +13 -8
  27. data/lib/httpx/transcoder/utils/body_reader.rb +1 -2
  28. data/lib/httpx/transcoder/utils/deflater.rb +1 -2
  29. data/lib/httpx/version.rb +1 -1
  30. data/sig/connection.rbs +12 -3
  31. data/sig/loggable.rbs +5 -1
  32. data/sig/options.rbs +5 -1
  33. data/sig/plugins/callbacks.rbs +3 -0
  34. data/sig/plugins/stream_bidi.rbs +3 -5
  35. data/sig/resolver/https.rbs +2 -0
  36. data/sig/resolver/multi.rbs +0 -9
  37. data/sig/resolver/native.rbs +0 -2
  38. data/sig/resolver/resolver.rbs +9 -8
  39. data/sig/resolver/system.rbs +4 -2
  40. data/sig/selector.rbs +2 -0
  41. data/sig/session.rbs +5 -3
  42. metadata +3 -1
@@ -49,8 +49,19 @@ module HTTPX
49
49
  transition(:closed)
50
50
  end
51
51
 
52
+ def force_close(*)
53
+ @timer.cancel if @timer
54
+ @timer = @name = nil
55
+ @queries.clear
56
+ @timeouts.clear
57
+ close
58
+ super
59
+ ensure
60
+ terminate
61
+ end
62
+
52
63
  def terminate
53
- emit(:close, self)
64
+ disconnect
54
65
  end
55
66
 
56
67
  def closed?
@@ -84,7 +95,7 @@ module HTTPX
84
95
  if @nameserver.nil?
85
96
  ex = ResolveError.new("No available nameserver")
86
97
  ex.set_backtrace(caller)
87
- connection.force_reset
98
+ connection.force_close
88
99
  throw(:resolve_error, ex)
89
100
  else
90
101
  @connections << connection
@@ -93,15 +104,34 @@ module HTTPX
93
104
  end
94
105
 
95
106
  def timeout
96
- return if @connections.empty?
107
+ return unless @name
97
108
 
98
109
  @start_timeout = Utils.now
99
- hosts = @queries.keys
100
- @timeouts.values_at(*hosts).reject(&:empty?).map(&:first).min
110
+
111
+ timeouts = @timeouts[@name]
112
+
113
+ return if timeouts.empty?
114
+
115
+ log(level: 2) { "resolver #{FAMILY_TYPES[@record_type]}: next timeout #{timeouts.first} secs... (#{timeouts.size - 1} left)" }
116
+
117
+ timeouts.first
101
118
  end
102
119
 
103
120
  def handle_socket_timeout(interval); end
104
121
 
122
+ def handle_error(error)
123
+ if error.respond_to?(:connection) &&
124
+ error.respond_to?(:host)
125
+ reset_hostname(error.host, connection: error.connection)
126
+ else
127
+ @queries.each do |host, connection|
128
+ reset_hostname(host, connection: connection)
129
+ end
130
+ end
131
+
132
+ super
133
+ end
134
+
105
135
  private
106
136
 
107
137
  def calculate_interests
@@ -118,7 +148,6 @@ module HTTPX
118
148
 
119
149
  break unless calculate_interests == :w
120
150
 
121
- # do_retry
122
151
  dwrite
123
152
 
124
153
  break unless calculate_interests == :r
@@ -133,7 +162,7 @@ module HTTPX
133
162
  retry
134
163
  else
135
164
  handle_error(e)
136
- emit(:close, self)
165
+ disconnect
137
166
  end
138
167
  rescue NativeResolveError => e
139
168
  handle_error(e)
@@ -154,7 +183,7 @@ module HTTPX
154
183
  @timer = @current_selector.after(timeout) do
155
184
  next unless @connections.include?(connection)
156
185
 
157
- @timer = nil
186
+ @timer = @name = nil
158
187
 
159
188
  do_retry(h, connection, timeout)
160
189
  end
@@ -178,8 +207,6 @@ module HTTPX
178
207
  @timeouts.clear
179
208
  resolve(connection, h)
180
209
  else
181
-
182
- @timeouts.delete(h)
183
210
  reset_hostname(h, reset_candidates: false)
184
211
 
185
212
  unless @queries.empty?
@@ -273,7 +300,7 @@ module HTTPX
273
300
  def parse(buffer)
274
301
  @timer.cancel
275
302
 
276
- @timer = nil
303
+ @timer = @name = nil
277
304
 
278
305
  code, result = Resolver.decode_dns_answer(buffer)
279
306
 
@@ -431,13 +458,14 @@ module HTTPX
431
458
  def generate_candidates(name)
432
459
  return [name] if name.end_with?(".")
433
460
 
434
- candidates = []
435
461
  name_parts = name.scan(/[^.]+/)
436
- candidates = [name] if @ndots <= name_parts.size - 1
437
- candidates.concat(@search.map { |domain| [*name_parts, *domain].join(".") })
462
+ candidates = @search.map { |domain| [*name_parts, *domain].join(".") }
438
463
  fname = "#{name}."
439
- candidates << fname unless candidates.include?(fname)
440
-
464
+ if @ndots <= name_parts.size - 1
465
+ candidates.unshift(fname)
466
+ else
467
+ candidates << fname
468
+ end
441
469
  candidates
442
470
  end
443
471
 
@@ -498,27 +526,7 @@ module HTTPX
498
526
  ConnectTimeoutError => e
499
527
  # these errors may happen during TCP handshake
500
528
  # treat them as resolve errors.
501
- handle_error(e)
502
- emit(:close, self)
503
- end
504
-
505
- def handle_error(error)
506
- if error.respond_to?(:connection) &&
507
- error.respond_to?(:host)
508
- reset_hostname(error.host, connection: error.connection)
509
- @connections.delete(error.connection)
510
- emit_resolve_error(error.connection, error.host, error)
511
- else
512
- @queries.each do |host, connection|
513
- reset_hostname(host, connection: connection)
514
- @connections.delete(connection)
515
- emit_resolve_error(connection, host, error)
516
- end
517
-
518
- while (connection = @connections.shift)
519
- emit_resolve_error(connection, connection.peer.host, error)
520
- end
521
- end
529
+ on_error(e)
522
530
  end
523
531
 
524
532
  def reset_hostname(hostname, connection: @queries.delete(hostname), reset_candidates: true)
@@ -538,7 +546,7 @@ module HTTPX
538
546
  @connections.shift until @connections.empty? || @connections.first.state != :closed
539
547
 
540
548
  if (@connections - @queries.values).empty?
541
- emit(:close, self)
549
+ disconnect
542
550
  else
543
551
  resolve
544
552
  end
@@ -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?(!conn_addrs))
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
- private
108
-
109
- def emit_resolved_connection(connection, addresses, early_resolve)
110
- begin
111
- connection.addresses = addresses
112
-
113
- return if connection.state == :closed
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.emit(:error, error)
180
+ connection.on_error(error)
167
181
  end
168
182
 
169
- def close_resolver(resolver)
170
- @current_session.__send__(:on_resolver_close, resolver, @current_selector)
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
- true
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].first
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 <<(connection)
110
+ def lazy_resolve(connection)
99
111
  @connections << connection
100
112
  resolve
101
- end
102
113
 
103
- def early_resolve(connection, **)
104
- self << connection
105
- true
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 |host, connection|
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
- if @pipe_read.wait_readable
144
- event = @pipe_read.getbyte
157
+ event = @pipe_read.read_nonblock(1, exception: false)
145
158
 
146
- case event
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
- catch(:coalesced) { emit_addresses(connection, family, addrs) }
155
- end
156
- when ERROR
157
- *pair, error = @pipe_mutex.synchronize { @ips.pop }
158
- if pair && error
159
- @queries.delete(pair)
160
- @connections.delete(connection)
161
-
162
- _, connection = pair
163
- emit_resolve_error(connection, connection.peer.host, error)
164
- end
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 emit(:close, self) if @connections.empty?
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 __addrinfo_resolve(host, scheme)
246
- Addrinfo.getaddrinfo(host, scheme, Socket::AF_UNSPEC, Socket::SOCK_STREAM)
247
- end
264
+ def close_or_resolve
265
+ # drop already closed connections
266
+ @connections.shift until @connections.empty? || @connections.first.state != :closed
248
267
 
249
- def emit_connection_error(_, error)
250
- throw(:resolve_error, error)
268
+ if (@connections - @queries.map(&:last)).empty?
269
+ disconnect
270
+ else
271
+ resolve
272
+ end
251
273
  end
252
274
 
253
- def close_resolver(resolver); end
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
@@ -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) { "[#{io.state}] registering for select (#{interests})#{" for #{interval} seconds" unless interval.nil?}" }
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
- readers, writers = ::IO.select(r, w, nil, interval)
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
- result =
232
- case interests
233
- when :r then io.to_io.wait_readable(interval)
234
- when :w then io.to_io.wait_writable(interval)
235
- when :rw then rw_wait(io, interval)
236
- end
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
- pin_connection(connection, selector)
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 pin_connection(connection, selector)
128
- connection.current_session = self
129
- connection.current_selector = selector
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
- pin_connection(connection, selector)
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
- pin_connection(connection, selector)
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.select do |c|
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
- "(conn##{found_connection.object_id}[#{found_connection.origin}])"
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.current_session = self
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 conn##{conn1.object_id}[#{conn1.origin}])" }
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