From 74fc7bf77d6cb26e2660174b5e18bae8585467c9 Mon Sep 17 00:00:00 2001 From: HoneyryderChuck Date: Mon, 22 Jul 2024 14:53:53 +0100 Subject: [PATCH] when bubbling up errors in the connection, handle request error directly instead of expecting it to be contained within it, and therefore handled explicitly. sometimes they may not. --- lib/httpx/adapters/datadog.rb | 10 +++++++--- lib/httpx/connection.rb | 30 ++++++++++++++++++++---------- lib/httpx/connection/http1.rb | 14 +++++++++----- lib/httpx/connection/http2.rb | 14 +++++++++----- sig/connection.rbs | 4 ++-- sig/connection/http1.rbs | 2 +- sig/connection/http2.rbs | 2 +- 7 files changed, 49 insertions(+), 27 deletions(-) diff --git a/lib/httpx/adapters/datadog.rb b/lib/httpx/adapters/datadog.rb index 6deb5508..a5e4b846 100644 --- a/lib/httpx/adapters/datadog.rb +++ b/lib/httpx/adapters/datadog.rb @@ -195,15 +195,19 @@ module Datadog::Tracing # that the tracing logic hasn't been injected yet; in such cases, the approximate # initial resolving time is collected from the connection, and used as span start time, # and the tracing object in inserted before the on response callback is called. - def handle_error(error) + def handle_error(error, request = nil) return super unless Datadog::Tracing.enabled? return super unless error.respond_to?(:connection) - @pending.each do |request| - RequestTracer.new(request).call(error.connection.init_time) + @pending.each do |req| + next if request and request == req + + RequestTracer.new(req).call(error.connection.init_time) end + RequestTracer.new(request).call(error.connection.init_time) if request + super end end diff --git a/lib/httpx/connection.rb b/lib/httpx/connection.rb index a5d9e26e..68b186ed 100644 --- a/lib/httpx/connection.rb +++ b/lib/httpx/connection.rb @@ -641,7 +641,7 @@ module HTTPX end end - def on_error(error) + def on_error(error, request = nil) if error.instance_of?(TimeoutError) # inactive connections do not contribute to the select loop, therefore @@ -655,17 +655,25 @@ module HTTPX error = error.to_connection_error if connecting? end - handle_error(error) + handle_error(error, request) reset end - def handle_error(error) - parser.handle_error(error) if @parser && parser.respond_to?(:handle_error) - while (request = @pending.shift) - response = ErrorResponse.new(request, error) - request.response = response - request.emit(:response, response) + def handle_error(error, request = nil) + parser.handle_error(error, request) if @parser && parser.respond_to?(:handle_error) + while (req = @pending.shift) + next if request && req == request + + response = ErrorResponse.new(req, error) + req.response = response + req.emit(:response, response) end + + return unless request + + response = ErrorResponse.new(request, error) + request.response = response + request.emit(:response, response) end def set_request_timeouts(request) @@ -709,7 +717,8 @@ module HTTPX @write_buffer.clear error = WriteTimeoutError.new(request, nil, write_timeout) - on_error(error) + + on_error(error, request) end def read_timeout_callback(request, read_timeout, error_type = ReadTimeoutError) @@ -719,7 +728,8 @@ module HTTPX @write_buffer.clear error = error_type.new(request, request.response, read_timeout) - on_error(error) + + on_error(error, request) end def set_request_timeout(request, timeout, start_event, finish_events, &callback) diff --git a/lib/httpx/connection/http1.rb b/lib/httpx/connection/http1.rb index 1b6b1718..46bedbaa 100644 --- a/lib/httpx/connection/http1.rb +++ b/lib/httpx/connection/http1.rb @@ -197,7 +197,7 @@ module HTTPX end end - def handle_error(ex) + def handle_error(ex, request = nil) if (ex.is_a?(EOFError) || ex.is_a?(TimeoutError)) && @request && @request.response && !@request.response.headers.key?("content-length") && !@request.response.headers.key?("transfer-encoding") @@ -211,11 +211,15 @@ module HTTPX if @pipelining catch(:called) { disable } else - @requests.each do |request| - emit(:error, request, ex) + @requests.each do |req| + next if request && request == req + + emit(:error, req, ex) end - @pending.each do |request| - emit(:error, request, ex) + @pending.each do |req| + next if request && request == req + + emit(:error, req, ex) end end end diff --git a/lib/httpx/connection/http2.rb b/lib/httpx/connection/http2.rb index 782fae7c..630a9697 100644 --- a/lib/httpx/connection/http2.rb +++ b/lib/httpx/connection/http2.rb @@ -123,7 +123,7 @@ module HTTPX end end - def handle_error(ex) + def handle_error(ex, request = nil) if ex.instance_of?(TimeoutError) && !@handshake_completed && @connection.state != :closed @connection.goaway(:settings_timeout, "closing due to settings timeout") emit(:close_handshake) @@ -131,11 +131,15 @@ module HTTPX settings_ex.set_backtrace(ex.backtrace) ex = settings_ex end - @streams.each_key do |request| - emit(:error, request, ex) + @streams.each_key do |req| + next if request && request == req + + emit(:error, req, ex) end - @pending.each do |request| - emit(:error, request, ex) + @pending.each do |req| + next if request && request == req + + emit(:error, req, ex) end end diff --git a/sig/connection.rbs b/sig/connection.rbs index 82ce190f..ae5ac06e 100644 --- a/sig/connection.rbs +++ b/sig/connection.rbs @@ -119,9 +119,9 @@ module HTTPX def build_socket: (?Array[ipaddr]? addrs) -> (TCP | SSL | UNIX) - def on_error: (HTTPX::TimeoutError | Error | StandardError error) -> void + def on_error: (HTTPX::TimeoutError | Error | StandardError error, ?Request? request) -> void - def handle_error: (StandardError error) -> void + def handle_error: (StandardError error, ?Request? request) -> void def purge_after_closed: () -> void diff --git a/sig/connection/http1.rbs b/sig/connection/http1.rbs index d920bc4b..1ec1d147 100644 --- a/sig/connection/http1.rbs +++ b/sig/connection/http1.rbs @@ -38,7 +38,7 @@ module HTTPX def consume: () -> void - def handle_error: (StandardError ex) -> void + def handle_error: (StandardError ex, ?Request? request) -> void def on_start: () -> void diff --git a/sig/connection/http2.rbs b/sig/connection/http2.rbs index 33eeac5f..42ad972e 100644 --- a/sig/connection/http2.rbs +++ b/sig/connection/http2.rbs @@ -32,7 +32,7 @@ module HTTPX def consume: () -> void - def handle_error: (StandardError ex) -> void + def handle_error: (StandardError ex, ?Request? request) -> void def ping: () -> void