cloudinary 1.29.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGELOG.md +33 -0
- data/README.md +5 -3
- data/cloudinary.gemspec +21 -51
- data/lib/active_storage/service/cloudinary_service.rb +4 -2
- data/lib/cloudinary/account_api.rb +21 -8
- data/lib/cloudinary/analytics.rb +157 -0
- data/lib/cloudinary/api.rb +24 -4
- data/lib/cloudinary/auth_token.rb +1 -5
- data/lib/cloudinary/base_api.rb +36 -31
- data/lib/cloudinary/carrier_wave/storage.rb +2 -1
- data/lib/cloudinary/carrier_wave.rb +0 -5
- data/lib/cloudinary/helper.rb +2 -10
- data/lib/cloudinary/migrator.rb +70 -71
- data/lib/cloudinary/uploader.rb +70 -90
- data/lib/cloudinary/utils.rb +31 -54
- data/lib/cloudinary/version.rb +1 -1
- data/lib/cloudinary.rb +3 -9
- data/lib/tasks/cloudinary/fetch_assets.rake +9 -3
- data/vendor/assets/javascripts/cloudinary/jquery.cloudinary.js +3 -3
- metadata +164 -38
- data/lib/cloudinary/ostruct2.rb +0 -284
data/lib/cloudinary/migrator.rb
CHANGED
@@ -6,29 +6,29 @@ class Cloudinary::Migrator
|
|
6
6
|
attr_reader :db
|
7
7
|
attr_reader :work, :results, :mutex
|
8
8
|
attr_reader :extra_options
|
9
|
-
|
10
|
-
|
9
|
+
|
10
|
+
|
11
11
|
@@init = false
|
12
12
|
def self.init
|
13
13
|
return if @@init
|
14
14
|
@@init = true
|
15
15
|
|
16
|
-
begin
|
16
|
+
begin
|
17
17
|
require 'sqlite3'
|
18
18
|
rescue LoadError
|
19
|
-
raise "Please add sqlite3 to your Gemfile"
|
19
|
+
raise "Please add sqlite3 to your Gemfile"
|
20
20
|
end
|
21
21
|
require 'tempfile'
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
def json_decode(str)
|
25
25
|
Cloudinary::Utils.json_decode(str)
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
def initialize(options={})
|
29
29
|
self.class.init
|
30
|
-
|
31
|
-
options[:db_file] = "tmp/migration#{$$}.db" if options[:private_database] && !options[:db_file]
|
30
|
+
|
31
|
+
options[:db_file] = "tmp/migration#{$$}.db" if options[:private_database] && !options[:db_file]
|
32
32
|
@dbfile = options[:db_file] || "tmp/migration.db"
|
33
33
|
FileUtils.mkdir_p(File.dirname(@dbfile))
|
34
34
|
@db = SQLite3::Database.new @dbfile, :results_as_hash=>true
|
@@ -37,7 +37,6 @@ class Cloudinary::Migrator
|
|
37
37
|
@debug = options[:debug] || false
|
38
38
|
@ignore_duplicates = options[:ignore_duplicates]
|
39
39
|
@threads = [options[:threads] || 10, 100].min
|
40
|
-
@threads = 1 if RUBY_VERSION < "1.9"
|
41
40
|
@extra_options = {:api_key=>options[:api_key], :api_secret=>options[:api_secret]}
|
42
41
|
@delete_after_done = options[:delete_after_done] || options[:private_database]
|
43
42
|
@max_processing = @threads * 10
|
@@ -77,7 +76,7 @@ class Cloudinary::Migrator
|
|
77
76
|
@db.execute("delete from queue")
|
78
77
|
end
|
79
78
|
end
|
80
|
-
|
79
|
+
|
81
80
|
def register_retrieve(&block)
|
82
81
|
@retrieve = block
|
83
82
|
end
|
@@ -85,26 +84,26 @@ class Cloudinary::Migrator
|
|
85
84
|
def register_complete(&block)
|
86
85
|
@complete = block
|
87
86
|
end
|
88
|
-
|
89
|
-
def process(options={})
|
87
|
+
|
88
|
+
def process(options={})
|
90
89
|
raise CloudinaryException, "url not given and no retrieve callback given" if options[:url].nil? && self.retrieve.nil?
|
91
90
|
raise CloudinaryException, "id not given and retrieve or complete callback given" if options[:id].nil? && (!self.retrieve.nil? || !self.complete.nil?)
|
92
91
|
|
93
92
|
debug("Process: #{options.inspect}")
|
94
93
|
start
|
95
|
-
process_results
|
94
|
+
process_results
|
96
95
|
wait_for_queue
|
97
96
|
options = options.dup
|
98
97
|
id = options.delete(:id)
|
99
98
|
url = options.delete(:url)
|
100
99
|
public_id = options.delete(:public_id)
|
101
100
|
row = {
|
102
|
-
"internal_id"=>id,
|
103
|
-
"url"=>url,
|
104
|
-
"public_id"=>public_id,
|
101
|
+
"internal_id"=>id,
|
102
|
+
"url"=>url,
|
103
|
+
"public_id"=>public_id,
|
105
104
|
"metadata"=>options.to_json,
|
106
|
-
"status"=>"processing"
|
107
|
-
}
|
105
|
+
"status"=>"processing"
|
106
|
+
}
|
108
107
|
begin
|
109
108
|
insert_row(row)
|
110
109
|
add_to_work_queue(row)
|
@@ -112,7 +111,7 @@ class Cloudinary::Migrator
|
|
112
111
|
raise if !@ignore_duplicates
|
113
112
|
end
|
114
113
|
end
|
115
|
-
|
114
|
+
|
116
115
|
def done
|
117
116
|
start
|
118
117
|
process_all_pending
|
@@ -122,37 +121,37 @@ class Cloudinary::Migrator
|
|
122
121
|
@db.close
|
123
122
|
File.delete(@dbfile) if @delete_after_done
|
124
123
|
end
|
125
|
-
|
124
|
+
|
126
125
|
def max_given_id
|
127
126
|
db.get_first_value("select max(internal_id) from queue").to_i
|
128
127
|
end
|
129
|
-
|
128
|
+
|
130
129
|
def close_if_needed(file)
|
131
130
|
if file.nil?
|
132
131
|
# Do nothing.
|
133
|
-
elsif file.respond_to?(:close!)
|
134
|
-
file.close!
|
132
|
+
elsif file.respond_to?(:close!)
|
133
|
+
file.close!
|
135
134
|
elsif file.respond_to?(:close)
|
136
135
|
file.close
|
137
136
|
end
|
138
137
|
rescue
|
139
138
|
# Ignore errors in closing files
|
140
|
-
end
|
139
|
+
end
|
141
140
|
|
142
|
-
def temporary_file(data, filename)
|
143
|
-
file =
|
141
|
+
def temporary_file(data, filename)
|
142
|
+
file = Tempfile.new('cloudinary', :encoding => 'ascii-8bit')
|
144
143
|
file.unlink
|
145
144
|
file.write(data)
|
146
145
|
file.rewind
|
147
|
-
# Tempfile return path == nil after unlink, which break rest-client
|
146
|
+
# Tempfile return path == nil after unlink, which break rest-client
|
148
147
|
class << file
|
149
148
|
attr_accessor :original_filename
|
150
149
|
def content_type
|
151
|
-
"application/octet-stream"
|
150
|
+
"application/octet-stream"
|
152
151
|
end
|
153
152
|
end
|
154
153
|
file.original_filename = filename
|
155
|
-
file
|
154
|
+
file
|
156
155
|
end
|
157
156
|
|
158
157
|
private
|
@@ -160,21 +159,21 @@ class Cloudinary::Migrator
|
|
160
159
|
def update_all(values)
|
161
160
|
@db.execute("update queue set #{values.keys.map{|key| "#{key}=?"}.join(",")}", *values.values)
|
162
161
|
end
|
163
|
-
|
164
|
-
def update_row(row, values)
|
162
|
+
|
163
|
+
def update_row(row, values)
|
165
164
|
values.merge!("updated_at"=>Time.now.to_i)
|
166
165
|
query = ["update queue set #{values.keys.map{|key| "#{key}=?"}.join(",")} where id=?"] + values.values + [row["id"]]
|
167
166
|
@db.execute(*query)
|
168
167
|
values.each{|key, value| row[key.to_s] = value}
|
169
|
-
row
|
168
|
+
row
|
170
169
|
end
|
171
|
-
|
170
|
+
|
172
171
|
def insert_row(values)
|
173
172
|
values.merge!("updated_at"=>Time.now.to_i)
|
174
173
|
@db.execute("insert into queue (#{values.keys.join(",")}) values (#{values.keys.map{"?"}.join(",")})", *values.values)
|
175
174
|
values["id"] = @db.last_insert_row_id
|
176
175
|
end
|
177
|
-
|
176
|
+
|
178
177
|
def refill_queue(last_id)
|
179
178
|
@db.execute("select * from queue where status in ('error', 'processing') and id > ? limit ?", last_id, 10000) do
|
180
179
|
|row|
|
@@ -183,25 +182,25 @@ class Cloudinary::Migrator
|
|
183
182
|
add_to_work_queue(row)
|
184
183
|
end
|
185
184
|
last_id
|
186
|
-
end
|
185
|
+
end
|
187
186
|
|
188
187
|
def process_results
|
189
188
|
while self.results.length > 0
|
190
189
|
row = self.results.pop
|
191
|
-
result = json_decode(row["result"])
|
190
|
+
result = json_decode(row["result"])
|
192
191
|
debug("Done ID=#{row['internal_id']}, result=#{result.inspect}")
|
193
|
-
complete.call(row["internal_id"], result) if complete
|
194
|
-
if result["error"]
|
192
|
+
complete.call(row["internal_id"], result) if complete
|
193
|
+
if result["error"]
|
195
194
|
status = case result["error"]["http_code"]
|
196
195
|
when 400, 404 then "fatal" # Problematic request. Not a server problem.
|
197
196
|
else "error"
|
198
197
|
end
|
199
198
|
else
|
200
199
|
status = "completed"
|
201
|
-
end
|
200
|
+
end
|
202
201
|
updates = {:status=>status, :result=>row["result"]}
|
203
202
|
updates["public_id"] = result["public_id"] if result["public_id"] && !row["public_id"]
|
204
|
-
begin
|
203
|
+
begin
|
205
204
|
update_row(row, updates)
|
206
205
|
rescue SQLite3::ConstraintException
|
207
206
|
updates = {:status=>"error", :result=>{:error=>{:message=>"public_id already exists"}}.to_json}
|
@@ -219,16 +218,16 @@ class Cloudinary::Migrator
|
|
219
218
|
raise if retry_count > tries
|
220
219
|
sleep rand * 3
|
221
220
|
retry
|
222
|
-
end
|
221
|
+
end
|
223
222
|
end
|
224
|
-
|
223
|
+
|
225
224
|
def start
|
226
225
|
return if @started
|
227
226
|
@started = true
|
228
227
|
@terminate = false
|
229
|
-
|
228
|
+
|
230
229
|
self.work.clear
|
231
|
-
|
230
|
+
|
232
231
|
main = self
|
233
232
|
Thread.abort_on_exception = true
|
234
233
|
1.upto(@threads) do
|
@@ -251,8 +250,8 @@ class Cloudinary::Migrator
|
|
251
250
|
elsif defined?(::CarrierWave) && defined?(Cloudinary::CarrierWave) && data.is_a?(Cloudinary::CarrierWave)
|
252
251
|
cw = true
|
253
252
|
begin
|
254
|
-
data.model.save!
|
255
|
-
rescue Cloudinary::CarrierWave::UploadError
|
253
|
+
data.model.save!
|
254
|
+
rescue Cloudinary::CarrierWave::UploadError
|
256
255
|
# upload errors will be handled by the result values.
|
257
256
|
end
|
258
257
|
result = data.metadata
|
@@ -264,22 +263,22 @@ class Cloudinary::Migrator
|
|
264
263
|
elsif data.match(/^https?:/)
|
265
264
|
url = data
|
266
265
|
else
|
267
|
-
file = main.temporary_file(data, row["public_id"] || "cloudinaryfile")
|
266
|
+
file = main.temporary_file(data, row["public_id"] || "cloudinaryfile")
|
268
267
|
end
|
269
268
|
end
|
270
|
-
|
269
|
+
|
271
270
|
if url || file
|
272
271
|
options = main.extra_options.merge(:public_id=>row["public_id"])
|
273
272
|
json_decode(row["metadata"]).each do
|
274
273
|
|key, value|
|
275
274
|
options[key.to_sym] = value
|
276
275
|
end
|
277
|
-
|
276
|
+
|
278
277
|
result = Cloudinary::Uploader.upload(url || file, options.merge(:return_error=>true)) || ({:error=>{:message=>"Received nil from uploader!"}})
|
279
278
|
elsif cw
|
280
279
|
result ||= {"status" => "saved"}
|
281
280
|
else
|
282
|
-
result = {"error" => {"message" => "Empty data and url", "http_code"=>404}}
|
281
|
+
result = {"error" => {"message" => "Empty data and url", "http_code"=>404}}
|
283
282
|
end
|
284
283
|
main.results << {"id"=>row["id"], "internal_id"=>row["internal_id"], "result"=>result.to_json}
|
285
284
|
rescue => e
|
@@ -289,14 +288,14 @@ class Cloudinary::Migrator
|
|
289
288
|
ensure
|
290
289
|
main.mutex.synchronize{main.in_process -= 1}
|
291
290
|
main.close_if_needed(file)
|
292
|
-
end
|
291
|
+
end
|
293
292
|
end
|
294
293
|
end
|
295
|
-
end
|
296
|
-
|
294
|
+
end
|
295
|
+
|
297
296
|
retry_previous_queue # Retry all work from previous iteration before we start processing this one.
|
298
297
|
end
|
299
|
-
|
298
|
+
|
300
299
|
def debug(message)
|
301
300
|
if @debug
|
302
301
|
mutex.synchronize{
|
@@ -310,60 +309,60 @@ class Cloudinary::Migrator
|
|
310
309
|
begin
|
311
310
|
prev_last_id, last_id = last_id, refill_queue(last_id)
|
312
311
|
end while last_id > prev_last_id
|
313
|
-
process_results
|
312
|
+
process_results
|
314
313
|
end
|
315
|
-
|
314
|
+
|
316
315
|
def process_all_pending
|
317
316
|
# Waiting for work to finish. While we are at it, process results.
|
318
|
-
while self.in_process > 0
|
317
|
+
while self.in_process > 0
|
319
318
|
process_results
|
320
319
|
sleep 0.1
|
321
320
|
end
|
322
321
|
# Make sure we processed all the results
|
323
322
|
process_results
|
324
323
|
end
|
325
|
-
|
324
|
+
|
326
325
|
def add_to_work_queue(row)
|
327
326
|
self.work << row
|
328
327
|
mutex.synchronize{self.in_process += 1}
|
329
328
|
end
|
330
|
-
|
329
|
+
|
331
330
|
def wait_for_queue
|
332
331
|
# Waiting f
|
333
332
|
while self.work.length > @max_processing
|
334
|
-
process_results
|
333
|
+
process_results
|
335
334
|
sleep 0.1
|
336
|
-
end
|
335
|
+
end
|
337
336
|
end
|
338
337
|
|
339
|
-
def self.sample
|
338
|
+
def self.sample
|
340
339
|
migrator = Cloudinary::Migrator.new(
|
341
|
-
:retrieve=>proc{|id| Post.find(id).data},
|
340
|
+
:retrieve=>proc{|id| Post.find(id).data},
|
342
341
|
:complete=>proc{|id, result| a}
|
343
342
|
)
|
344
|
-
|
343
|
+
|
345
344
|
Post.find_each(:conditions=>["id > ?", migrator.max_given_id], :select=>"id") do
|
346
345
|
|post|
|
347
346
|
migrator.process(:id=>post.id, :public_id=>"post_#{post.id}")
|
348
347
|
end
|
349
348
|
migrator.done
|
350
|
-
end
|
351
|
-
|
352
|
-
def self.test
|
349
|
+
end
|
350
|
+
|
351
|
+
def self.test
|
353
352
|
posts = {}
|
354
|
-
done = {}
|
353
|
+
done = {}
|
355
354
|
migrator = Cloudinary::Migrator.new(
|
356
|
-
:retrieve=>proc{|id| posts[id]},
|
355
|
+
:retrieve=>proc{|id| posts[id]},
|
357
356
|
:complete=>proc{|id, result| $stderr.print "done #{id} #{result}\n"; done[id] = result}
|
358
357
|
)
|
359
358
|
start = migrator.max_given_id + 1
|
360
359
|
(start..1000).each{|i| posts[i] = "hello#{i}"}
|
361
|
-
|
360
|
+
|
362
361
|
posts.each do
|
363
362
|
|id, data|
|
364
363
|
migrator.process(:id=>id, :public_id=>"post_#{id}")
|
365
364
|
end
|
366
365
|
migrator.done
|
367
366
|
pp [done.length, start]
|
368
|
-
end
|
367
|
+
end
|
369
368
|
end
|
data/lib/cloudinary/uploader.rb
CHANGED
@@ -1,83 +1,53 @@
|
|
1
1
|
# Copyright Cloudinary
|
2
|
-
require '
|
2
|
+
require 'faraday'
|
3
3
|
require 'json'
|
4
4
|
require 'cloudinary/cache'
|
5
5
|
|
6
6
|
class Cloudinary::Uploader
|
7
|
-
|
8
|
-
|
9
|
-
# @deprecated use {Cloudinary::Utils.build_eager} instead
|
10
|
-
def self.build_eager(eager)
|
11
|
-
Cloudinary::Utils.build_eager(eager)
|
12
|
-
end
|
13
|
-
|
14
|
-
# @private
|
15
|
-
def self.build_upload_params(options)
|
7
|
+
@adapter = nil
|
8
|
+
def self.build_upload_params(options, as_bool = false)
|
16
9
|
#symbolize keys
|
17
10
|
options = options.clone
|
18
11
|
options.keys.each { |key| options[key.to_sym] = options.delete(key) if key.is_a?(String) }
|
19
12
|
|
20
13
|
params = {
|
21
|
-
:access_control
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:custom_coordinates => Cloudinary::Utils.encode_double_array(options[:custom_coordinates]),
|
35
|
-
:detection => options[:detection],
|
36
|
-
:discard_original_filename => Cloudinary::Utils.as_safe_bool(options[:discard_original_filename]),
|
37
|
-
:display_name => options[:display_name],
|
38
|
-
:eager => Cloudinary::Utils.build_eager(options[:eager]),
|
39
|
-
:eager_async => Cloudinary::Utils.as_safe_bool(options[:eager_async]),
|
40
|
-
:eager_notification_url => options[:eager_notification_url],
|
41
|
-
:exif => Cloudinary::Utils.as_safe_bool(options[:exif]),
|
42
|
-
:eval => options[:eval],
|
43
|
-
:on_success => options[:on_success],
|
44
|
-
:face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
|
45
|
-
:faces => Cloudinary::Utils.as_safe_bool(options[:faces]),
|
46
|
-
:folder => options[:folder],
|
47
|
-
:format => options[:format],
|
48
|
-
:filename_override => options[:filename_override],
|
49
|
-
:headers => build_custom_headers(options[:headers]),
|
50
|
-
:image_metadata => Cloudinary::Utils.as_safe_bool(options[:image_metadata]),
|
51
|
-
:media_metadata => Cloudinary::Utils.as_safe_bool(options[:media_metadata]),
|
52
|
-
:invalidate => Cloudinary::Utils.as_safe_bool(options[:invalidate]),
|
53
|
-
:moderation => options[:moderation],
|
54
|
-
:notification_url => options[:notification_url],
|
55
|
-
:ocr => options[:ocr],
|
56
|
-
:overwrite => Cloudinary::Utils.as_safe_bool(options[:overwrite]),
|
57
|
-
:phash => Cloudinary::Utils.as_safe_bool(options[:phash]),
|
58
|
-
:proxy => options[:proxy],
|
59
|
-
:public_id => options[:public_id],
|
60
|
-
:public_id_prefix => options[:public_id_prefix],
|
61
|
-
:quality_analysis => Cloudinary::Utils.as_safe_bool(options[:quality_analysis]),
|
62
|
-
:quality_override => options[:quality_override],
|
63
|
-
:raw_convert => options[:raw_convert],
|
64
|
-
:responsive_breakpoints => Cloudinary::Utils.generate_responsive_breakpoints_string(options[:responsive_breakpoints]),
|
65
|
-
:return_delete_token => Cloudinary::Utils.as_safe_bool(options[:return_delete_token]),
|
66
|
-
:similarity_search => options[:similarity_search],
|
67
|
-
:visual_search => Cloudinary::Utils.as_safe_bool(options[:visual_search]),
|
68
|
-
:tags => options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
|
69
|
-
:timestamp => (options[:timestamp] || Time.now.to_i),
|
70
|
-
:transformation => Cloudinary::Utils.generate_transformation_string(options.clone),
|
71
|
-
:type => options[:type],
|
72
|
-
:unique_filename => Cloudinary::Utils.as_safe_bool(options[:unique_filename]),
|
73
|
-
:upload_preset => options[:upload_preset],
|
74
|
-
:use_filename => Cloudinary::Utils.as_safe_bool(options[:use_filename]),
|
75
|
-
:use_filename_as_display_name => Cloudinary::Utils.as_safe_bool(options[:use_filename_as_display_name]),
|
76
|
-
:use_asset_folder_as_public_id_prefix => Cloudinary::Utils.as_safe_bool(options[:use_asset_folder_as_public_id_prefix]),
|
77
|
-
:unique_display_name => Cloudinary::Utils.as_safe_bool(options[:unique_display_name]),
|
78
|
-
:accessibility_analysis => Cloudinary::Utils.as_safe_bool(options[:accessibility_analysis]),
|
79
|
-
:metadata => Cloudinary::Utils.encode_context(options[:metadata])
|
14
|
+
:access_control => Cloudinary::Utils.json_array_param(options[:access_control]),
|
15
|
+
:allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
|
16
|
+
:auto_tagging => options[:auto_tagging] && options[:auto_tagging].to_f,
|
17
|
+
:context => Cloudinary::Utils.encode_context(options[:context]),
|
18
|
+
:custom_coordinates => Cloudinary::Utils.encode_double_array(options[:custom_coordinates]),
|
19
|
+
:eager => Cloudinary::Utils.build_eager(options[:eager]),
|
20
|
+
:face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates]),
|
21
|
+
:headers => build_custom_headers(options[:headers]),
|
22
|
+
:responsive_breakpoints => Cloudinary::Utils.generate_responsive_breakpoints_string(options[:responsive_breakpoints]),
|
23
|
+
:tags => options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
|
24
|
+
:timestamp => (options[:timestamp] || Time.now.to_i),
|
25
|
+
:transformation => Cloudinary::Utils.generate_transformation_string(options.clone),
|
26
|
+
:metadata => Cloudinary::Utils.encode_context(options[:metadata])
|
80
27
|
}
|
28
|
+
|
29
|
+
bool_params = [
|
30
|
+
:async, :backup, :cinemagraph_analysis, :colors, :discard_original_filename, :eager_async, :exif, :faces,
|
31
|
+
:image_metadata, :media_metadata, :invalidate, :overwrite, :phash, :quality_analysis, :return_delete_token,
|
32
|
+
:visual_search, :unique_filename, :use_filename, :use_filename_as_display_name,
|
33
|
+
:use_asset_folder_as_public_id_prefix, :unique_display_name, :accessibility_analysis
|
34
|
+
]
|
35
|
+
|
36
|
+
string_params = [
|
37
|
+
:access_mode, :asset_folder, :background_removal, :callback, :categorization, :detection, :display_name,
|
38
|
+
:eager_notification_url, :eval, :on_success, :folder, :format, :filename_override, :moderation, :notification_url,
|
39
|
+
:ocr, :proxy, :public_id, :public_id_prefix, :quality_override, :raw_convert, :similarity_search, :type,
|
40
|
+
:upload_preset
|
41
|
+
]
|
42
|
+
|
43
|
+
bool_params.each do |b|
|
44
|
+
params[b] = as_bool ? Cloudinary::Utils.as_bool(options[b]): Cloudinary::Utils.as_safe_bool(options[b])
|
45
|
+
end
|
46
|
+
|
47
|
+
string_params.each do |s|
|
48
|
+
params[s] = options[s]
|
49
|
+
end
|
50
|
+
|
81
51
|
params
|
82
52
|
end
|
83
53
|
|
@@ -394,29 +364,39 @@ class Cloudinary::Uploader
|
|
394
364
|
params[:signature] = Cloudinary::Utils.api_sign_request(params.reject { |k, v| non_signable.include?(k) }, api_secret, signature_algorithm)
|
395
365
|
params[:api_key] = api_key
|
396
366
|
end
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
if
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
367
|
+
|
368
|
+
api_url = Cloudinary::Utils.cloudinary_api_url(action, options)
|
369
|
+
api_proxy = options[:api_proxy] || Cloudinary.config.api_proxy
|
370
|
+
timeout = options.fetch(:timeout) { Cloudinary.config.to_h.fetch(:timeout, 60) }
|
371
|
+
|
372
|
+
conn = Faraday.new(url: api_url) do |faraday|
|
373
|
+
faraday.proxy = api_proxy if api_proxy
|
374
|
+
faraday.request :multipart, **options
|
375
|
+
faraday.request :url_encoded
|
376
|
+
faraday.adapter @adapter || Faraday.default_adapter
|
377
|
+
end
|
378
|
+
|
379
|
+
response = conn.send(:post) do |req|
|
380
|
+
req.headers = headers
|
381
|
+
req.body = params.reject { |_, v| v.nil? || v=="" }
|
382
|
+
req.options.timeout = timeout if timeout
|
383
|
+
end
|
384
|
+
|
385
|
+
raise CloudinaryException, "Server returned unexpected status code - #{response.status} - #{response.body}" unless [200, 400, 401, 403, 404, 500].include?(response.status)
|
386
|
+
begin
|
387
|
+
result = Cloudinary::Utils.json_decode(response.body)
|
388
|
+
rescue => e
|
389
|
+
# Error is parsing json
|
390
|
+
raise CloudinaryException, "Error parsing server response (#{response.status}) - #{response.body}. Got - #{e}"
|
391
|
+
end
|
392
|
+
if result["error"]
|
393
|
+
if return_error
|
394
|
+
result["error"]["http_code"] = response.status
|
395
|
+
else
|
396
|
+
raise CloudinaryException, result["error"]["message"]
|
418
397
|
end
|
419
398
|
end
|
399
|
+
|
420
400
|
if use_cache && !result.nil?
|
421
401
|
cache_results(result)
|
422
402
|
end
|