diff --git a/lib/prerender_rails.rb b/lib/prerender_rails.rb index 98c1ca9..a664579 100644 --- a/lib/prerender_rails.rb +++ b/lib/prerender_rails.rb @@ -111,12 +111,19 @@ def call(env) return cached_response.finish end - prerendered_response = get_prerendered_page_response(env) - - if prerendered_response - response = build_rack_response_from_prerender(prerendered_response) - after_render(env, prerendered_response) - return response.finish + begin + prerendered_response = get_prerendered_page_response(env) + + if prerendered_response + response = build_rack_response_from_prerender(prerendered_response) + after_render(env, prerendered_response) + return response.finish + end + rescue Timeout::Error + if @options[:read_timeout] + response = Rack::Response.new(nil, 503, nil) + return response.finish + end end end @@ -183,6 +190,7 @@ def get_prerendered_page_response(env) req.basic_auth(ENV['PRERENDER_USERNAME'], ENV['PRERENDER_PASSWORD']) if @options[:basic_auth] http = Net::HTTP.new(url.host, url.port) http.use_ssl = true if url.scheme == 'https' + http.read_timeout = @options[:read_timeout] if @options[:read_timeout] response = http.request(req) if response['Content-Encoding'] == 'gzip' response.body = ActiveSupport::Gzip.decompress(response.body) diff --git a/test/lib/prerender_rails.rb b/test/lib/prerender_rails.rb index 719b61e..3d1aff7 100644 --- a/test/lib/prerender_rails.rb +++ b/test/lib/prerender_rails.rb @@ -102,6 +102,20 @@ end + it 'should return a timeout error to the crawler if the request takes longer than the read_timeout argument' do + request = Rack::MockRequest.env_for '/', 'HTTP_USER_AGENT' => bot + stub_request(:get, @prerender.build_api_url(request)) + .with(headers: { 'User-Agent': bot }) + .to_raise(Timeout::Error) + + err = assert_raises Timeout::Error do + Rack::Prerender.new(@app, read_timeout: 22).call(request) + end + + assert_equal err.message, '503 Service Unavailable' + end + + it "should continue to app routes if the url is part of the regex specific blacklist" do request = Rack::MockRequest.env_for "/search/things/123/page", "HTTP_USER_AGENT" => bot response = Rack::Prerender.new(@app, blacklist: ['^/search', '/help']).call(request)