diff --git a/lib/carrierwave/downloader/base.rb b/lib/carrierwave/downloader/base.rb index ad77e921f..12a39f228 100644 --- a/lib/carrierwave/downloader/base.rb +++ b/lib/carrierwave/downloader/base.rb @@ -31,7 +31,7 @@ def download(url, remote_headers = {}) end ## - # Processes the given URL by parsing and escaping it. Public to allow overriding. + # Processes the given URL by parsing it, and escaping if necessary. Public to allow overriding. # # === Parameters # @@ -40,8 +40,12 @@ def download(url, remote_headers = {}) def process_uri(uri) uri_parts = uri.split('?') encoded_uri = Addressable::URI.parse(uri_parts.shift).normalize.to_s - encoded_uri << '?' << Addressable::URI.encode(uri_parts.join('?')).gsub('%5B', '[').gsub('%5D', ']') if uri_parts.any? - URI.parse(encoded_uri) + query = uri_parts.any? ? "?#{uri_parts.join('?')}" : '' + begin + URI.parse("#{encoded_uri}#{query}") + rescue URI::InvalidURIError + URI.parse("#{encoded_uri}#{URI::DEFAULT_PARSER.escape(query)}") + end rescue URI::InvalidURIError, Addressable::URI::InvalidURIError raise CarrierWave::DownloadError, "couldn't parse URL: #{uri}" end diff --git a/spec/downloader/base_spec.rb b/spec/downloader/base_spec.rb index 3599352c5..3ca8a3c2a 100644 --- a/spec/downloader/base_spec.rb +++ b/spec/downloader/base_spec.rb @@ -159,6 +159,20 @@ expect(processed.to_s).to eq('http://example.com/%5D.jpg?test[]') end + it "escapes and parse unescaped characters in path" do + uri = 'http://example.com/あああ.jpg' + processed = subject.process_uri(uri) + expect(processed.class).to eq(URI::HTTP) + expect(processed.to_s).to eq('http://example.com/%E3%81%82%E3%81%82%E3%81%82.jpg') + end + + it "escapes and parse unescaped characters in query string" do + uri = 'http://example.com/?q=あああ' + processed = subject.process_uri(uri) + expect(processed.class).to eq(URI::HTTP) + expect(processed.to_s).to eq('http://example.com/?q=%E3%81%82%E3%81%82%E3%81%82') + end + it "throws an exception on bad uris" do uri = '~http:' expect { subject.process_uri(uri) }.to raise_error(CarrierWave::DownloadError)