cloudinary 1.9.1 → 1.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE/bug_report.md +42 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
- data/.github/pull_request_template.md +24 -0
- data/.gitignore +7 -1
- data/.travis.yml +15 -8
- data/CHANGELOG.md +261 -0
- data/README.md +3 -0
- data/Rakefile +3 -45
- data/cloudinary.gemspec +27 -20
- data/lib/active_storage/blob_key.rb +20 -0
- data/lib/active_storage/service/cloudinary_service.rb +249 -0
- data/lib/cloudinary.rb +53 -63
- data/lib/cloudinary/account_api.rb +231 -0
- data/lib/cloudinary/account_config.rb +30 -0
- data/lib/cloudinary/api.rb +228 -71
- data/lib/cloudinary/auth_token.rb +10 -4
- data/lib/cloudinary/base_api.rb +79 -0
- data/lib/cloudinary/base_config.rb +70 -0
- data/lib/cloudinary/cache.rb +38 -0
- data/lib/cloudinary/cache/breakpoints_cache.rb +31 -0
- data/lib/cloudinary/cache/key_value_cache_adapter.rb +25 -0
- data/lib/cloudinary/cache/rails_cache_adapter.rb +34 -0
- data/lib/cloudinary/cache/storage/rails_cache_storage.rb +5 -0
- data/lib/cloudinary/carrier_wave.rb +4 -2
- data/lib/cloudinary/carrier_wave/remote.rb +3 -2
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/{controller.rb → cloudinary_controller.rb} +3 -5
- data/lib/cloudinary/config.rb +43 -0
- data/lib/cloudinary/helper.rb +77 -7
- data/lib/cloudinary/migrator.rb +3 -1
- data/lib/cloudinary/railtie.rb +7 -3
- data/lib/cloudinary/responsive.rb +111 -0
- data/lib/cloudinary/uploader.rb +67 -15
- data/lib/cloudinary/utils.rb +324 -54
- data/lib/cloudinary/version.rb +1 -1
- data/lib/cloudinary/video_helper.rb +96 -22
- data/lib/tasks/cloudinary/fetch_assets.rake +48 -0
- data/lib/tasks/{cloudinary.rake → cloudinary/sync_static.rake} +0 -0
- data/tools/allocate_test_cloud.sh +9 -0
- data/tools/get_test_cloud.sh +9 -0
- data/tools/update_version +220 -0
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +51 -13
- data/vendor/assets/javascripts/cloudinary/jquery.fileupload.js +24 -4
- data/vendor/assets/javascripts/cloudinary/jquery.ui.widget.js +741 -561
- data/vendor/assets/javascripts/cloudinary/load-image.all.min.js +1 -1
- metadata +92 -67
- data/spec/access_control_spec.rb +0 -99
- data/spec/api_spec.rb +0 -545
- data/spec/archive_spec.rb +0 -129
- data/spec/auth_token_spec.rb +0 -79
- data/spec/cloudinary_helper_spec.rb +0 -190
- data/spec/cloudinary_spec.rb +0 -32
- data/spec/data/sync_static/app/assets/javascripts/1.coffee +0 -1
- data/spec/data/sync_static/app/assets/javascripts/1.js +0 -1
- data/spec/data/sync_static/app/assets/stylesheets/1.css +0 -3
- data/spec/docx.docx +0 -0
- data/spec/favicon.ico +0 -0
- data/spec/logo.png +0 -0
- data/spec/rake_spec.rb +0 -160
- data/spec/sample_asset_file.tsv +0 -4
- data/spec/search_spec.rb +0 -109
- data/spec/spec_helper.rb +0 -245
- data/spec/storage_spec.rb +0 -44
- data/spec/streaminig_profiles_api_spec.rb +0 -74
- data/spec/support/helpers/temp_file_helpers.rb +0 -22
- data/spec/support/shared_contexts/rake.rb +0 -19
- data/spec/uploader_spec.rb +0 -363
- data/spec/utils_methods_spec.rb +0 -54
- data/spec/utils_spec.rb +0 -906
- data/spec/video_tag_spec.rb +0 -251
- data/spec/video_url_spec.rb +0 -164
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'openssl'
|
2
4
|
if RUBY_VERSION > "2"
|
3
5
|
require "ostruct"
|
@@ -10,6 +12,7 @@ module Cloudinary
|
|
10
12
|
module AuthToken
|
11
13
|
SEPARATOR = '~'
|
12
14
|
UNSAFE = /[ "#%&\'\/:;<=>?@\[\\\]^`{\|}~]/
|
15
|
+
EMPTY_TOKEN = {}.freeze
|
13
16
|
|
14
17
|
def self.generate(options = {})
|
15
18
|
key = options[:key]
|
@@ -30,6 +33,10 @@ module Cloudinary
|
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
36
|
+
if url.blank? && acl.blank?
|
37
|
+
raise 'AuthToken must contain either an acl or a url property'
|
38
|
+
end
|
39
|
+
|
33
40
|
token = []
|
34
41
|
token << "ip=#{ip}" if ip
|
35
42
|
token << "st=#{start}" if start
|
@@ -42,12 +49,11 @@ module Cloudinary
|
|
42
49
|
"#{name}=#{token.join(SEPARATOR)}"
|
43
50
|
end
|
44
51
|
|
45
|
-
|
46
52
|
# Merge token2 to token1 returning a new
|
47
53
|
# Requires to support Ruby 1.9
|
48
54
|
def self.merge_auth_token(token1, token2)
|
49
|
-
token1 = token1 ||
|
50
|
-
token2 = token2 ||
|
55
|
+
token1 = token1 || EMPTY_TOKEN
|
56
|
+
token2 = token2 || EMPTY_TOKEN
|
51
57
|
token1 = token1.respond_to?( :to_h) ? token1.to_h : token1
|
52
58
|
token2 = token2.respond_to?( :to_h) ? token2.to_h : token2
|
53
59
|
token1.merge(token2)
|
@@ -69,4 +75,4 @@ module Cloudinary
|
|
69
75
|
OpenSSL::HMAC.hexdigest(digest, bin_key, message)
|
70
76
|
end
|
71
77
|
end
|
72
|
-
end
|
78
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require "rest_client"
|
2
|
+
require "json"
|
3
|
+
|
4
|
+
module Cloudinary::BaseApi
|
5
|
+
class Error < CloudinaryException; end
|
6
|
+
class NotFound < Error; end
|
7
|
+
class NotAllowed < Error; end
|
8
|
+
class AlreadyExists < Error; end
|
9
|
+
class RateLimited < Error; end
|
10
|
+
class BadRequest < Error; end
|
11
|
+
class GeneralError < Error; end
|
12
|
+
class AuthorizationRequired < Error; end
|
13
|
+
|
14
|
+
class Response < Hash
|
15
|
+
attr_reader :rate_limit_reset_at, :rate_limit_remaining, :rate_limit_allowed
|
16
|
+
|
17
|
+
def initialize(response=nil)
|
18
|
+
if response
|
19
|
+
# This sets the instantiated self as the response Hash
|
20
|
+
update Cloudinary::Api.parse_json_response response
|
21
|
+
|
22
|
+
@rate_limit_allowed = response.headers[:x_featureratelimit_limit].to_i if response.headers[:x_featureratelimit_limit]
|
23
|
+
@rate_limit_reset_at = Time.parse(response.headers[:x_featureratelimit_reset]) if response.headers[:x_featureratelimit_reset]
|
24
|
+
@rate_limit_remaining = response.headers[:x_featureratelimit_remaining].to_i if response.headers[:x_featureratelimit_remaining]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.extended(base)
|
30
|
+
[Error, NotFound, NotAllowed, AlreadyExists, RateLimited, BadRequest, GeneralError, AuthorizationRequired, Response].each do |constant|
|
31
|
+
base.const_set(constant.name.split("::").last, constant)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def call_json_api(method, api_url, payload, timeout, headers, proxy = nil, user = nil, password = nil)
|
36
|
+
RestClient::Request.execute(method: method,
|
37
|
+
url: api_url,
|
38
|
+
payload: payload,
|
39
|
+
timeout: timeout,
|
40
|
+
headers: headers,
|
41
|
+
proxy: proxy,
|
42
|
+
user: user,
|
43
|
+
password: password) do |response|
|
44
|
+
return Response.new(response) if response.code == 200
|
45
|
+
exception_class = case response.code
|
46
|
+
when 400 then BadRequest
|
47
|
+
when 401 then AuthorizationRequired
|
48
|
+
when 403 then NotAllowed
|
49
|
+
when 404 then NotFound
|
50
|
+
when 409 then AlreadyExists
|
51
|
+
when 420 then RateLimited
|
52
|
+
when 500 then GeneralError
|
53
|
+
else raise GeneralError.new("Server returned unexpected status code - #{response.code} - #{response.body}")
|
54
|
+
end
|
55
|
+
json = Cloudinary::Api.parse_json_response(response)
|
56
|
+
raise exception_class.new(json["error"]["message"])
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def call_cloudinary_api(method, uri, user, password, params, options, &api_url_builder)
|
63
|
+
cloudinary = options[:upload_prefix] || Cloudinary.config.upload_prefix || 'https://api.cloudinary.com'
|
64
|
+
api_url = Cloudinary::Utils.smart_escape(api_url_builder.call(cloudinary, uri).flatten.join('/'))
|
65
|
+
timeout = options[:timeout] || Cloudinary.config.timeout || 60
|
66
|
+
proxy = options[:api_proxy] || Cloudinary.config.api_proxy
|
67
|
+
|
68
|
+
headers = { "User-Agent" => Cloudinary::USER_AGENT }
|
69
|
+
|
70
|
+
if options[:content_type] == :json
|
71
|
+
payload = params.to_json
|
72
|
+
headers.merge!("Content-Type" => "application/json", "Accept" => "application/json")
|
73
|
+
else
|
74
|
+
payload = params.reject { |_, v| v.nil? || v == "" }
|
75
|
+
end
|
76
|
+
|
77
|
+
call_json_api(method, api_url, payload, timeout, headers, proxy, user, password)
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Cloudinary
|
2
|
+
module BaseConfig
|
3
|
+
def load_from_url(url)
|
4
|
+
return unless url && !url.empty?
|
5
|
+
|
6
|
+
parsed_url = URI.parse(url)
|
7
|
+
scheme = parsed_url.scheme.to_s.downcase
|
8
|
+
|
9
|
+
if expected_scheme != scheme
|
10
|
+
raise(CloudinaryException,
|
11
|
+
"Invalid #{env_url} scheme. Expecting to start with '#{expected_scheme}://'")
|
12
|
+
end
|
13
|
+
|
14
|
+
update(config_from_parsed_url(parsed_url))
|
15
|
+
setup_from_parsed_url(parsed_url)
|
16
|
+
end
|
17
|
+
|
18
|
+
def update(new_config = {})
|
19
|
+
new_config.each{ |k,v| public_send(:"#{k}=", v) unless v.nil?}
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_config_from_env
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def config_from_parsed_url(parsed_url)
|
29
|
+
raise NotImplementedError
|
30
|
+
end
|
31
|
+
|
32
|
+
def env_url
|
33
|
+
raise NotImplementedError
|
34
|
+
end
|
35
|
+
|
36
|
+
def expected_scheme
|
37
|
+
raise NotImplementedError
|
38
|
+
end
|
39
|
+
|
40
|
+
def put_nested_key(key, value)
|
41
|
+
chain = key.split(/[\[\]]+/).reject(&:empty?)
|
42
|
+
outer = self
|
43
|
+
lastKey = chain.pop
|
44
|
+
chain.each do |innerKey|
|
45
|
+
inner = outer[innerKey]
|
46
|
+
if inner.nil?
|
47
|
+
inner = OpenStruct.new
|
48
|
+
outer[innerKey] = inner
|
49
|
+
end
|
50
|
+
outer = inner
|
51
|
+
end
|
52
|
+
outer[lastKey] = value
|
53
|
+
end
|
54
|
+
|
55
|
+
def is_nested_key?(key)
|
56
|
+
/\w+\[\w+\]/ =~ key
|
57
|
+
end
|
58
|
+
|
59
|
+
def setup_from_parsed_url(parsed_url)
|
60
|
+
parsed_url.query.to_s.split("&").each do |param|
|
61
|
+
key, value = param.split("=")
|
62
|
+
if is_nested_key? key
|
63
|
+
put_nested_key key, value
|
64
|
+
else
|
65
|
+
update(key => Utils.smart_unescape(value))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
3
|
+
module Cloudinary
|
4
|
+
module Cache
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_accessor :storage
|
8
|
+
|
9
|
+
def get(public_id, options)
|
10
|
+
if block_given?
|
11
|
+
storage.read(generate_cache_key(public_id, options)) {yield}
|
12
|
+
else
|
13
|
+
storage.read(generate_cache_key(public_id, options))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def set(public_id, options, value)
|
18
|
+
storage.write(generate_cache_key(public_id, options), value)
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method :fetch, :get
|
22
|
+
|
23
|
+
def flush_all
|
24
|
+
storage.clear
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def generate_cache_key(public_id, options)
|
30
|
+
type = options[:type] || "upload"
|
31
|
+
resource_type = options[:resource_type] || "image"
|
32
|
+
transformation = Cloudinary::Utils.generate_transformation_string options.clone
|
33
|
+
format = options[:format]
|
34
|
+
Digest::SHA1.hexdigest [public_id, type, resource_type, transformation, format].reject(&:blank?).join('/')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Cloudinary::Cache
|
2
|
+
class BreakpointsCache
|
3
|
+
attr_accessor :adapter
|
4
|
+
|
5
|
+
def set(public_id, options, value)
|
6
|
+
upload_type, resource_type, transformation, format = options_to_parameters(options)
|
7
|
+
@adapter.set(public_id, upload_type, resource_type, transformation, format, value)
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch(public_id, options)
|
12
|
+
upload_type, resource_type, transformation, format = options_to_parameters(options)
|
13
|
+
@adapter.set(public_id, upload_type, resource_type, transformation, format, &Proc.new)
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(public_id, options)
|
18
|
+
upload_type, resource_type, transformation, format = options_to_parameters(options)
|
19
|
+
@adapter.get(public_id, upload_type, resource_type, transformation, format)
|
20
|
+
end
|
21
|
+
|
22
|
+
def options_to_parameters(options)
|
23
|
+
options = Cloudinary::Utils.symbolize_keys options
|
24
|
+
transformation = Cloudinary::Utils.generate_transformation_string(options)
|
25
|
+
upload_type = options[:type] || 'upload'
|
26
|
+
resource_type = options[:resource_type] || 'image'
|
27
|
+
format = options[:format] || ""
|
28
|
+
[upload_type, resource_type, transformation, format]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'digest'
|
2
|
+
module Cloudinary::Cache
|
3
|
+
class KeyValueCacheAdapter < CacheAdapter
|
4
|
+
def get(public_id, type, resource_type, transformation, format)
|
5
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
6
|
+
@storage.get(key)
|
7
|
+
end
|
8
|
+
|
9
|
+
def set(public_id, type, resource_type, transformation, format, value)
|
10
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
11
|
+
@storage.set(key, value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def flush_all()
|
15
|
+
@storage.flush_all()
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def generate_cache_key(public_id, type, resource_type, transformation, format)
|
21
|
+
Digest::SHA1.hexdigest [public_id, type, resource_type, transformation, format].reject(&:blank?)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Cloudinary::Cache
|
2
|
+
class RailsCacheAdapter < CacheAdapter
|
3
|
+
|
4
|
+
def flush_all
|
5
|
+
end
|
6
|
+
|
7
|
+
def get(public_id, type, resource_type, transformation, format)
|
8
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
9
|
+
Rails.cache.read(key)
|
10
|
+
end
|
11
|
+
|
12
|
+
def init
|
13
|
+
unless defined? Rails
|
14
|
+
raise CloudinaryException.new "Rails is required in order to use RailsCacheAdapter"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def set(public_id, type, resource_type, transformation, format, value)
|
19
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
20
|
+
Rails.cache.write(key, value)
|
21
|
+
end
|
22
|
+
|
23
|
+
def fetch(public_id, type, resource_type, transformation, format)
|
24
|
+
key = generate_cache_key(public_id, type, resource_type, transformation, format)
|
25
|
+
Rails.cache.fetch(key, &Proc.new)
|
26
|
+
end
|
27
|
+
private
|
28
|
+
|
29
|
+
def generate_cache_key(public_id, type, resource_type, transformation, format)
|
30
|
+
Digest::SHA1.hexdigest [public_id, type, resource_type, transformation, format].reject(&:blank?)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -3,14 +3,16 @@ require 'cloudinary/carrier_wave/process'
|
|
3
3
|
require 'cloudinary/carrier_wave/error'
|
4
4
|
require 'cloudinary/carrier_wave/remote'
|
5
5
|
require 'cloudinary/carrier_wave/preloaded'
|
6
|
-
require 'cloudinary/carrier_wave/storage'
|
6
|
+
require 'cloudinary/carrier_wave/storage' if defined?(::CarrierWave) # HACK
|
7
7
|
|
8
8
|
module Cloudinary::CarrierWave
|
9
9
|
|
10
10
|
def self.included(base)
|
11
11
|
base.storage Cloudinary::CarrierWave::Storage
|
12
|
+
base.cache_storage = :file if base.cache_storage.blank?
|
12
13
|
base.extend ClassMethods
|
13
|
-
base.class_attribute :
|
14
|
+
base.class_attribute :metadata
|
15
|
+
base.class_attribute :storage_type, instance_reader: false
|
14
16
|
override_in_versions(base, :blank?, :full_public_id, :my_public_id, :all_versions_processors, :stored_version)
|
15
17
|
end
|
16
18
|
|
@@ -1,10 +1,11 @@
|
|
1
1
|
module Cloudinary::CarrierWave
|
2
2
|
def download!(uri, *args)
|
3
|
-
return super
|
3
|
+
return super unless self.cloudinary_should_handle_remote?
|
4
4
|
if respond_to?(:process_uri)
|
5
5
|
uri = process_uri(uri)
|
6
6
|
else # Backward compatibility with old CarrierWave
|
7
|
-
|
7
|
+
remote_url_unsafe_chars = /([^a-zA-Z0-9_.\-\/:?&=]+)/ # In addition allow query string characters: "?","&" and "="
|
8
|
+
uri = URI.parse(Cloudinary::Utils.smart_escape(Cloudinary::Utils.smart_unescape(uri), remote_url_unsafe_chars))
|
8
9
|
end
|
9
10
|
return if uri.to_s.blank?
|
10
11
|
self.original_filename = @cache_id = @filename = File.basename(uri.path).gsub(/[^a-zA-Z0-9\.\-\+_]/, '')
|
@@ -1,7 +1,8 @@
|
|
1
1
|
class Cloudinary::CarrierWave::Storage < ::CarrierWave::Storage::Abstract
|
2
2
|
|
3
3
|
def store!(file)
|
4
|
-
return
|
4
|
+
return unless uploader.enable_processing
|
5
|
+
|
5
6
|
if uploader.is_main_uploader?
|
6
7
|
case file
|
7
8
|
when Cloudinary::CarrierWave::PreloadedCloudinaryFile
|
@@ -1,13 +1,11 @@
|
|
1
|
-
module CloudinaryController
|
1
|
+
module Cloudinary::CloudinaryController
|
2
2
|
protected
|
3
|
-
|
3
|
+
|
4
4
|
def valid_cloudinary_response?
|
5
5
|
received_signature = request.query_parameters[:signature]
|
6
6
|
calculated_signature = Cloudinary::Utils.api_sign_request(
|
7
7
|
request.query_parameters.select{|key, value| [:public_id, :version].include?(key.to_sym)},
|
8
8
|
Cloudinary.config.api_secret)
|
9
9
|
return received_signature == calculated_signature
|
10
|
-
end
|
10
|
+
end
|
11
11
|
end
|
12
|
-
|
13
|
-
ActionController::Base.send :include, CloudinaryController
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Cloudinary
|
2
|
+
module Config
|
3
|
+
include BaseConfig
|
4
|
+
|
5
|
+
ENV_URL = "CLOUDINARY_URL"
|
6
|
+
SCHEME = "cloudinary"
|
7
|
+
|
8
|
+
def load_config_from_env
|
9
|
+
if ENV["CLOUDINARY_CLOUD_NAME"]
|
10
|
+
config_keys = ENV.keys.select! { |key| key.start_with? "CLOUDINARY_" }
|
11
|
+
config_keys -= ["CLOUDINARY_URL"] # ignore it when explicit options are passed
|
12
|
+
config_keys.each do |full_key|
|
13
|
+
conf_key = full_key["CLOUDINARY_".length..-1].downcase # convert "CLOUDINARY_CONFIG_NAME" to "config_name"
|
14
|
+
conf_val = ENV[full_key]
|
15
|
+
conf_val = conf_val == 'true' if %w[true false].include?(conf_val) # cast relevant boolean values
|
16
|
+
update(conf_key => conf_val)
|
17
|
+
end
|
18
|
+
elsif ENV[ENV_URL]
|
19
|
+
load_from_url(ENV[ENV_URL])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def env_url
|
26
|
+
ENV_URL
|
27
|
+
end
|
28
|
+
|
29
|
+
def expected_scheme
|
30
|
+
SCHEME
|
31
|
+
end
|
32
|
+
|
33
|
+
def config_from_parsed_url(parsed_url)
|
34
|
+
{
|
35
|
+
"cloud_name" => parsed_url.host,
|
36
|
+
"api_key" => parsed_url.user,
|
37
|
+
"api_secret" => parsed_url.password,
|
38
|
+
"private_cdn" => !parsed_url.path.blank?,
|
39
|
+
"secure_distribution" => parsed_url.path[1..-1]
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|