aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Kane <andrew@ankane.org>2023-01-13 20:27:05 -0800
committergit <svn-admin@ruby-lang.org>2023-12-07 07:00:53 +0000
commitd97479f9c966bd2c9d52c8be28aca9431760c610 (patch)
treee2f53abae3b46f2c269fe61be3fff35ef3f34e84
parent7d32830b8ce14cc130d052a4aa67495a34ed55dc (diff)
downloadruby-d97479f9c966bd2c9d52c8be28aca9431760c610.tar.gz
[ruby/open-uri] Add :max_redirects option
https://github.com/ruby/open-uri/commit/7fd5ea09a7
-rw-r--r--lib/open-uri.rb3
-rw-r--r--test/open-uri/test_open-uri.rb19
2 files changed, 22 insertions, 0 deletions
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