Skip to content

Commit

Permalink
Handle internationalized domain names correctly using Addressable. Cl…
Browse files Browse the repository at this point in the history
…oses #2086
  • Loading branch information
mshibuya committed Jun 11, 2019
1 parent 68d1eb8 commit 57a4a3b
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 5 deletions.
1 change: 1 addition & 0 deletions carrierwave.gemspec
Expand Up @@ -26,6 +26,7 @@ Gem::Specification.new do |s|
s.add_dependency "mini_mime", ">= 0.1.3"
s.add_dependency "image_processing", "~> 1.1"
s.add_dependency "mimemagic", ">= 0.3.0"
s.add_dependency "addressable", "~> 2.6"
if RUBY_ENGINE == 'jruby'
s.add_development_dependency 'activerecord-jdbcpostgresql-adapter'
else
Expand Down
10 changes: 5 additions & 5 deletions lib/carrierwave/downloader/base.rb
@@ -1,4 +1,5 @@
require 'open-uri'
require 'addressable'
require 'carrierwave/downloader/remote_file'

module CarrierWave
Expand Down Expand Up @@ -37,13 +38,12 @@ def download(url, remote_headers = {})
# [url (String)] The URL where the remote file is stored
#
def process_uri(uri)
URI.parse(uri)
rescue URI::InvalidURIError
uri_parts = uri.split('?')
# regexp from Ruby's URI::Parser#regexp[:UNSAFE], with [] specifically removed
encoded_uri = URI.encode(uri_parts.shift, /[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,]/)
encoded_uri = Addressable::URI.parse(uri_parts.shift).normalize.to_s
encoded_uri << '?' << URI.encode(uri_parts.join('?')) if uri_parts.any?
URI.parse(encoded_uri) rescue raise CarrierWave::DownloadError, "couldn't parse URL"
URI.parse(encoded_uri)
rescue URI::InvalidURIError, Addressable::URI::InvalidURIError
raise CarrierWave::DownloadError, "couldn't parse URL: #{uri}"
end
end
end
Expand Down
15 changes: 15 additions & 0 deletions spec/downloader/base_spec.rb
Expand Up @@ -26,6 +26,21 @@
end
end

context "with a URL with internationalized domain name" do
let(:uri) { URI.encode("http://ドメイン名例.jp/#{filename}") }
before do
stub_request(:get, 'http://xn--eckwd4c7cu47r2wf.jp/test.jpg').to_return(body: file)
end

it "converts to Punycode URI" do
expect(subject.process_uri(uri).to_s).to eq 'http://xn--eckwd4c7cu47r2wf.jp/test.jpg'
end

it "downloads a file" do
expect(subject.download(uri).file.read).to eq file
end
end

context 'with request headers' do
let(:authentication_headers) do
{
Expand Down

1 comment on commit 57a4a3b

@toshimaru
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Please sign in to comment.