From d5eacd8b7eb81d2cfb4359ef593325f69ec93512 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Thu, 22 Aug 2019 17:36:25 -0700 Subject: [PATCH] Handle cookies when handling HTTP redirects This approach will handle the Set-Cookie header during the redirect. To avoid redirect loops for arbitrary cookies and the same URI, it will not redirect to an URI more than once for the cookie/non-cookie cases. Implements Ruby Feature #11322 --- lib/open-uri.rb | 15 +++++++++++---- test/open-uri/test_open-uri.rb | 11 +++++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/open-uri.rb b/lib/open-uri.rb index 421a82e..4f14e9a 100644 --- a/lib/open-uri.rb +++ b/lib/open-uri.rb @@ -207,7 +207,7 @@ def OpenURI.open_loop(uri, options) # :nodoc: uri_set = {} buf = nil while true - redirect = catch(:open_uri_redirect) { + redirect, cookie = catch(:open_uri_redirect) { buf = Buffer.new uri.buffer_open(buf, find_proxy.call(uri), options) nil @@ -229,9 +229,13 @@ def OpenURI.open_loop(uri, options) # :nodoc: options = options.dup options.delete :http_basic_authentication end + if cookie + options = options.dup + options[:cookie] = cookie.split(';')[0] + end uri = redirect - raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s - uri_set[uri.to_s] = true + raise "HTTP redirection loop: #{uri}" if uri_set.include?([uri.to_s, !!cookie]) + uri_set[[uri.to_s, !!cookie]] = true else break end @@ -321,6 +325,9 @@ def OpenURI.open_http(buf, target, proxy, options) # :nodoc: resp = nil http.start { + if cookie = options[:cookie] + header['Cookie'] = cookie + end req = Net::HTTP::Get.new(request_uri, header) if options.include? :http_basic_authentication user, pass = options[:http_basic_authentication] @@ -359,7 +366,7 @@ def OpenURI.open_http(buf, target, proxy, options) # :nodoc: rescue URI::InvalidURIError raise OpenURI::HTTPError.new(io.status.join(' ') + ' (Invalid Location URI)', io) end - throw :open_uri_redirect, loc_uri + throw :open_uri_redirect, [loc_uri, resp['Set-Cookie']] else raise OpenURI::HTTPError.new(io.status.join(' '), io) end diff --git a/test/open-uri/test_open-uri.rb b/test/open-uri/test_open-uri.rb index 9a52e7a..ff5877f 100644 --- a/test/open-uri/test_open-uri.rb +++ b/test/open-uri/test_open-uri.rb @@ -545,6 +545,17 @@ def test_redirect_auth_failure_r1 } end + def test_redirect_cookie + with_http {|srv, dr, url| + srv.mount_proc("/r1/") {|req, res| res.status = 301; res['set-cookie'] = "cookie-name=cookie-value"; res["location"] = "#{url}/r2"; res.body = "r1" } + srv.mount_proc("/r2/") {|req, res| res.body = req['Cookie'] } + URI.open("#{url}/r1/") {|f| + assert_equal("#{url}/r2", f.base_uri.to_s) + assert_equal('cookie-name=cookie-value', f.read) + } + } + end + def test_userinfo assert_raise(ArgumentError) { URI.open("http://user:pass@127.0.0.1/") {} } end