mirror of
https://github.com/HoneyryderChuck/httpx.git
synced 2025-10-04 00:00:37 -04:00
fix: reset timeout callbacks when requests are routed to a different connection
this may happen in a few contexts, such as connection exhaustion, but more importantly, when a request is retried in a different connection; if the request successfully sets the callbacks before the connection raises an issue and the request is retried in a new one, the callback from the faulty connection are carried with it, and triggered at a time when the connection is back in the connection pool, or worse, used in a different thread this fix relies on :idle transition callback, which is called before request is routed around
This commit is contained in:
parent
999b6a603a
commit
88f8f5d287
@ -4,7 +4,7 @@ module HTTPX
|
||||
module Callbacks
|
||||
def on(type, &action)
|
||||
callbacks(type) << action
|
||||
self
|
||||
action
|
||||
end
|
||||
|
||||
def once(type, &block)
|
||||
@ -12,7 +12,6 @@ module HTTPX
|
||||
block.call(*args, &callback)
|
||||
:delete
|
||||
end
|
||||
self
|
||||
end
|
||||
|
||||
def emit(type, *args)
|
||||
|
@ -903,13 +903,13 @@ module HTTPX
|
||||
end
|
||||
|
||||
def set_request_timeout(label, request, timeout, start_event, finish_events, &callback)
|
||||
request.once(start_event) do
|
||||
request.set_timeout_callback(start_event) do
|
||||
timer = @current_selector.after(timeout, callback)
|
||||
request.active_timeouts << label
|
||||
|
||||
Array(finish_events).each do |event|
|
||||
# clean up request timeouts if the connection errors out
|
||||
request.once(event) do
|
||||
request.set_timeout_callback(event) do
|
||||
timer.cancel
|
||||
request.active_timeouts.delete(label)
|
||||
end
|
||||
|
@ -25,6 +25,7 @@ module HTTPX
|
||||
class_eval(<<-MOD, __FILE__, __LINE__ + 1)
|
||||
def on_#{meth}(&blk) # def on_connection_opened(&blk)
|
||||
on(:#{meth}, &blk) # on(:connection_opened, &blk)
|
||||
self # self
|
||||
end # end
|
||||
MOD
|
||||
end
|
||||
|
@ -36,6 +36,7 @@ module HTTPX
|
||||
class_eval(<<-MOD, __FILE__, __LINE__ + 1)
|
||||
def on_#{meth}(&blk) # def on_circuit_open(&blk)
|
||||
on(:#{meth}, &blk) # on(:circuit_open, &blk)
|
||||
self # self
|
||||
end # end
|
||||
MOD
|
||||
end
|
||||
|
@ -284,6 +284,15 @@ module HTTPX
|
||||
def expects?
|
||||
@headers["expect"] == "100-continue" && @informational_status == 100 && !@response
|
||||
end
|
||||
|
||||
def set_timeout_callback(event, &callback)
|
||||
clb = once(event, &callback)
|
||||
|
||||
# reset timeout callbacks when requests get rerouted to a different connection
|
||||
once(:idle) do
|
||||
callbacks(event).delete(clb)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -4,8 +4,8 @@ module HTTPX
|
||||
end
|
||||
|
||||
module Callbacks
|
||||
def on: (Symbol) { (*untyped) -> void } -> self
|
||||
def once: (Symbol) { (*untyped) -> void } -> self
|
||||
def on: (Symbol) { (*untyped) -> void } -> ^(*untyped) -> void
|
||||
def once: (Symbol) { (*untyped) -> void } -> ^(*untyped) -> void
|
||||
def emit: (Symbol, *untyped) -> void
|
||||
|
||||
def callbacks_for?: (Symbol) -> bool
|
||||
|
@ -64,6 +64,8 @@ module HTTPX
|
||||
|
||||
def request_timeout: () -> Numeric?
|
||||
|
||||
def set_timeout_callback: (Symbol event) { (*untyped) -> void } -> void
|
||||
|
||||
private
|
||||
|
||||
def initialize_body: (Options options) -> Transcoder::_Encoder?
|
||||
|
Loading…
x
Reference in New Issue
Block a user