scale_down 0.2.9 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.bundle/config +1 -2
- data/Gemfile +4 -0
- data/Gemfile.lock +10 -3
- data/README.rdoc +55 -42
- data/lib/scale_down/controller.rb +10 -5
- data/lib/scale_down/dispatcher.rb +6 -5
- data/lib/scale_down/image.rb +1 -1
- data/lib/scale_down/version.rb +1 -1
- data/lib/scale_down.rb +1 -1
- data/test/scale_down/controller_test.rb +6 -7
- data/test/scale_down/dispatcher_test.rb +11 -11
- data/test/scale_down/image_test.rb +18 -18
- data/test/scale_down_test.rb +7 -7
- data/test/scaled_image_tag_test.rb +7 -7
- data/test/test_helper.rb +1 -2
- metadata +3 -5
data/.bundle/config
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
---
|
2
|
-
BUNDLE_DISABLE_SHARED_GEMS: "1"
|
1
|
+
--- {}
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
scale_down (0.2.
|
4
|
+
scale_down (0.2.9)
|
5
5
|
rmagick (>= 2.1)
|
6
6
|
ruby-hmac (>= 0.4.0)
|
7
7
|
sinatra (>= 1.0)
|
@@ -10,6 +10,8 @@ GEM
|
|
10
10
|
remote: http://rubygems.org/
|
11
11
|
specs:
|
12
12
|
contest (0.1.3)
|
13
|
+
daemons (1.1.4)
|
14
|
+
eventmachine (0.12.10)
|
13
15
|
mocha (0.9.8)
|
14
16
|
rake
|
15
17
|
rack (1.2.2)
|
@@ -18,10 +20,14 @@ GEM
|
|
18
20
|
rake (0.8.7)
|
19
21
|
rmagick (2.13.1)
|
20
22
|
ruby-hmac (0.4.0)
|
21
|
-
sinatra (1.2.
|
23
|
+
sinatra (1.2.7)
|
22
24
|
rack (~> 1.1)
|
23
25
|
tilt (>= 1.2.2, < 2.0)
|
24
|
-
|
26
|
+
thin (1.3.1)
|
27
|
+
daemons (>= 1.0.9)
|
28
|
+
eventmachine (>= 0.12.6)
|
29
|
+
rack (>= 1.0.0)
|
30
|
+
tilt (1.3.3)
|
25
31
|
|
26
32
|
PLATFORMS
|
27
33
|
ruby
|
@@ -31,3 +37,4 @@ DEPENDENCIES
|
|
31
37
|
mocha (= 0.9.8)
|
32
38
|
rack-test (= 0.5.6)
|
33
39
|
scale_down!
|
40
|
+
thin
|
data/README.rdoc
CHANGED
@@ -1,52 +1,89 @@
|
|
1
1
|
= ScaleDown
|
2
2
|
|
3
|
-
|
3
|
+
An on demand image scaling server.
|
4
4
|
|
5
5
|
Images are scaled based upon their URL. An HMAC signature is used to prevent unauthorized scaling of images.
|
6
6
|
|
7
7
|
Supports cropping images and converts CMYK to RGB.
|
8
8
|
|
9
|
-
The URL schema
|
9
|
+
== The URL schema
|
10
10
|
|
11
|
-
|
11
|
+
Your file on `example.com` has a public path of `/images/john/picture.png`. You want it scaled to fit in a 400x400 pixel box. *ScaleDown* is running on the subdomain `images`.
|
12
12
|
|
13
|
-
|
13
|
+
The URL to your image would be:
|
14
14
|
|
15
|
-
|
15
|
+
http://images.example.com/images/john/scaled/400x400/picture.png?HMAC_SIGNATURE
|
16
|
+
|
17
|
+
The scaled file will be saved in a public path identical to the request. So once an image is scaled your webserver, Apache, Nginx, etc, can statically server the file.
|
18
|
+
|
19
|
+
The schema is
|
20
|
+
|
21
|
+
http://:host/:path_to_file/scaled/:geometry/:filename?:hmac_signature
|
22
|
+
|
23
|
+
:host is the address running ScaleDown
|
16
24
|
|
17
25
|
:path_to_file is the public path of the original file
|
18
26
|
|
27
|
+
`scaled` keyword
|
28
|
+
|
29
|
+
:geometry is width x height and an optional `-crop`
|
30
|
+
|
19
31
|
:filename is the name of the image to scale
|
20
32
|
|
21
33
|
:hmac_signature a security measure to validate the request
|
22
34
|
|
23
|
-
|
35
|
+
== Geometry & Cropping
|
24
36
|
|
25
|
-
|
37
|
+
To crop an image include the `-crop` option. The image will be scaled and cropped to fit the geometry.
|
26
38
|
|
27
|
-
|
39
|
+
http://images.example.com/images/scaled/400x300-crop/logo.png?A3SDACEDF
|
28
40
|
|
29
|
-
|
41
|
+
Using `auto` as a dimension will fit the image to other dimension.
|
30
42
|
|
31
|
-
|
43
|
+
For example, to ensure an image is 300 pixels wide set the height to auto
|
32
44
|
|
33
|
-
http://images.example.com/
|
45
|
+
http://images.example.com/images/scaled/300xauto/logo.png/?A3SDACEDF
|
34
46
|
|
35
|
-
|
47
|
+
There is a very simple `/info` function for getting image dimensions. It just returns a string with the WIDTHxHEIGHT.
|
36
48
|
|
37
|
-
|
49
|
+
http://images.example.com/images/logo.png/info
|
50
|
+
|
51
|
+
== HMAC
|
52
|
+
|
53
|
+
You don't want someone taking down your server with malicious URLs, so an HMAC signature is used. This ensures that your URL was generated by a trusted source.
|
54
|
+
|
55
|
+
HMAC requires a shared key between the application generating the URL and the ScaleDown server.
|
38
56
|
|
39
|
-
|
57
|
+
=== Sample Ruby URL Generator
|
40
58
|
|
41
|
-
|
59
|
+
require 'ruby-hmac'
|
42
60
|
|
43
|
-
|
61
|
+
def signed_image_url(absolute_path, filename, geometry)
|
62
|
+
shared_secret = "secret"
|
63
|
+
hmac = HMAC::SHA1.new(shared_secret).update([absolute_path, 'scaled', geometry, filename].join("/")).to_s[0...8]
|
64
|
+
"http://images.example.com#{[absolute_path, 'scaled', geometry, CGI.escape(filename)].join("/")}?#{hmac}"
|
65
|
+
end
|
66
|
+
|
67
|
+
=== Sample Node.js URL Generator
|
68
|
+
|
69
|
+
// Uses the Node.js crypot library
|
70
|
+
var crypto = require('crypto')
|
71
|
+
|
72
|
+
function hmac(string){
|
73
|
+
var shared_secret = "secret"
|
74
|
+
return crypto.createHmac('sha1',shared_secret).update(string).digest('hex').substr(0,8)
|
75
|
+
}
|
76
|
+
|
77
|
+
function signed_image_url(absolute_path, filename, geometry){
|
78
|
+
signature = hmac( [ absolute_path, '/scaled', "/" + geometry, "/", filename].join("") )
|
79
|
+
return [global.$FD.assetHost, absolute_path, '/scaled', "/", geometry, "/",escape(filename)].join("") + "?"+ signature
|
80
|
+
}
|
44
81
|
|
45
82
|
== Installation and Configuration
|
46
83
|
|
47
84
|
gem install scale_down
|
48
85
|
|
49
|
-
Create a
|
86
|
+
Create a Rackup file (config.ru). See https://github.com/jweir/ScaleDown/tree/master/config_sample.ru more options
|
50
87
|
|
51
88
|
require 'rubygems'
|
52
89
|
require 'scale_down'
|
@@ -61,36 +98,12 @@ Create a rackup file (config.ru). See http://rubydoc.info/gems/scale_down/0.2.1/
|
|
61
98
|
|
62
99
|
run ScaleDown::Controller
|
63
100
|
|
64
|
-
Configure Nginx, Apache, etc to run the server.
|
65
|
-
|
66
|
-
=== Generating the URL
|
67
|
-
|
68
|
-
Your application will need to generate the image's URL and HMAC signature.
|
69
|
-
|
70
|
-
# Example ruby function to generate signed URL
|
71
|
-
require 'HMAC::SHA1'
|
72
|
-
require 'cgi'
|
73
|
-
|
74
|
-
# ie signed_image_url('images', 'picture.png', '400x300-cropped')
|
75
|
-
def signed_image_url(path, filename, geometry)
|
76
|
-
hmac = HMAC::SHA1.new("secret").update("/#{geometry}/#{path}/#{filename}").to_s[0..8]
|
77
|
-
"http://images.myserver.com/#{geometry}/#{path}/#{CGI.escape(filename)}?#{hmac}"
|
78
|
-
end
|
79
|
-
|
80
|
-
Of course this could be done in PHP, Node, Python, or other languages.
|
101
|
+
Configure Nginx, Apache, etc to run the server.
|
81
102
|
|
82
103
|
== Known Issues
|
83
104
|
|
84
105
|
Pluses in filenames will not route properly. Filenames need to have these removed or replaced.
|
85
106
|
|
86
|
-
== TODO
|
87
|
-
|
88
|
-
Custom Read/Write methods to allow for more than just local storage.
|
89
|
-
|
90
|
-
Examples using Node.js
|
91
|
-
|
92
|
-
There is an issue on some systems with pluses in filenames.
|
93
|
-
|
94
107
|
== Dependencies
|
95
108
|
|
96
109
|
* Sinatra
|
@@ -17,25 +17,30 @@ class ScaleDown::Controller < Sinatra::Application
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
# get '/*/:filename
|
20
|
+
# get '/*/:geometry/:filename?:hmac'
|
21
21
|
# is what I want, but this fails when the URL includes things like %23 (an encoded hash tag)
|
22
22
|
get '/*' do
|
23
23
|
parts = params[:splat].join("/").split("/")
|
24
24
|
|
25
25
|
params = {
|
26
26
|
:hmac => request.env["QUERY_STRING"],
|
27
|
-
:geometry => parts.shift,
|
28
27
|
:filename => parts.pop,
|
28
|
+
:geometry => parts.pop,
|
29
29
|
:splat => parts
|
30
30
|
}
|
31
31
|
|
32
32
|
path, status = dispatch(params)
|
33
33
|
|
34
34
|
ScaleDown.logger.info "Controller#get #{path} #{status}"
|
35
|
-
|
36
|
-
|
35
|
+
case status
|
36
|
+
when 302 then
|
37
|
+
# File is found or scaled, use Sinatra's built in send file method
|
38
|
+
static!
|
39
|
+
when 403 then
|
40
|
+
[status, "Error: the the HMAC is invalid for this request"]
|
41
|
+
when 404 then
|
42
|
+
[status, "Error: the orignal image could not be found"]
|
37
43
|
else
|
38
|
-
# TODO error messages which explain what went wrong
|
39
44
|
[status, "Error: this image could not be processed"]
|
40
45
|
end
|
41
46
|
end
|
@@ -10,12 +10,12 @@ class ScaleDown::Dispatcher
|
|
10
10
|
ScaleDown.logger.info "Dipatcher#process #{dispatcher.root_path}"
|
11
11
|
|
12
12
|
return ["Missing file", 404] unless dispatcher.root_file_exists?
|
13
|
-
return [dispatcher.redirect_path,
|
13
|
+
return [dispatcher.redirect_path, 302] if dispatcher.scaled_file_exists?
|
14
14
|
|
15
15
|
return ["Invalid HMAC signature", 403] unless dispatcher.valid_hmac?
|
16
16
|
return ["File failed to scale. The file may be corrupt.", 500] unless dispatcher.scale
|
17
17
|
|
18
|
-
[dispatcher.redirect_path,
|
18
|
+
[dispatcher.redirect_path, 302]
|
19
19
|
end
|
20
20
|
|
21
21
|
# TODO return a JSON response with a full set of image details
|
@@ -55,7 +55,7 @@ class ScaleDown::Dispatcher
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def redirect_path
|
58
|
-
["/"+@params[:path],
|
58
|
+
["/"+@params[:path], @params[:geometry], scaled_filename].join("/")
|
59
59
|
end
|
60
60
|
|
61
61
|
def root_file_exists?
|
@@ -67,7 +67,8 @@ class ScaleDown::Dispatcher
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def root_path
|
70
|
-
|
70
|
+
root = @params[:path].gsub(/\/scaled$/,"")
|
71
|
+
File.join(ScaleDown.public_path, root, @params[:filename])
|
71
72
|
end
|
72
73
|
|
73
74
|
def scaled_file_path
|
@@ -75,7 +76,7 @@ class ScaleDown::Dispatcher
|
|
75
76
|
end
|
76
77
|
|
77
78
|
def scaled_filename
|
78
|
-
"#{filename}
|
79
|
+
"#{filename}.#{scaled_extension}"
|
79
80
|
end
|
80
81
|
|
81
82
|
def filename
|
data/lib/scale_down/image.rb
CHANGED
data/lib/scale_down/version.rb
CHANGED
data/lib/scale_down.rb
CHANGED
@@ -10,23 +10,22 @@ class ScaleDown::Controller::Test < Test::Unit::TestCase
|
|
10
10
|
context "parsing a request" do
|
11
11
|
should "have an image path" do
|
12
12
|
ScaleDown::Dispatcher.expects(:process).with(
|
13
|
-
:path => "user/path",
|
13
|
+
:path => "user/path/scaled",
|
14
14
|
:filename => "filename.png",
|
15
15
|
:geometry => "400x300-crop-grayscale",
|
16
16
|
:hmac => "HMAC").
|
17
17
|
returns ["path","status"]
|
18
18
|
|
19
|
-
get '/400x300-crop-grayscale/
|
19
|
+
get '/user/path/scaled/400x300-crop-grayscale/filename.png?HMAC'
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
context "a valid request" do
|
24
24
|
should "redirect to the image path" do
|
25
|
-
ScaleDown::Dispatcher.expects(:process).returns ["/image-path",
|
26
|
-
get "/geo/
|
25
|
+
ScaleDown::Dispatcher.expects(:process).returns ["/image-path", 302]
|
26
|
+
get "/path/geo/filename?hmac"
|
27
27
|
|
28
|
-
assert_equal
|
29
|
-
assert_equal "http://example.org/image-path", last_response["Location"]
|
28
|
+
assert_equal 200, last_response.status
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
@@ -35,7 +34,7 @@ class ScaleDown::Controller::Test < Test::Unit::TestCase
|
|
35
34
|
should "respond with a 403 and error message" do
|
36
35
|
ScaleDown::Dispatcher.expects(:process).returns ["Error description", 403]
|
37
36
|
|
38
|
-
get "/geo/
|
37
|
+
get "/path/geo/filename?hmac"
|
39
38
|
|
40
39
|
assert_equal 403, last_response.status
|
41
40
|
assert_match "Error", last_response.body
|
@@ -9,10 +9,10 @@ class ScaleDown::Dispatcher::Test < Test::Unit::TestCase
|
|
9
9
|
ScaleDown.hmac_length = 8
|
10
10
|
ScaleDown.public_path = "/tmp"
|
11
11
|
|
12
|
-
hmac = HMAC::SHA1.new("secret").update("file/path/filename.png
|
12
|
+
hmac = HMAC::SHA1.new("secret").update("file/path/400x300-crop/filename.png").to_s
|
13
13
|
|
14
14
|
@params = {
|
15
|
-
:path => "file/path",
|
15
|
+
:path => "file/path/scaled",
|
16
16
|
:filename => "filename.png",
|
17
17
|
:geometry => "400x300-crop",
|
18
18
|
:hmac => hmac[0...8]
|
@@ -34,8 +34,8 @@ class ScaleDown::Dispatcher::Test < Test::Unit::TestCase
|
|
34
34
|
assert @dispatcher.root_file_exists?
|
35
35
|
end
|
36
36
|
|
37
|
-
should "
|
38
|
-
File.expects(:exists?).with("/tmp/file/path/scaled/
|
37
|
+
should "determine the scaled image's existance" do
|
38
|
+
File.expects(:exists?).with("/tmp/file/path/scaled/400x300-crop/filename.png").returns true
|
39
39
|
assert @dispatcher.scaled_file_exists?
|
40
40
|
end
|
41
41
|
|
@@ -44,7 +44,7 @@ class ScaleDown::Dispatcher::Test < Test::Unit::TestCase
|
|
44
44
|
end
|
45
45
|
|
46
46
|
should "have a redirect path" do
|
47
|
-
assert_equal "/file/path/scaled/
|
47
|
+
assert_equal "/file/path/scaled/400x300-crop/filename.png", @dispatcher.redirect_path
|
48
48
|
end
|
49
49
|
|
50
50
|
should "process the image" do
|
@@ -74,7 +74,7 @@ class ScaleDown::Dispatcher::Test < Test::Unit::TestCase
|
|
74
74
|
context "for an existing, unscaled image" do
|
75
75
|
setup do
|
76
76
|
File.expects(:exists?).with("/tmp/file/path/filename.png").returns true
|
77
|
-
File.expects(:exists?).with("/tmp/file/path/scaled/
|
77
|
+
File.expects(:exists?).with("/tmp/file/path/scaled/400x300-crop/filename.png").returns false
|
78
78
|
end
|
79
79
|
|
80
80
|
context "with a valid HMAC" do
|
@@ -87,8 +87,8 @@ class ScaleDown::Dispatcher::Test < Test::Unit::TestCase
|
|
87
87
|
ScaleDown::Dispatcher.process(@params)
|
88
88
|
end
|
89
89
|
|
90
|
-
should "return a
|
91
|
-
assert_equal ["/file/path/scaled/
|
90
|
+
should "return a 302 redirect to the processed image's URL" do
|
91
|
+
assert_equal ["/file/path/scaled/400x300-crop/filename.png", 302], ScaleDown::Dispatcher.process(@params)
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
@@ -103,11 +103,11 @@ class ScaleDown::Dispatcher::Test < Test::Unit::TestCase
|
|
103
103
|
context "for an existing, scaled, image" do
|
104
104
|
setup do
|
105
105
|
File.expects(:exists?).with("/tmp/file/path/filename.png").returns true
|
106
|
-
File.expects(:exists?).with("/tmp/file/path/scaled/
|
106
|
+
File.expects(:exists?).with("/tmp/file/path/scaled/400x300-crop/filename.png").returns true
|
107
107
|
end
|
108
108
|
|
109
|
-
should "return a
|
110
|
-
assert_equal ["/file/path/scaled/
|
109
|
+
should "return a 302 redirect to the processed image's URL" do
|
110
|
+
assert_equal ["/file/path/scaled/400x300-crop/filename.png", 302], ScaleDown::Dispatcher.process(@params)
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
@@ -17,16 +17,16 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
17
17
|
setup do
|
18
18
|
@subject = create \
|
19
19
|
fixture_path("files/graphic.png"),
|
20
|
-
fixture_path("scaled_test/
|
20
|
+
fixture_path("scaled_test/scaled/graphic.png"),
|
21
21
|
{ :width => 100, :height => 180}
|
22
22
|
end
|
23
23
|
|
24
24
|
should "save the file (and generate the path)" do
|
25
|
-
assert File.exists?(fixture_path('scaled_test/
|
25
|
+
assert File.exists?(fixture_path('scaled_test/scaled/graphic.png'))
|
26
26
|
end
|
27
27
|
|
28
28
|
should "scale the image" do
|
29
|
-
image = Magick::Image.read(fixture_path("scaled_test/
|
29
|
+
image = Magick::Image.read(fixture_path("scaled_test/scaled/graphic.png")).first
|
30
30
|
assert_equal 90, image.columns
|
31
31
|
assert_equal 180, image.rows
|
32
32
|
end
|
@@ -46,10 +46,10 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
46
46
|
should "auto scale any one dimensions" do
|
47
47
|
assert create \
|
48
48
|
fixture_path("files/graphic.png"),
|
49
|
-
fixture_path("scaled_test/
|
49
|
+
fixture_path("scaled_test/scaled/graphic.png"),
|
50
50
|
{ :width => "auto", :height => 150 }
|
51
51
|
|
52
|
-
image = Magick::Image.read(fixture_path("scaled_test/
|
52
|
+
image = Magick::Image.read(fixture_path("scaled_test/scaled/graphic.png")).first
|
53
53
|
assert_equal 150, image.rows
|
54
54
|
assert_equal 75, image.columns
|
55
55
|
end
|
@@ -77,7 +77,7 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
77
77
|
setup do
|
78
78
|
@subject = create \
|
79
79
|
fixture_path("files/invalid_jpeg.jpg"),
|
80
|
-
fixture_path("scaled_test/
|
80
|
+
fixture_path("scaled_test/scaled/graphic.jpg"),
|
81
81
|
{ :width => 100, :height => 105 }
|
82
82
|
end
|
83
83
|
|
@@ -86,7 +86,7 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
86
86
|
end
|
87
87
|
|
88
88
|
should "not create a scaled image" do
|
89
|
-
assert !File.exists?(fixture_path("scaled_test/
|
89
|
+
assert !File.exists?(fixture_path("scaled_test/scaled/graphic.jpg"))
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
@@ -99,7 +99,7 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
99
99
|
assert_raises ScaleDown::FileSizeTooLarge do
|
100
100
|
@subject = create \
|
101
101
|
fixture_path("files/graphic.png"),
|
102
|
-
fixture_path("scaled_test/
|
102
|
+
fixture_path("scaled_test/scaled/graphic.png"),
|
103
103
|
{ :width => 100, :height => 105 }
|
104
104
|
end
|
105
105
|
end
|
@@ -109,12 +109,12 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
109
109
|
setup do
|
110
110
|
@subject = create \
|
111
111
|
fixture_path("files/graphic.png"),
|
112
|
-
fixture_path("scaled_test/
|
112
|
+
fixture_path("scaled_test/scaled/graphic.png"),
|
113
113
|
{ :width => 25, :height => 25, :crop => true }
|
114
114
|
end
|
115
115
|
|
116
116
|
should "crop the image to the dimensions" do
|
117
|
-
image = Magick::Image.read(fixture_path("scaled_test/
|
117
|
+
image = Magick::Image.read(fixture_path("scaled_test/scaled/graphic.png")).first
|
118
118
|
assert_equal 25, image.columns
|
119
119
|
assert_equal 25, image.rows
|
120
120
|
end
|
@@ -124,12 +124,12 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
124
124
|
setup do
|
125
125
|
@subject = create \
|
126
126
|
fixture_path("files/orient.jpg"),
|
127
|
-
fixture_path("scaled_test/
|
127
|
+
fixture_path("scaled_test/scaled/graphic.jpg"),
|
128
128
|
{ :width => "auto", :height => 800}
|
129
129
|
end
|
130
130
|
|
131
131
|
should "be automatic" do
|
132
|
-
image = Magick::Image.read(fixture_path("scaled_test/
|
132
|
+
image = Magick::Image.read(fixture_path("scaled_test/scaled/graphic.jpg")).first
|
133
133
|
assert_equal 600, image.columns
|
134
134
|
assert_equal 800, image.rows
|
135
135
|
end
|
@@ -137,10 +137,10 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
137
137
|
should "ignore files without orientation EXIF" do
|
138
138
|
@subject = create \
|
139
139
|
fixture_path("files/no_orient.tif"),
|
140
|
-
fixture_path("scaled_test/
|
140
|
+
fixture_path("scaled_test/scaled/graphic.jpg"),
|
141
141
|
{ :width => "auto", :height => 424}
|
142
142
|
|
143
|
-
image = Magick::Image.read(fixture_path("scaled_test/
|
143
|
+
image = Magick::Image.read(fixture_path("scaled_test/scaled/graphic.jpg")).first
|
144
144
|
assert_equal 330, image.columns
|
145
145
|
assert_equal 424, image.rows
|
146
146
|
end
|
@@ -150,20 +150,20 @@ class ScaleDown::Image::Test < Test::Unit::TestCase
|
|
150
150
|
should "be converted to RGB" do
|
151
151
|
create \
|
152
152
|
fixture_path("files/cmyk.tif"),
|
153
|
-
fixture_path("scaled_test/
|
153
|
+
fixture_path("scaled_test/scaled/graphic.jpg"),
|
154
154
|
{ :width => "auto", :height => 200}
|
155
155
|
|
156
|
-
image = Magick::Image.read(fixture_path("scaled_test/
|
156
|
+
image = Magick::Image.read(fixture_path("scaled_test/scaled/graphic.jpg")).first
|
157
157
|
assert_equal Magick::RGBColorspace, image.colorspace
|
158
158
|
end
|
159
159
|
|
160
160
|
should "convert JPGs to RGB JPEGS" do
|
161
161
|
create \
|
162
162
|
fixture_path("files/cmyk_gray.jpg"),
|
163
|
-
fixture_path("scaled_test/
|
163
|
+
fixture_path("scaled_test/scaled/graphic_2.jpg"),
|
164
164
|
{ :width => "auto", :height => 200}
|
165
165
|
|
166
|
-
image = Magick::Image.read(fixture_path("scaled_test/
|
166
|
+
image = Magick::Image.read(fixture_path("scaled_test/scaled/graphic_2.jpg")).first
|
167
167
|
assert_equal Magick::RGBColorspace, image.colorspace
|
168
168
|
end
|
169
169
|
end
|
data/test/scale_down_test.rb
CHANGED
@@ -21,7 +21,7 @@ class ScaleDown::Test < Test::Unit::TestCase
|
|
21
21
|
|
22
22
|
context "HMAC" do
|
23
23
|
setup do
|
24
|
-
hmac = HMAC::SHA1.new("secret").update("/400x300-crop/
|
24
|
+
hmac = HMAC::SHA1.new("secret").update("/file/path/400x300-crop/filename.png").to_s
|
25
25
|
|
26
26
|
@params = {
|
27
27
|
:path => "file/path",
|
@@ -59,19 +59,19 @@ class ScaleDown::Test < Test::Unit::TestCase
|
|
59
59
|
end
|
60
60
|
|
61
61
|
should "get an image and scale it" do
|
62
|
-
valid_get '/400x300-cropped/
|
63
|
-
assert_equal
|
64
|
-
|
65
|
-
|
62
|
+
valid_get '/test_images/example_1/scaled/400x300-cropped/graphic.png'
|
63
|
+
assert_equal 200, last_response.status
|
64
|
+
assert File.exists?("/tmp/scale_down/test_images/example_1/scaled/400x300-cropped/graphic.png")
|
65
|
+
assert_match "/test_images/example_1/scaled/400x300-cropped/graphic.png", last_response["Location"]
|
66
66
|
end
|
67
67
|
|
68
68
|
should "get a nonexistant image and return a 404" do
|
69
|
-
valid_get "/
|
69
|
+
valid_get "/test_images/example_none/scaled/400x300/image.jpg"
|
70
70
|
assert_equal 404, last_response.status
|
71
71
|
end
|
72
72
|
|
73
73
|
should "get an invalid image and return a 500" do
|
74
|
-
valid_get '/400x300-cropped/
|
74
|
+
valid_get '/test_images/example_2/scaled/400x300-cropped/invalid_jpeg.jpg'
|
75
75
|
|
76
76
|
assert_equal 500, last_response.status
|
77
77
|
assert !File.exists?("/tmp/scale_down/test_images/example_2/scaled/400x300-cropped/invalid_jpeg.jpg")
|
@@ -4,9 +4,9 @@ require 'cgi'
|
|
4
4
|
|
5
5
|
class ScaleDown::Test < Test::Unit::TestCase
|
6
6
|
|
7
|
-
def signed_image_url(path, filename,
|
8
|
-
hmac = HMAC::SHA1.new("secret").update([path,
|
9
|
-
"http://images.myserver.com#{[path, CGI.escape(filename)
|
7
|
+
def signed_image_url(path, filename, geometry)
|
8
|
+
hmac = HMAC::SHA1.new("secret").update([path, 'scaled', geometry, filename].join("/")).to_s[0...8]
|
9
|
+
"http://images.myserver.com#{[path, 'scaled', geometry, CGI.escape(filename)].join("/")}?#{hmac}"
|
10
10
|
end
|
11
11
|
|
12
12
|
setup do
|
@@ -17,17 +17,17 @@ class ScaleDown::Test < Test::Unit::TestCase
|
|
17
17
|
end
|
18
18
|
|
19
19
|
should "create a URL with the HMAC signature" do
|
20
|
-
hmac = ScaleDown.hmac("/images/
|
20
|
+
hmac = ScaleDown.hmac("/images/scaled/400x300-cropped/graphic.png")
|
21
21
|
assert_equal\
|
22
|
-
"http://images.myserver.com/images/
|
22
|
+
"http://images.myserver.com/images/scaled/400x300-cropped/graphic.png?#{hmac}",
|
23
23
|
signed_image_url("/images","graphic.png","400x300-cropped")
|
24
24
|
end
|
25
25
|
|
26
26
|
should "create a URL when the filename has URI break characters" do
|
27
27
|
filename = "# !%23?.png"
|
28
|
-
hmac = ScaleDown.hmac("/images/#{filename}
|
28
|
+
hmac = ScaleDown.hmac("/images/scaled/400x300-cropped/#{filename}")
|
29
29
|
assert_equal\
|
30
|
-
"http://images.myserver.com/images/#{CGI.escape filename}
|
30
|
+
"http://images.myserver.com/images/scaled/400x300-cropped/#{CGI.escape filename}?#{hmac}",
|
31
31
|
signed_image_url("/images", filename, "400x300-cropped")
|
32
32
|
end
|
33
33
|
end
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: scale_down
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.5.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- John Weir
|
@@ -10,8 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
14
|
-
default_executable:
|
13
|
+
date: 2011-12-09 00:00:00 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: rmagick
|
@@ -118,7 +117,6 @@ files:
|
|
118
117
|
- test/scale_down_test.rb
|
119
118
|
- test/scaled_image_tag_test.rb
|
120
119
|
- test/test_helper.rb
|
121
|
-
has_rdoc: true
|
122
120
|
homepage: http://github.com/jweir/ScaleDown
|
123
121
|
licenses: []
|
124
122
|
|
@@ -142,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
140
|
requirements: []
|
143
141
|
|
144
142
|
rubyforge_project: scale_down
|
145
|
-
rubygems_version: 1.
|
143
|
+
rubygems_version: 1.8.8
|
146
144
|
signing_key:
|
147
145
|
specification_version: 3
|
148
146
|
summary: A Sinatra based server for quickly scaling and serving images. Nothing more.
|