cloudinary 1.0.66 → 1.0.67
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.
- data/CHANGELOG +8 -0
- data/lib/cloudinary.rb +3 -1
- data/lib/cloudinary/api.rb +10 -3
- data/lib/cloudinary/uploader.rb +7 -3
- data/lib/cloudinary/utils.rb +21 -3
- data/lib/cloudinary/version.rb +1 -1
- data/spec/api_spec.rb +18 -6
- data/spec/uploader_spec.rb +32 -0
- data/spec/utils_spec.rb +22 -1
- metadata +16 -8
- checksums.yaml +0 -15
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
= Version 1.0.67 - 2014-01-09
|
2
|
+
* Support specifying face coordinates in upload API.
|
3
|
+
* Support specifying context (currently alt and caption) in upload API and returning context in API.
|
4
|
+
* Support specifying allowed image formats in upload API.
|
5
|
+
* Support listing resources in admin API by multiple public IDs.
|
6
|
+
* Send User-Agent header with client library version in API request.
|
7
|
+
* Support for signed-URLs to override restricted dynamic URLs.
|
8
|
+
|
1
9
|
= Version 1.0.66 - 2013-11-14
|
2
10
|
* Support overwrite flag in upload
|
3
11
|
* Support tags flag in resources_by_tag
|
data/lib/cloudinary.rb
CHANGED
@@ -25,7 +25,9 @@ module Cloudinary
|
|
25
25
|
CF_SHARED_CDN = "d3jpl91pxevbkh.cloudfront.net"
|
26
26
|
AKAMAI_SHARED_CDN = "res.cloudinary.com"
|
27
27
|
OLD_AKAMAI_SHARED_CDN = "cloudinary-a.akamaihd.net"
|
28
|
-
SHARED_CDN = AKAMAI_SHARED_CDN
|
28
|
+
SHARED_CDN = AKAMAI_SHARED_CDN
|
29
|
+
|
30
|
+
USER_AGENT = "cld-ruby-" + VERSION
|
29
31
|
|
30
32
|
FORMAT_ALIASES = {
|
31
33
|
"jpeg" => "jpg",
|
data/lib/cloudinary/api.rb
CHANGED
@@ -36,13 +36,20 @@ class Cloudinary::Api
|
|
36
36
|
type = options[:type]
|
37
37
|
uri = "resources/#{resource_type}"
|
38
38
|
uri += "/#{type}" if !type.blank?
|
39
|
-
call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags), options)
|
39
|
+
call_api(:get, uri, only(options, :next_cursor, :max_results, :prefix, :tags, :context), options)
|
40
40
|
end
|
41
41
|
|
42
42
|
def self.resources_by_tag(tag, options={})
|
43
43
|
resource_type = options[:resource_type] || "image"
|
44
44
|
uri = "resources/#{resource_type}/tags/#{tag}"
|
45
|
-
call_api(:get, uri, only(options, :next_cursor, :max_results, :tags), options)
|
45
|
+
call_api(:get, uri, only(options, :next_cursor, :max_results, :tags, :context), options)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.resources_by_ids(public_ids, options={})
|
49
|
+
resource_type = options[:resource_type] || "image"
|
50
|
+
type = options[:type] || "upload"
|
51
|
+
uri = "resources/#{resource_type}/#{type}"
|
52
|
+
call_api(:get, uri, only(options, :tags, :context).merge(public_ids: public_ids), options)
|
46
53
|
end
|
47
54
|
|
48
55
|
def self.resource(public_id, options={})
|
@@ -126,7 +133,7 @@ class Cloudinary::Api
|
|
126
133
|
# Add authentication
|
127
134
|
api_url.sub!(%r(^(https?://)), "\\1#{api_key}:#{api_secret}@")
|
128
135
|
|
129
|
-
RestClient::Request.execute(:method => method, :url => api_url, :payload => params.reject{|k, v| v.nil? || v==""}, :timeout=>60) do
|
136
|
+
RestClient::Request.execute(:method => method, :url => api_url, :payload => params.reject{|k, v| v.nil? || v==""}, :timeout=>60, :headers => {"User-Agent" => Cloudinary::USER_AGENT}) do
|
130
137
|
|response, request, tmpresult|
|
131
138
|
return Response.new(response) if response.code == 200
|
132
139
|
exception_class = case response.code
|
data/lib/cloudinary/uploader.rb
CHANGED
@@ -38,7 +38,10 @@ class Cloudinary::Uploader
|
|
38
38
|
:eager_async=>Cloudinary::Utils.as_safe_bool(options[:eager_async]),
|
39
39
|
:proxy=>options[:proxy],
|
40
40
|
:folder=>options[:folder],
|
41
|
-
:tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(",")
|
41
|
+
:tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
|
42
|
+
:allowed_formats => Cloudinary::Utils.build_array(options[:allowed_formats]).join(","),
|
43
|
+
:context => Cloudinary::Utils.encode_hash(options[:context]),
|
44
|
+
:face_coordinates => Cloudinary::Utils.encode_double_array(options[:face_coordinates])}
|
42
45
|
params
|
43
46
|
end
|
44
47
|
|
@@ -98,7 +101,8 @@ class Cloudinary::Uploader
|
|
98
101
|
:callback=> options[:callback],
|
99
102
|
:eager=>build_eager(options[:eager]),
|
100
103
|
:headers=>build_custom_headers(options[:headers]),
|
101
|
-
:tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(",")
|
104
|
+
:tags=>options[:tags] && Cloudinary::Utils.build_array(options[:tags]).join(","),
|
105
|
+
:face_coordinates => options[:face_coordinates] && Cloudinary::Utils.encode_double_array(options[:face_coordinates])
|
102
106
|
}
|
103
107
|
end
|
104
108
|
end
|
@@ -205,7 +209,7 @@ class Cloudinary::Uploader
|
|
205
209
|
|
206
210
|
api_url = Cloudinary::Utils.cloudinary_api_url(action, options)
|
207
211
|
|
208
|
-
RestClient::Request.execute(:method => :post, :url => api_url, :payload => params.reject{|k, v| v.nil? || v==""}, :timeout=>60) do
|
212
|
+
RestClient::Request.execute(:method => :post, :url => api_url, :payload => params.reject{|k, v| v.nil? || v==""}, :timeout=>60, :headers => {"User-Agent" => Cloudinary::USER_AGENT}) do
|
209
213
|
|response, request, tmpresult|
|
210
214
|
raise CloudinaryException, "Server returned unexpected status code - #{response.code} - #{response.body}" if ![200,400,401,403,404,500].include?(response.code)
|
211
215
|
begin
|
data/lib/cloudinary/utils.rb
CHANGED
@@ -107,6 +107,8 @@ class Cloudinary::Utils
|
|
107
107
|
shorten = config_option_consume(options, :shorten)
|
108
108
|
force_remote = options.delete(:force_remote)
|
109
109
|
cdn_subdomain = config_option_consume(options, :cdn_subdomain)
|
110
|
+
sign_url = config_option_consume(options, :sign_url)
|
111
|
+
secret = config_option_consume(options, :api_secret)
|
110
112
|
|
111
113
|
original_source = source
|
112
114
|
return original_source if source.blank?
|
@@ -165,9 +167,13 @@ class Cloudinary::Utils
|
|
165
167
|
type = nil
|
166
168
|
end
|
167
169
|
version ||= 1 if source.include?("/") and !source.match(/^v[0-9]+/) and !source.match(/^https?:\//)
|
168
|
-
|
169
|
-
|
170
|
-
|
170
|
+
|
171
|
+
rest = [transformation, version ? "v#{version}" : nil, source].reject(&:blank?).join("/").gsub(%r(([^:])//), '\1/')
|
172
|
+
if sign_url
|
173
|
+
rest = 's--' + Base64.urlsafe_encode64(Digest::SHA1.digest(rest + secret))[0,8] + '--/' + rest
|
174
|
+
end
|
175
|
+
|
176
|
+
source = prefix + "/" + [resource_type, type, rest].reject(&:blank?).join("/").gsub(%r(([^:])//), '\1/')
|
171
177
|
end
|
172
178
|
|
173
179
|
def self.cloudinary_api_url(action = 'upload', options = {})
|
@@ -272,6 +278,18 @@ class Cloudinary::Utils
|
|
272
278
|
else [array]
|
273
279
|
end
|
274
280
|
end
|
281
|
+
|
282
|
+
def self.encode_hash(hash)
|
283
|
+
case hash
|
284
|
+
when Hash then hash.map{|k,v| "#{k}=#{v}"}.join("|")
|
285
|
+
when nil then ""
|
286
|
+
else hash
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
def self.encode_double_array(array)
|
291
|
+
build_array(array).map{|a| build_array(a).join(",")}.join("|")
|
292
|
+
end
|
275
293
|
|
276
294
|
IMAGE_FORMATS = %w(bmp png tif tiff jpg jpeg gif pdf ico eps jpc jp2 psd)
|
277
295
|
|
data/lib/cloudinary/version.rb
CHANGED
data/spec/api_spec.rb
CHANGED
@@ -8,8 +8,8 @@ describe Cloudinary::Api do
|
|
8
8
|
@api = Cloudinary::Api
|
9
9
|
Cloudinary::Uploader.destroy("api_test")
|
10
10
|
Cloudinary::Uploader.destroy("api_test2")
|
11
|
-
Cloudinary::Uploader.upload("spec/logo.png", :public_id=>"api_test", :tags=>"api_test_tag", :eager=>[:width=>100,:crop=>:scale])
|
12
|
-
Cloudinary::Uploader.upload("spec/logo.png", :public_id=>"api_test2", :tags=>"api_test_tag", :eager=>[:width=>100,:crop=>:scale])
|
11
|
+
Cloudinary::Uploader.upload("spec/logo.png", :public_id=>"api_test", :tags=>"api_test_tag", :context => "key=value", :eager=>[:width=>100,:crop=>:scale])
|
12
|
+
Cloudinary::Uploader.upload("spec/logo.png", :public_id=>"api_test2", :tags=>"api_test_tag", :context => "key=value", :eager=>[:width=>100,:crop=>:scale])
|
13
13
|
@api.delete_transformation("api_test_transformation") rescue nil
|
14
14
|
@api.delete_transformation("api_test_transformation2") rescue nil
|
15
15
|
@api.delete_transformation("api_test_transformation3") rescue nil
|
@@ -44,13 +44,25 @@ describe Cloudinary::Api do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should allow listing resources by prefix" do
|
47
|
-
|
48
|
-
|
47
|
+
resources = @api.resources(:type=>"upload", :prefix=>"api_test", :tags => true, :context => true)["resources"]
|
48
|
+
resources.map{|resource| resource["public_id"]}.should include("api_test", "api_test2")
|
49
|
+
resources.map{|resource| resource["tags"]}.should include(["api_test_tag"])
|
50
|
+
resources.map{|resource| resource["context"]}.should include({"custom" => {"key" => "value"}})
|
49
51
|
end
|
50
52
|
|
51
53
|
it "should allow listing resources by tag" do
|
52
|
-
|
53
|
-
resource.should_not be_blank
|
54
|
+
resources = @api.resources_by_tag("api_test_tag", :tags => true, :context => true)["resources"]
|
55
|
+
resources.find{|resource| resource["public_id"] == "api_test"}.should_not be_blank
|
56
|
+
resources.map{|resource| resource["tags"]}.should include(["api_test_tag"])
|
57
|
+
resources.map{|resource| resource["context"]}.should include({"custom" => {"key" => "value"}})
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should allow listing resources by public ids" do
|
61
|
+
resources = @api.resources_by_ids(["api_test", "api_test2"], :tags => true, :context => true)["resources"]
|
62
|
+
resources.length.should == 2
|
63
|
+
resources.find{|resource| resource["public_id"] == "api_test"}.should_not be_blank
|
64
|
+
resources.map{|resource| resource["tags"]}.should include(["api_test_tag"])
|
65
|
+
resources.map{|resource| resource["context"]}.should include({"custom" => {"key" => "value"}})
|
54
66
|
end
|
55
67
|
|
56
68
|
it "should allow get resource metadata" do
|
data/spec/uploader_spec.rb
CHANGED
@@ -75,4 +75,36 @@ describe Cloudinary::Uploader do
|
|
75
75
|
result = Cloudinary::Uploader.upload("spec/logo.png", use_filename: true, unique_filename: false)
|
76
76
|
result["public_id"].should == "logo"
|
77
77
|
end
|
78
|
+
|
79
|
+
it "should allow whitelisted formats if allowed_formats", :allowed=>true do
|
80
|
+
result = Cloudinary::Uploader.upload("spec/logo.png", allowed_formats: ["png"])
|
81
|
+
result["format"].should == "png"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should prevent non whitelisted formats from being uploaded if allowed_formats is specified", :allowed=>true do
|
85
|
+
lambda{Cloudinary::Uploader.upload("spec/logo.png", allowed_formats: ["jpg"])}.should raise_error
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should allow non whitelisted formats if type is specified and convert to that type", :allowed=>true do
|
89
|
+
result = Cloudinary::Uploader.upload("spec/logo.png", allowed_formats: ["jpg"], format: "jpg")
|
90
|
+
result["format"].should == "jpg"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should allow sending face coordinates" do
|
94
|
+
coordinates = [[120, 30, 109, 150], [121, 31, 110, 151]]
|
95
|
+
result = Cloudinary::Uploader.upload("spec/logo.png", {face_coordinates: coordinates, faces: true})
|
96
|
+
result["faces"].should == coordinates
|
97
|
+
|
98
|
+
different_coordinates = [[122, 32, 111, 152]]
|
99
|
+
Cloudinary::Uploader.explicit(result["public_id"], {face_coordinates: different_coordinates, faces: true, type: "upload"})
|
100
|
+
info = Cloudinary::Api.resource(result["public_id"], {faces: true})
|
101
|
+
info["faces"].should == different_coordinates
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should allow sending context" do
|
105
|
+
context = {"caption" => "some caption", "alt" => "alternative"}
|
106
|
+
result = Cloudinary::Uploader.upload("spec/logo.png", {:context => context})
|
107
|
+
info = Cloudinary::Api.resource(result["public_id"], {:context => true})
|
108
|
+
info["context"].should == {"custom" => context}
|
109
|
+
end
|
78
110
|
end
|
data/spec/utils_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Cloudinary::Utils do
|
|
12
12
|
config.cname = nil
|
13
13
|
config.cdn_subdomain = false
|
14
14
|
config.api_key = "1234"
|
15
|
-
config.api_secret = "
|
15
|
+
config.api_secret = "b"
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -439,4 +439,25 @@ describe Cloudinary::Utils do
|
|
439
439
|
Cloudinary::Utils.cloudinary_url(source).should == "http://res.cloudinary.com/test123/image/upload/#{target}"
|
440
440
|
end
|
441
441
|
end
|
442
|
+
|
443
|
+
it "should correctly sign URLs", :signed => true do
|
444
|
+
options = {version: 1234, transformation: {crop: "crop", width: 10, height: 20}, sign_url: true}
|
445
|
+
expected = "http://res.cloudinary.com/test123/image/upload/s--MaRXzoEC--/c_crop,h_20,w_10/v1234/image.jpg"
|
446
|
+
actual = Cloudinary::Utils.cloudinary_url("image.jpg", options)
|
447
|
+
actual.should == expected
|
448
|
+
|
449
|
+
options = {version: 1234, sign_url: true}
|
450
|
+
expected = "http://res.cloudinary.com/test123/image/upload/s--ZlgFLQcO--/v1234/image.jpg"
|
451
|
+
actual = Cloudinary::Utils.cloudinary_url("image.jpg", options)
|
452
|
+
actual.should == expected
|
453
|
+
|
454
|
+
options = {transformation: {crop: "crop", width: 10, height: 20}, sign_url: true}
|
455
|
+
expected = "http://res.cloudinary.com/test123/image/upload/s--Ai4Znfl3--/c_crop,h_20,w_10/image.jpg"
|
456
|
+
actual = Cloudinary::Utils.cloudinary_url("image.jpg", options)
|
457
|
+
actual.should == expected
|
458
|
+
|
459
|
+
expected = "http://res.cloudinary.com/test123/image/fetch/s--_GAUclyB--/v1234/http://google.com/path/to/image.png"
|
460
|
+
actual = Cloudinary::Utils.cloudinary_url("http://google.com/path/to/image.png", type: "fetch", version: 1234, sign_url: true)
|
461
|
+
actual.should == expected
|
462
|
+
end
|
442
463
|
end
|
metadata
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cloudinary
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.67
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Nadav Soferman
|
@@ -10,46 +11,52 @@ authors:
|
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date:
|
14
|
+
date: 2014-01-09 00:00:00.000000000 Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
17
|
+
name: rest-client
|
16
18
|
requirement: !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
17
20
|
requirements:
|
18
21
|
- - ! '>='
|
19
22
|
- !ruby/object:Gem::Version
|
20
23
|
version: '0'
|
21
24
|
type: :runtime
|
22
25
|
prerelease: false
|
23
|
-
name: rest-client
|
24
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
25
28
|
requirements:
|
26
29
|
- - ! '>='
|
27
30
|
- !ruby/object:Gem::Version
|
28
31
|
version: '0'
|
29
32
|
- !ruby/object:Gem::Dependency
|
33
|
+
name: aws_cf_signer
|
30
34
|
requirement: !ruby/object:Gem::Requirement
|
35
|
+
none: false
|
31
36
|
requirements:
|
32
37
|
- - ! '>='
|
33
38
|
- !ruby/object:Gem::Version
|
34
39
|
version: '0'
|
35
40
|
type: :runtime
|
36
41
|
prerelease: false
|
37
|
-
name: aws_cf_signer
|
38
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
none: false
|
39
44
|
requirements:
|
40
45
|
- - ! '>='
|
41
46
|
- !ruby/object:Gem::Version
|
42
47
|
version: '0'
|
43
48
|
- !ruby/object:Gem::Dependency
|
49
|
+
name: rspec
|
44
50
|
requirement: !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
45
52
|
requirements:
|
46
53
|
- - ! '>='
|
47
54
|
- !ruby/object:Gem::Version
|
48
55
|
version: '0'
|
49
56
|
type: :development
|
50
57
|
prerelease: false
|
51
|
-
name: rspec
|
52
58
|
version_requirements: !ruby/object:Gem::Requirement
|
59
|
+
none: false
|
53
60
|
requirements:
|
54
61
|
- - ! '>='
|
55
62
|
- !ruby/object:Gem::Version
|
@@ -114,26 +121,27 @@ files:
|
|
114
121
|
homepage: http://cloudinary.com
|
115
122
|
licenses:
|
116
123
|
- MIT
|
117
|
-
metadata: {}
|
118
124
|
post_install_message:
|
119
125
|
rdoc_options: []
|
120
126
|
require_paths:
|
121
127
|
- lib
|
122
128
|
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
123
130
|
requirements:
|
124
131
|
- - ! '>='
|
125
132
|
- !ruby/object:Gem::Version
|
126
133
|
version: '0'
|
127
134
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
128
136
|
requirements:
|
129
137
|
- - ! '>='
|
130
138
|
- !ruby/object:Gem::Version
|
131
139
|
version: '0'
|
132
140
|
requirements: []
|
133
141
|
rubyforge_project: cloudinary
|
134
|
-
rubygems_version:
|
142
|
+
rubygems_version: 1.8.24
|
135
143
|
signing_key:
|
136
|
-
specification_version:
|
144
|
+
specification_version: 3
|
137
145
|
summary: Client library for easily using the Cloudinary service
|
138
146
|
test_files:
|
139
147
|
- spec/api_spec.rb
|
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
NjljOWM1ZTk5ODJmZDAyMzc3Y2Y0MGU0OGY0NTE5NTI5N2FkZjA3OA==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MmFiZjlmNzJjMDQwZDI4YzUzZmJkZjA0NjRjMzk0MzI2YzVhNDk1Yw==
|
7
|
-
!binary "U0hBNTEy":
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
MWNkY2Y0MzQ1YjljZWM4OTYwZjkxNWY0ZGI1OWRmNjAwOWZlZjRkZTgxOGFm
|
10
|
-
NmI3YjVhMDJlM2Y2MGJmYjk0NmFiNjVkMmI2NzkxNjM3NmViNTdkM2ZhNDc2
|
11
|
-
MTE5MzQ1MjM0ZTY5OGJiMmU0NDliYzBhNDI4N2I0YTY2ZDNmMTM=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
ZTk2ZGUwMTA5MjYyZmFkMWEzZmIzMTQ4NTQ5MjdhMzliMjk5YmQzNzNhZDhh
|
14
|
-
NTBiNGM0MDcyZWVhOGMzODk5NDQ2ZTcxMWI3MTFlMDkzZDkyNTYzOGM5NDI5
|
15
|
-
Yzc4Yjc1MmQ0ZGUxMTcwNDViNjI0ZmUyMTk4NTM2Njg0NDMyMjA=
|