From d97479f9c966bd2c9d52c8be28aca9431760c610 Mon Sep 17 00:00:00 2001 From: Andrew Kane Date: Fri, 13 Jan 2023 20:27:05 -0800 Subject: [PATCH] [ruby/open-uri] Add :max_redirects option https://github.com/ruby/open-uri/commit/7fd5ea09a7 --- lib/open-uri.rb | 3 +++ test/open-uri/test_open-uri.rb | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/open-uri.rb b/lib/open-uri.rb index 00e4c2d9b8..56dac75b29 100644 --- a/lib/open-uri.rb +++ b/lib/open-uri.rb @@ -108,6 +108,7 @@ module OpenURI :ftp_active_mode => false, :redirect => true, :encoding => nil, + :max_redirects => nil, } def OpenURI.check_options(options) # :nodoc: @@ -211,6 +212,7 @@ module OpenURI end uri_set = {} + max_redirects = options[:max_redirects] buf = nil while true redirect = catch(:open_uri_redirect) { @@ -238,6 +240,7 @@ module OpenURI uri = redirect raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s uri_set[uri.to_s] = true + raise "Too many redirects" if max_redirects && uri_set.size > max_redirects else break end diff --git a/test/open-uri/test_open-uri.rb b/test/open-uri/test_open-uri.rb index 86aefc52c8..6bad7f4bdf 100644 --- a/test/open-uri/test_open-uri.rb +++ b/test/open-uri/test_open-uri.rb @@ -558,6 +558,25 @@ class TestOpenURI < Test::Unit::TestCase } end + def test_max_redirects_success + with_http {|srv, dr, url| + srv.mount_proc("/r1/") {|req, res| res.status = 301; res["location"] = "#{url}/r2"; res.body = "r1" } + srv.mount_proc("/r2/") {|req, res| res.status = 301; res["location"] = "#{url}/r3"; res.body = "r2" } + srv.mount_proc("/r3/") {|req, res| res.body = "r3" } + URI.open("#{url}/r1/", max_redirects: 2) { |f| assert_equal("r3", f.read) } + } + end + + def test_max_redirects_too_many + with_http {|srv, dr, url| + srv.mount_proc("/r1/") {|req, res| res.status = 301; res["location"] = "#{url}/r2"; res.body = "r1" } + srv.mount_proc("/r2/") {|req, res| res.status = 301; res["location"] = "#{url}/r3"; res.body = "r2" } + srv.mount_proc("/r3/") {|req, res| res.body = "r3" } + exc = assert_raise(RuntimeError) { URI.open("#{url}/r1/", max_redirects: 1) {} } + assert_equal("Too many redirects", exc.message) + } + end + def test_userinfo assert_raise(ArgumentError) { URI.open("http://user:pass@127.0.0.1/") {} } end