mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-11-22 00:05:57 -05:00
https resolver: close the http-2 connection on error
the connection was being kept open beyond the scope of the session scope. also, the connection wasn't deactivated after use, lingering in the selector.
This commit is contained in:
parent
3efca5b703
commit
7ca5d9febb
@ -31,7 +31,7 @@ module HTTPX
|
||||
}.freeze
|
||||
|
||||
def_delegators :@resolver_connection, :state, :connecting?, :to_io, :call, :close,
|
||||
:terminate, :inflight?, :handle_socket_timeout
|
||||
:closed?, :deactivate, :terminate, :inflight?, :handle_socket_timeout
|
||||
|
||||
def initialize(_, options)
|
||||
super
|
||||
@ -109,6 +109,7 @@ module HTTPX
|
||||
reset_hostname(hostname)
|
||||
throw(:resolve_error, e) if connection.pending.empty?
|
||||
emit_resolve_error(connection, connection.peer.host, e)
|
||||
close_or_resolve
|
||||
end
|
||||
end
|
||||
|
||||
@ -118,6 +119,7 @@ module HTTPX
|
||||
hostname = @requests.delete(request)
|
||||
connection = reset_hostname(hostname)
|
||||
emit_resolve_error(connection, connection.peer.host, e)
|
||||
close_or_resolve
|
||||
else
|
||||
# @type var response: HTTPX::Response
|
||||
parse(request, response)
|
||||
@ -144,6 +146,7 @@ module HTTPX
|
||||
|
||||
unless @queries.value?(connection)
|
||||
emit_resolve_error(connection)
|
||||
close_or_resolve
|
||||
return
|
||||
end
|
||||
|
||||
@ -153,10 +156,12 @@ module HTTPX
|
||||
connection = reset_hostname(host)
|
||||
|
||||
emit_resolve_error(connection)
|
||||
close_or_resolve
|
||||
when :decode_error
|
||||
host = @requests.delete(request)
|
||||
connection = reset_hostname(host)
|
||||
emit_resolve_error(connection, connection.peer.host, result)
|
||||
close_or_resolve
|
||||
end
|
||||
end
|
||||
|
||||
@ -166,6 +171,7 @@ module HTTPX
|
||||
host = @requests.delete(request)
|
||||
connection = reset_hostname(host)
|
||||
emit_resolve_error(connection)
|
||||
close_or_resolve
|
||||
return
|
||||
|
||||
else
|
||||
@ -204,9 +210,7 @@ module HTTPX
|
||||
catch(:coalesced) { emit_addresses(connection, @family, addresses.map { |a| Resolver::Entry.new(a["data"], a["TTL"]) }) }
|
||||
end
|
||||
end
|
||||
return if @connections.empty?
|
||||
|
||||
resolve
|
||||
close_or_resolve(true)
|
||||
end
|
||||
|
||||
def build_request(hostname)
|
||||
@ -249,5 +253,20 @@ module HTTPX
|
||||
|
||||
connection
|
||||
end
|
||||
|
||||
def close_or_resolve(should_deactivate = false)
|
||||
# drop already closed connections
|
||||
@connections.shift until @connections.empty? || @connections.first.state != :closed
|
||||
|
||||
if (@connections - @queries.values).empty?
|
||||
if should_deactivate
|
||||
deactivate
|
||||
else
|
||||
disconnect
|
||||
end
|
||||
else
|
||||
resolve
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -40,6 +40,8 @@ module HTTPX
|
||||
def decode_response_body: (Response) -> dns_decoding_response
|
||||
|
||||
def reset_hostname: (String hostname, ?reset_candidates: bool) -> Connection?
|
||||
|
||||
def close_or_resolve: (?bool should_deactivate) -> void
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -58,6 +58,8 @@ module HTTPX
|
||||
def emit_resolve_error: (Connection connection, ?String hostname, ?StandardError) -> void
|
||||
|
||||
def resolve_error: (String hostname, ?StandardError?) -> (ResolveError | ResolveTimeoutError)
|
||||
|
||||
def close_or_resolve: () -> void
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -123,11 +123,16 @@ module Requests
|
||||
when :https
|
||||
|
||||
define_method :"test_resolver_#{resolver_type}_get_request" do
|
||||
session = HTTPX.plugin(SessionWithPool)
|
||||
uri = build_uri("/get")
|
||||
response = session.head(uri, resolver_class: resolver_type, resolver_options: options.merge(use_get: true))
|
||||
verify_status(response, 200)
|
||||
response.close
|
||||
HTTPX.plugin(SessionWithPool).wrap do |http|
|
||||
uri = build_uri("/get")
|
||||
response = http.head(uri, resolver_class: resolver_type, resolver_options: options.merge(use_get: true))
|
||||
verify_status(response, 200)
|
||||
response.close
|
||||
resolver_uri = URI(options[:uri])
|
||||
resolver_conn = http.pool.connections.find { |c| c.origin.to_s == resolver_uri.origin }
|
||||
assert resolver_conn, "https resolver connection should still be there"
|
||||
assert resolver_conn.open?, "resolver connection should be kept around open"
|
||||
end
|
||||
end
|
||||
|
||||
define_method :"test_resolver_#{resolver_type}_unresolvable_servername" do
|
||||
@ -188,16 +193,20 @@ module Requests
|
||||
end
|
||||
|
||||
define_method :"test_resolver_#{resolver_type}_no_answers" do
|
||||
session = HTTPX.plugin(SessionWithPool)
|
||||
uri = URI(build_uri("/get"))
|
||||
resolver_class = Class.new(HTTPX::Resolver::HTTPS) do
|
||||
def parse_addresses(_, request)
|
||||
super([], request)
|
||||
HTTPX.plugin(SessionWithPool).wrap do |http|
|
||||
uri = URI(build_uri("/get"))
|
||||
resolver_class = Class.new(HTTPX::Resolver::HTTPS) do
|
||||
def parse_addresses(_, request)
|
||||
super([], request)
|
||||
end
|
||||
end
|
||||
response = http.head(uri, resolver_class: resolver_class, resolver_options: options.merge(record_types: %w[]))
|
||||
verify_error_response(response, HTTPX::ResolveError)
|
||||
resolver_uri = URI(options[:uri])
|
||||
resolver_conn = http.pool.connections.find { |c| c.origin.to_s == resolver_uri.origin }
|
||||
assert resolver_conn, "https resolver connection should still be there"
|
||||
assert resolver_conn.state == :closed, "resolver connection should have closed after error"
|
||||
end
|
||||
response = session.head(uri, resolver_class: resolver_class, resolver_options: options.merge(record_types: %w[]))
|
||||
verify_error_response(response, HTTPX::ResolveError)
|
||||
assert session.pool.connections.size == 1, "https resolver connection should still be there"
|
||||
end
|
||||
when :native
|
||||
define_method :"test_resolver_#{resolver_type}_tcp_request" do
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user