From 1177c0c7bb55578c7336366c8c35b082dd5da2d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 3 Dec 2019 21:39:27 +0100 Subject: [PATCH 01/15] Fix incorrect spec Expectation goes first. --- test/rubygems/test_remote_fetch_error.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_remote_fetch_error.rb b/test/rubygems/test_remote_fetch_error.rb index 780e5e79f778..766086756ecb 100644 --- a/test/rubygems/test_remote_fetch_error.rb +++ b/test/rubygems/test_remote_fetch_error.rb @@ -5,7 +5,7 @@ class TestRemoteFetchError < Gem::TestCase def test_password_redacted error = Gem::RemoteFetcher::FetchError.new('There was an error fetching', 'https://user:secret@gemsource.org') - refute_match error.to_s, 'secret' + refute_match 'secret', error.to_s end def test_invalid_url From 0f55f337b174f9f70a213c078ae2a1c2bfd07e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 14:44:32 +0100 Subject: [PATCH 02/15] Stop autoloading `uri` --- lib/rubygems/request.rb | 2 ++ lib/rubygems/source.rb | 1 - lib/rubygems/uri_formatter.rb | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rubygems/request.rb b/lib/rubygems/request.rb index 435c7c53cbe4..b5a14ec34d7f 100644 --- a/lib/rubygems/request.rb +++ b/lib/rubygems/request.rb @@ -19,6 +19,7 @@ def self.create_with_proxy(uri, request_class, last_modified, proxy) # :nodoc: end def self.proxy_uri(proxy) # :nodoc: + require "uri" case proxy when :no_proxy then nil when URI::HTTP then proxy @@ -173,6 +174,7 @@ def self.get_proxy_from_env(scheme = 'http') :no_proxy : get_proxy_from_env('http') end + require "uri" uri = URI(Gem::UriFormatter.new(env_proxy).normalize) if uri and uri.user.nil? and uri.password.nil? diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb index d949aa838d0d..8572cb180623 100644 --- a/lib/rubygems/source.rb +++ b/lib/rubygems/source.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true autoload :FileUtils, 'fileutils' -autoload :URI, 'uri' require "rubygems/text" ## diff --git a/lib/rubygems/uri_formatter.rb b/lib/rubygems/uri_formatter.rb index 0a24dde24d4b..f3d510470bb0 100644 --- a/lib/rubygems/uri_formatter.rb +++ b/lib/rubygems/uri_formatter.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true require 'cgi' -require 'uri' ## # The UriFormatter handles URIs from user-input and escaping. From 78b8d8a7c69c9d1ebebbcdbaafe5c83350986821 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 15:50:35 +0100 Subject: [PATCH 03/15] Simplify `nil` arg handling to `FetchError` `URI.parse` consistenly returns `InvalidURIError`, so we can remove one rescue exception class and make the parsing like it looks in other places of this file. --- lib/rubygems/remote_fetcher.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index c399cc9d95c6..128b2116104f 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -31,10 +31,10 @@ class FetchError < Gem::Exception def initialize(message, uri) super message begin - uri = URI(uri) + uri = URI.parse(uri) uri.password = 'REDACTED' if uri.password @uri = uri.to_s - rescue URI::InvalidURIError, ArgumentError + rescue URI::InvalidURIError @uri = uri end end From 16b9deac7241871efb7aa94002f76e46b9fd67e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 18:41:12 +0100 Subject: [PATCH 04/15] Remove unreachable code `URI.parse` never returns `nil`. --- lib/rubygems/remote_fetcher.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 128b2116104f..670f3d812556 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -256,8 +256,6 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0) def fetch_path(uri, mtime = nil, head = false) uri = URI.parse uri unless URI::Generic === uri - raise ArgumentError, "bad uri: #{uri}" unless uri - unless uri.scheme raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}" end From 3b11357986748b2f6d992e1c8c76dbfc630db286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 19:00:28 +0100 Subject: [PATCH 05/15] Consistently use `is_a?` over `===` --- lib/rubygems/remote_fetcher.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 670f3d812556..2435ff69b1c5 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -254,7 +254,7 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0) # Downloads +uri+ and returns it as a String. def fetch_path(uri, mtime = nil, head = false) - uri = URI.parse uri unless URI::Generic === uri + uri = URI.parse uri unless uri.is_a?(URI::Generic) unless uri.scheme raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}" From 730d9d0405ff53f6fe47ad04b761bbf56045c690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 3 Dec 2019 21:58:49 +0100 Subject: [PATCH 06/15] Do the inverse `is_a?` check Because it's more straightforwards and avoid loading `URI`. --- lib/rubygems/remote_fetcher.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 2435ff69b1c5..9d4dc9dd0723 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -135,7 +135,7 @@ def download(spec, source_uri, install_dir = Gem.dir) # a valid URI with escaped characters. e.g. "{DESede}" is encoded # as "%7BDESede%7D". If this is escaped again the percentage # symbols will be escaped. - unless source_uri.is_a?(URI::Generic) + if source_uri.is_a?(String) begin source_uri = URI.parse(source_uri) rescue @@ -254,7 +254,7 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0) # Downloads +uri+ and returns it as a String. def fetch_path(uri, mtime = nil, head = false) - uri = URI.parse uri unless uri.is_a?(URI::Generic) + uri = URI.parse uri if uri.is_a?(String) unless uri.scheme raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}" From 7085cd41584571572f750608497e1c09516cbb90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 19:01:20 +0100 Subject: [PATCH 07/15] Move comment to a better place The command refers to the begin-rescue-end block, not to the URI::Generic condition. --- lib/rubygems/remote_fetcher.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 9d4dc9dd0723..9c75c12dc8a0 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -130,12 +130,12 @@ def download(spec, source_uri, install_dir = Gem.dir) FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir - # Always escape URI's to deal with potential spaces and such - # It should also be considered that source_uri may already be - # a valid URI with escaped characters. e.g. "{DESede}" is encoded - # as "%7BDESede%7D". If this is escaped again the percentage - # symbols will be escaped. if source_uri.is_a?(String) + # Always escape URI's to deal with potential spaces and such + # It should also be considered that source_uri may already be + # a valid URI with escaped characters. e.g. "{DESede}" is encoded + # as "%7BDESede%7D". If this is escaped again the percentage + # symbols will be escaped. begin source_uri = URI.parse(source_uri) rescue From 7629e91b46972a50166c0fed0965ce3a9f552170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 19:02:44 +0100 Subject: [PATCH 08/15] Reuse local variable --- lib/rubygems/remote_fetcher.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 9c75c12dc8a0..7c1c77d4c382 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -236,7 +236,7 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0) unless location = response['Location'] raise FetchError.new("redirecting but no redirect location was given", uri) end - location = URI.parse response['Location'] + location = URI.parse location if https?(uri) && !https?(location) raise FetchError.new("redirecting to non-https resource: #{location}", uri) From 4ce8a59bef6dcb38421444c4f7171d1ce431f148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 20:51:09 +0100 Subject: [PATCH 09/15] Remove unnecessary `to_s` --- lib/rubygems/remote_fetcher.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 7c1c77d4c382..6f0ee199371e 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -139,7 +139,7 @@ def download(spec, source_uri, install_dir = Gem.dir) begin source_uri = URI.parse(source_uri) rescue - source_uri = URI.parse(URI::DEFAULT_PARSER.escape(source_uri.to_s)) + source_uri = URI.parse(URI::DEFAULT_PARSER.escape(source_uri)) end end From 60d365ac26a63a7c8b8d86e2e2dda6fe77ce9e1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 19:10:24 +0100 Subject: [PATCH 10/15] Normalize and centralize uri parsing --- lib/rubygems/remote_fetcher.rb | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 6f0ee199371e..23daccc9eff2 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -130,18 +130,7 @@ def download(spec, source_uri, install_dir = Gem.dir) FileUtils.mkdir_p cache_dir rescue nil unless File.exist? cache_dir - if source_uri.is_a?(String) - # Always escape URI's to deal with potential spaces and such - # It should also be considered that source_uri may already be - # a valid URI with escaped characters. e.g. "{DESede}" is encoded - # as "%7BDESede%7D". If this is escaped again the percentage - # symbols will be escaped. - begin - source_uri = URI.parse(source_uri) - rescue - source_uri = URI.parse(URI::DEFAULT_PARSER.escape(source_uri)) - end - end + source_uri = parse_uri(source_uri) scheme = source_uri.scheme @@ -236,7 +225,7 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0) unless location = response['Location'] raise FetchError.new("redirecting but no redirect location was given", uri) end - location = URI.parse location + location = parse_uri location if https?(uri) && !https?(location) raise FetchError.new("redirecting to non-https resource: #{location}", uri) @@ -254,7 +243,7 @@ def fetch_http(uri, last_modified = nil, head = false, depth = 0) # Downloads +uri+ and returns it as a String. def fetch_path(uri, mtime = nil, head = false) - uri = URI.parse uri if uri.is_a?(String) + uri = parse_uri uri unless uri.scheme raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}" @@ -355,6 +344,20 @@ def close_all private + def parse_uri(source_uri) + return source_uri unless source_uri.is_a?(String) + + # It should also be considered that source_uri may already be + # a valid URI with escaped characters. e.g. "{DESede}" is encoded + # as "%7BDESede%7D". If this is escaped again the percentage + # symbols will be escaped. + begin + URI.parse(source_uri) + rescue + URI.parse(URI::DEFAULT_PARSER.escape(source_uri)) + end + end + def proxy_for(proxy, uri) Gem::Request.proxy_uri(proxy || Gem::Request.get_proxy_from_env(uri.scheme)) end From ea701d220e2f59a253bf09a3da72a1b5dccff4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 2 Dec 2019 21:01:54 +0100 Subject: [PATCH 11/15] Remove dummy rescue & re-raise --- lib/rubygems/remote_fetcher.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 23daccc9eff2..b41ed6353014 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -260,8 +260,6 @@ def fetch_path(uri, mtime = nil, head = false) end data - rescue FetchError - raise rescue Timeout::Error raise UnknownHostError.new('timed out', uri.to_s) rescue IOError, SocketError, SystemCallError, From eabd27e220452d75a405b8e521204788a0fbd957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 3 Dec 2019 11:39:49 +0100 Subject: [PATCH 12/15] Allow passing URIs to FetchError And pass them. Since we already have URIs in most places, it's better to reuse them to converting them to strings and then reparsing them to build the same URI object. --- lib/rubygems/remote_fetcher.rb | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index b41ed6353014..da56029aef1e 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -30,13 +30,18 @@ class FetchError < Gem::Exception def initialize(message, uri) super message - begin - uri = URI.parse(uri) - uri.password = 'REDACTED' if uri.password - @uri = uri.to_s - rescue URI::InvalidURIError - @uri = uri + + if uri.is_a?(String) + begin + uri = URI.parse(uri) + rescue URI::InvalidURIError + @uri = uri + return + end end + + uri.password = 'REDACTED' if uri.password + @uri = uri.to_s end def to_s # :nodoc: @@ -107,7 +112,7 @@ def download_to_cache(dependency) spec, source = found.max_by { |(s,_)| s.version } - download spec, source.uri.to_s + download spec, source.uri end ## @@ -255,19 +260,19 @@ def fetch_path(uri, mtime = nil, head = false) begin data = Gem::Util.gunzip data rescue Zlib::GzipFile::Error - raise FetchError.new("server did not return a valid file", uri.to_s) + raise FetchError.new("server did not return a valid file", uri) end end data rescue Timeout::Error - raise UnknownHostError.new('timed out', uri.to_s) + raise UnknownHostError.new('timed out', uri) rescue IOError, SocketError, SystemCallError, *(OpenSSL::SSL::SSLError if defined?(OpenSSL)) => e if e.message =~ /getaddrinfo/ - raise UnknownHostError.new('no such name', uri.to_s) + raise UnknownHostError.new('no such name', uri) else - raise FetchError.new("#{e.class}: #{e}", uri.to_s) + raise FetchError.new("#{e.class}: #{e}", uri) end end From e6ce7b24db6cf19520863d1ee260668ead92f2f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 3 Dec 2019 11:53:52 +0100 Subject: [PATCH 13/15] Remove unnecessary namespacing --- lib/rubygems/remote_fetcher.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index da56029aef1e..1a3901597899 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -153,7 +153,7 @@ def download(spec, source_uri, install_dir = Gem.dir) remote_gem_path = source_uri + "gems/#{gem_file_name}" self.cache_update_path remote_gem_path, local_gem_path - rescue Gem::RemoteFetcher::FetchError + rescue FetchError raise if spec.original_platform == spec.platform alternate_name = "#{spec.original_name}.gem" From 361e080146d7581f975ad0b497bd6bcd5b9b7e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 3 Dec 2019 12:13:01 +0100 Subject: [PATCH 14/15] Move URI parsing to a separate class --- Manifest.txt | 1 + lib/rubygems/remote_fetcher.rb | 43 ++++++++++++++++++++-------------- lib/rubygems/uri_parser.rb | 36 ++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 lib/rubygems/uri_parser.rb diff --git a/Manifest.txt b/Manifest.txt index 7a9ebba3d6ab..a955f08f0913 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -493,6 +493,7 @@ lib/rubygems/test_utilities.rb lib/rubygems/text.rb lib/rubygems/uninstaller.rb lib/rubygems/uri_formatter.rb +lib/rubygems/uri_parser.rb lib/rubygems/user_interaction.rb lib/rubygems/util.rb lib/rubygems/util/licenses.rb diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 1a3901597899..1f8ca52789c0 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -4,6 +4,7 @@ require 'rubygems/request/connection_pools' require 'rubygems/s3_uri_signer' require 'rubygems/uri_formatter' +require 'rubygems/uri_parser' require 'rubygems/user_interaction' require 'resolv' require 'rubygems/deprecate' @@ -31,16 +32,10 @@ class FetchError < Gem::Exception def initialize(message, uri) super message - if uri.is_a?(String) - begin - uri = URI.parse(uri) - rescue URI::InvalidURIError - @uri = uri - return - end - end + uri = parse_uri(uri) + + uri.password = 'REDACTED' if uri.respond_to?(:password) && uri.password - uri.password = 'REDACTED' if uri.password @uri = uri.to_s end @@ -48,6 +43,20 @@ def to_s # :nodoc: "#{super} (#{uri})" end + private + + def parse_uri(source_uri) + return source_uri unless source_uri.is_a?(String) + + uri_parser.parse(source_uri) + end + + def uri_parser + require "uri" + + Gem::UriParser.new + end + end ## @@ -350,15 +359,13 @@ def close_all def parse_uri(source_uri) return source_uri unless source_uri.is_a?(String) - # It should also be considered that source_uri may already be - # a valid URI with escaped characters. e.g. "{DESede}" is encoded - # as "%7BDESede%7D". If this is escaped again the percentage - # symbols will be escaped. - begin - URI.parse(source_uri) - rescue - URI.parse(URI::DEFAULT_PARSER.escape(source_uri)) - end + uri_parser.parse!(source_uri) + end + + def uri_parser + require "uri" + + @uri_parser ||= Gem::UriParser.new end def proxy_for(proxy, uri) diff --git a/lib/rubygems/uri_parser.rb b/lib/rubygems/uri_parser.rb new file mode 100644 index 000000000000..5c7cabc43658 --- /dev/null +++ b/lib/rubygems/uri_parser.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +## +# The UriParser handles parsing URIs. +# + +class Gem::UriParser + + ## + # Parses the #uri, raising if it's invalid + + def parse!(uri) + raise URI::InvalidURIError unless uri + + # Always escape URI's to deal with potential spaces and such + # It should also be considered that source_uri may already be + # a valid URI with escaped characters. e.g. "{DESede}" is encoded + # as "%7BDESede%7D". If this is escaped again the percentage + # symbols will be escaped. + begin + URI.parse(uri) + rescue URI::InvalidURIError + URI.parse(URI::DEFAULT_PARSER.escape(uri)) + end + end + + ## + # Parses the #uri, returning the original uri if it's invalid + + def parse(uri) + parse!(uri) + rescue URI::InvalidURIError + uri + end + +end From c6692142814e1b01aa489d6cbba7cb86b7dbd052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 3 Dec 2019 22:27:18 +0100 Subject: [PATCH 15/15] Extract common logic to a mixin --- Manifest.txt | 1 + lib/rubygems/remote_fetcher.rb | 32 +++++--------------------------- lib/rubygems/uri_parsing.rb | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+), 27 deletions(-) create mode 100644 lib/rubygems/uri_parsing.rb diff --git a/Manifest.txt b/Manifest.txt index a955f08f0913..6f37d0aee3fc 100644 --- a/Manifest.txt +++ b/Manifest.txt @@ -494,6 +494,7 @@ lib/rubygems/text.rb lib/rubygems/uninstaller.rb lib/rubygems/uri_formatter.rb lib/rubygems/uri_parser.rb +lib/rubygems/uri_parsing.rb lib/rubygems/user_interaction.rb lib/rubygems/util.rb lib/rubygems/util/licenses.rb diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb index 1f8ca52789c0..2ed619f1bc6f 100644 --- a/lib/rubygems/remote_fetcher.rb +++ b/lib/rubygems/remote_fetcher.rb @@ -4,7 +4,7 @@ require 'rubygems/request/connection_pools' require 'rubygems/s3_uri_signer' require 'rubygems/uri_formatter' -require 'rubygems/uri_parser' +require 'rubygems/uri_parsing' require 'rubygems/user_interaction' require 'resolv' require 'rubygems/deprecate' @@ -18,12 +18,16 @@ class Gem::RemoteFetcher include Gem::UserInteraction extend Gem::Deprecate + include Gem::UriParsing + ## # A FetchError exception wraps up the various possible IO and HTTP failures # that could happen while downloading from the internet. class FetchError < Gem::Exception + include Gem::UriParsing + ## # The URI which was being accessed when the exception happened. @@ -43,20 +47,6 @@ def to_s # :nodoc: "#{super} (#{uri})" end - private - - def parse_uri(source_uri) - return source_uri unless source_uri.is_a?(String) - - uri_parser.parse(source_uri) - end - - def uri_parser - require "uri" - - Gem::UriParser.new - end - end ## @@ -356,18 +346,6 @@ def close_all private - def parse_uri(source_uri) - return source_uri unless source_uri.is_a?(String) - - uri_parser.parse!(source_uri) - end - - def uri_parser - require "uri" - - @uri_parser ||= Gem::UriParser.new - end - def proxy_for(proxy, uri) Gem::Request.proxy_uri(proxy || Gem::Request.get_proxy_from_env(uri.scheme)) end diff --git a/lib/rubygems/uri_parsing.rb b/lib/rubygems/uri_parsing.rb new file mode 100644 index 000000000000..941d7e023a8b --- /dev/null +++ b/lib/rubygems/uri_parsing.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require "rubygems/uri_parser" + +module Gem::UriParsing + + def parse_uri(source_uri) + return source_uri unless source_uri.is_a?(String) + + uri_parser.parse(source_uri) + end + + private :parse_uri + + def uri_parser + require "uri" + + Gem::UriParser.new + end + + private :uri_parser + +end