Class: CarrierWave::Downloader::Base
- Inherits:
-
Object
- Object
- CarrierWave::Downloader::Base
- Defined in:
- lib/carrierwave/downloader/base.rb
Instance Attribute Summary collapse
-
#uploader ⇒ Object
readonly
Returns the value of attribute uploader.
Instance Method Summary collapse
-
#download(url, remote_headers = {}) ⇒ Object
Downloads a file from given URL and returns a RemoteFile.
-
#initialize(uploader) ⇒ Base
constructor
A new instance of Base.
-
#process_uri(uri) ⇒ Object
Processes the given URL by parsing it, and escaping if necessary.
-
#skip_ssrf_protection?(uri) ⇒ Boolean
If this returns true, SSRF protection will be bypassed.
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
#uploader ⇒ Object (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 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/carrierwave/downloader/base.rb', line 23 def download(url, remote_headers = {}) @current_download_retry_count = 0 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 if ::SsrfFilter::VERSION.to_f < 1.1 response = SsrfFilter.get(uri, headers: headers) do |req| request = req end else response = SsrfFilter.get(uri, headers: headers, request_proc: ->(req) { request = req }) do |res| res.body # ensure to read body end end response.uri = request.uri response.value end rescue StandardError => e if @current_download_retry_count < @uploader.download_retry_count @current_download_retry_count += 1 sleep @uploader.download_retry_wait_time retry else raise CarrierWave::DownloadError, "could not download file: #{e.}" end 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
64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/carrierwave/downloader/base.rb', line 64 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
95 96 97 |
# File 'lib/carrierwave/downloader/base.rb', line 95 def skip_ssrf_protection?(uri) false end |