diff --git a/lib/faraday/adapter.rb b/lib/faraday/adapter.rb index f3e6af7bf..a581166c6 100644 --- a/lib/faraday/adapter.rb +++ b/lib/faraday/adapter.rb @@ -78,8 +78,7 @@ def save_response(env, status, body, headers = nil, reason_phrase = nil, finishe # @param type [Symbol] Describes which timeout setting to get: :read, # :write, or :open. # @param options [Hash] Hash containing Symbol keys like :timeout, - # :read_timeout, :write_timeout, :open_timeout, or - # :timeout + # :read_timeout, :write_timeout, or :open_timeout # # @return [Integer, nil] Timeout duration in seconds, or nil if no timeout # has been set. diff --git a/lib/faraday/adapter/test.rb b/lib/faraday/adapter/test.rb index b8a5b28aa..7843d8c1a 100644 --- a/lib/faraday/adapter/test.rb +++ b/lib/faraday/adapter/test.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'timeout' + module Faraday class Adapter # @example @@ -277,11 +279,22 @@ def call(env) end block_arity = stub.block.arity + params = if block_arity >= 0 + [env, meta].take(block_arity) + else + [env, meta] + end + + timeout = request_timeout(:open, env[:request]) + timeout ||= request_timeout(:read, env[:request]) + status, headers, body = - if block_arity >= 0 - stub.block.call(*[env, meta].take(block_arity)) + if timeout + ::Timeout.timeout(timeout, Faraday::TimeoutError) do + stub.block.call(*params) + end else - stub.block.call(env, meta) + stub.block.call(*params) end # We need to explicitly pass `reason_phrase = nil` here to avoid keyword args conflicts. diff --git a/spec/faraday/adapter/test_spec.rb b/spec/faraday/adapter/test_spec.rb index bdeb6cdf9..117bb7899 100644 --- a/spec/faraday/adapter/test_spec.rb +++ b/spec/faraday/adapter/test_spec.rb @@ -410,4 +410,33 @@ def make_request end end end + + describe 'request timeout' do + subject(:request) do + connection.get('/sleep') do |req| + req.options.timeout = timeout + end + end + + before do + stubs.get('/sleep') do + sleep(0.01) + [200, {}, ''] + end + end + + context 'when request is within timeout' do + let(:timeout) { 1 } + + it { expect(request.status).to eq 200 } + end + + context 'when request is too slow' do + let(:timeout) { 0.001 } + + it 'raises an exception' do + expect { request }.to raise_error(Faraday::TimeoutError) + end + end + end end