Class: CarrierWave::Downloader::Base
- Inherits:
-
Object
- Object
- CarrierWave::Downloader::Base
- Includes:
- Utilities::Uri
- Defined in:
- lib/carrierwave/downloader/base.rb
Constant Summary
Constants included from Utilities::Uri
Utilities::Uri::NON_ASCII, Utilities::Uri::PATH_SAFE, Utilities::Uri::PATH_UNSAFE
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(source) ⇒ 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.
13 14 15 |
# File 'lib/carrierwave/downloader/base.rb', line 13 def initialize(uploader) @uploader = uploader end |
Instance Attribute Details
#uploader ⇒ Object (readonly)
Returns the value of attribute uploader.
11 12 13 |
# File 'lib/carrierwave/downloader/base.rb', line 11 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
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 56 57 |
# File 'lib/carrierwave/downloader/base.rb', line 25 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(source) ⇒ 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
66 67 68 69 70 71 72 73 74 75 76 |
# File 'lib/carrierwave/downloader/base.rb', line 66 def process_uri(source) uri = Addressable::URI.parse(source) uri.host = uri.normalized_host # Perform decode first, as the path is likely to be already encoded uri.path = encode_path(decode_uri(uri.path)) if uri.path =~ CarrierWave::Utilities::Uri::PATH_UNSAFE uri.query = encode_non_ascii(uri.query) if uri.query uri.fragment = encode_non_ascii(uri.fragment) if uri.fragment URI.parse(uri.to_s) rescue URI::InvalidURIError, Addressable::URI::InvalidURIError raise CarrierWave::DownloadError, "couldn't parse URL: #{source}" 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
96 97 98 |
# File 'lib/carrierwave/downloader/base.rb', line 96 def skip_ssrf_protection?(uri) @uploader.skip_ssrf_protection end |