Class: CarrierWave::Downloader::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/carrierwave/downloader/base.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uploader) ⇒ Base

Returns a new instance of Base.


11
12
13
# File 'lib/carrierwave/downloader/base.rb', line 11

def initialize(uploader)
  @uploader = uploader
end

Instance Attribute Details

#uploaderObject (readonly)

Returns the value of attribute uploader


9
10
11
# File 'lib/carrierwave/downloader/base.rb', line 9

def uploader
  @uploader
end

Instance Method Details

#download(url, remote_headers = {}) ⇒ Object

Downloads a file from given URL and returns a RemoteFile.

Parameters

url (String)

The URL where the remote file is stored

remote_headers (Hash)

Request headers


23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/carrierwave/downloader/base.rb', line 23

def download(url, remote_headers = {})
  headers = remote_headers.
    reverse_merge('User-Agent' => "CarrierWave/#{CarrierWave::VERSION}")
  uri = process_uri(url.to_s)
  begin
    if skip_ssrf_protection?(uri)
      response = OpenURI.open_uri(process_uri(url.to_s), headers)
    else
      request = nil
      response = SsrfFilter.get(uri, headers: headers) do |req|
        request = req
      end
      response.uri = request.uri
      response.value
    end
  rescue StandardError => e
    raise CarrierWave::DownloadError, "could not download file: #{e.message}"
  end
  CarrierWave::Downloader::RemoteFile.new(response)
end

#process_uri(uri) ⇒ Object

Processes the given URL by parsing it, and escaping if necessary. Public to allow overriding.

Parameters

url (String)

The URL where the remote file is stored


51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/carrierwave/downloader/base.rb', line 51

def process_uri(uri)
  uri_parts = uri.split('?')
  encoded_uri = Addressable::URI.parse(uri_parts.shift).normalize.to_s
  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

#skip_ssrf_protection?(uri) ⇒ Boolean

If this returns true, SSRF protection will be bypassed. You can override this if you want to allow accessing specific local URIs that are not SSRF exploitable.

Parameters

uri (URI)

The URI where the remote file is stored

Examples

class CarrierWave::Downloader::CustomDownloader < CarrierWave::Downloader::Base
  def skip_ssrf_protection?(uri)
    uri.hostname == 'localhost' && uri.port == 80
  end
end

my_uploader.downloader = CarrierWave::Downloader::CustomDownloader

Returns:

  • (Boolean)

82
83
84
# File 'lib/carrierwave/downloader/base.rb', line 82

def skip_ssrf_protection?(uri)
  false
end