lib/httpx/connection.rb in httpx-1.0.2 vs lib/httpx/connection.rb in httpx-1.1.0
- old
+ new
@@ -68,10 +68,12 @@
end
@inflight = 0
@keep_alive_timeout = @options.timeout[:keep_alive_timeout]
+ @intervals = []
+
self.addresses = @options.addresses if @options.addresses
end
# this is a semi-private method, to be used by the resolver
# to initiate the io object.
@@ -211,10 +213,13 @@
@io.to_io
end
def call
case @state
+ when :idle
+ connect
+ consume
when :closed
return
when :closing
consume
transition(:closed)
@@ -292,11 +297,19 @@
def open?
@state == :open || @state == :inactive
end
- def raise_timeout_error(interval)
+ def handle_socket_timeout(interval)
+ @intervals.delete_if(&:elapsed?)
+
+ unless @intervals.empty?
+ # remove the intervals which will elapse
+
+ return
+ end
+
error = HTTPX::TimeoutError.new(interval, "timed out while waiting on select")
error.set_backtrace(caller)
on_error(error)
end
@@ -447,10 +460,11 @@
@parser ||= build_parser
end
def send_request_to_parser(request)
@inflight += 1
+ request.peer_address = @io.ip
parser.send(request)
set_request_timeouts(request)
return unless @state == :inactive
@@ -653,23 +667,30 @@
end
end
def set_request_timeouts(request)
write_timeout = request.write_timeout
- request.once(:headers) do
- @timers.after(write_timeout) { write_timeout_callback(request, write_timeout) }
- end unless write_timeout.nil? || write_timeout.infinite?
-
read_timeout = request.read_timeout
- request.once(:done) do
- @timers.after(read_timeout) { read_timeout_callback(request, read_timeout) }
- end unless read_timeout.nil? || read_timeout.infinite?
-
request_timeout = request.request_timeout
- request.once(:headers) do
- @timers.after(request_timeout) { read_timeout_callback(request, request_timeout, RequestTimeoutError) }
- end unless request_timeout.nil? || request_timeout.infinite?
+
+ unless write_timeout.nil? || write_timeout.infinite?
+ set_request_timeout(request, write_timeout, :headers, %i[done response]) do
+ write_timeout_callback(request, write_timeout)
+ end
+ end
+
+ unless read_timeout.nil? || read_timeout.infinite?
+ set_request_timeout(request, read_timeout, :done, :response) do
+ read_timeout_callback(request, read_timeout)
+ end
+ end
+
+ return if request_timeout.nil? || request_timeout.infinite?
+
+ set_request_timeout(request, request_timeout, :headers, :response) do
+ read_timeout_callback(request, request_timeout, RequestTimeoutError)
+ end
end
def write_timeout_callback(request, write_timeout)
return if request.state == :done
@@ -684,9 +705,27 @@
return if response && response.finished?
@write_buffer.clear
error = error_type.new(request, request.response, read_timeout)
on_error(error)
+ end
+
+ def set_request_timeout(request, timeout, start_event, finish_events, &callback)
+ request.once(start_event) do
+ interval = @timers.after(timeout, callback)
+
+ Array(finish_events).each do |event|
+ # clean up reques timeouts if the connection errors out
+ request.once(event) do
+ if @intervals.include?(interval)
+ interval.delete(callback)
+ @intervals.delete(interval) if interval.no_callbacks?
+ end
+ end
+ end
+
+ @intervals << interval
+ end
end
class << self
def parser_type(protocol)
case protocol