scale_down 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.rdoc +53 -23
- data/config_sample.ru +15 -4
- data/lib/scale_down/scaler.rb +3 -18
- data/lib/scale_down/version.rb +1 -1
- data/lib/scale_down.rb +16 -0
- data/test/scale_down/scaler_test.rb +8 -18
- data/test/scale_down_test.rb +53 -27
- data/test/scaled_image_tag_test.rb +6 -8
- data/test/test_helper.rb +1 -1
- metadata +3 -3
data/Gemfile.lock
CHANGED
data/README.rdoc
CHANGED
@@ -8,54 +8,85 @@ Images are scaled based upon their URL. An HMAC signature is used to prevent mal
|
|
8
8
|
|
9
9
|
For example
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
[ image server address ][ image source ][ size ][ hmac ]
|
12
|
+
http://images.example.com/images/logo.png/400x300/A3SDACEDF
|
13
13
|
|
14
|
-
|
14
|
+
would 301 redirect to the scaled image
|
15
15
|
|
16
|
-
|
16
|
+
http://images.example.com/images/scaled/logo-400x300.png
|
17
17
|
|
18
18
|
To crop an image include the 'cropped' option
|
19
19
|
|
20
|
-
|
20
|
+
http://images.example.com/images/logo.png/400x300-cropped/A3SDACEDF
|
21
21
|
|
22
22
|
Use 'auto' to have an image scale to one dimension or another.
|
23
23
|
|
24
24
|
For example, to ensure an image is 300 pixels wide
|
25
25
|
|
26
|
-
|
26
|
+
http://images.example.com/images/logo.png/300xauto/A3SDACEDF
|
27
27
|
|
28
|
+
== Installation and Configuration
|
28
29
|
|
29
|
-
|
30
|
+
gem install scale_down
|
30
31
|
|
31
|
-
|
32
|
-
ScaleDown::Scaler.hmac_method = HMAC::MD5
|
33
|
-
ScaleDown::Scaler.hmac_length = 8
|
34
|
-
ScaleDown::Scaler.root_path = "/tmp/scale_down"
|
32
|
+
Create a rackup file (config.ru)
|
35
33
|
|
36
|
-
|
34
|
+
require 'scale_down'
|
37
35
|
|
38
|
-
|
36
|
+
ScaleDown.tap do |config|
|
39
37
|
|
40
|
-
#
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
# This is the shared secret. Use something strong
|
39
|
+
# Perhaps a visit to http://www.random.org/strings/?num=10&len=20&digits=on&upperalpha=on&format=html&rnd=new
|
40
|
+
config.hmac_key = "secret"
|
41
|
+
|
42
|
+
# You can use a different HMAC, see the ruby-hmac gen
|
43
|
+
config.hmac_method = HMAC::SHA1
|
44
|
+
|
45
|
+
# The length of the HMAC signature to use
|
46
|
+
config.hmac_length = 8
|
47
|
+
|
48
|
+
# The root path to the images. Use a symlink if it is helpful
|
49
|
+
config.root_path = File.expand_path(File.dirname(__FILE__))+"/public"
|
50
|
+
end
|
51
|
+
|
52
|
+
run ScaleDown::Controller
|
53
|
+
|
54
|
+
Start the server using whatever server you want.
|
55
|
+
|
56
|
+
thin start -p 3002
|
57
|
+
|
58
|
+
|
59
|
+
== Generating the URL
|
60
|
+
|
61
|
+
In your application with the images you will need to generate the URL for the image source.
|
62
|
+
|
63
|
+
require 'HMAC::SHA1'
|
64
|
+
|
65
|
+
# ie scaled_image_src('/images/picture.png/400x300-cropped')
|
66
|
+
def scaled_image_src(url)
|
67
|
+
hmac = HMAC::SHA1.new("secret").update(url).to_s[0...8]
|
68
|
+
"http://images.myserver.com#{url}/#{hmac}"
|
69
|
+
end
|
70
|
+
|
71
|
+
Of course this could be done in PHP, Python, or whatever language your application is running.
|
45
72
|
|
46
73
|
== TODO
|
47
74
|
|
48
75
|
This thing is brand spankin new and is in flux - expect changes.
|
49
76
|
|
50
77
|
Define a max image size (do not scale images over this size).
|
78
|
+
|
51
79
|
Support DELETE requests to remove scaled images.
|
52
|
-
|
80
|
+
|
81
|
+
Custom Read/Write methods to allow for more than just local storage.
|
53
82
|
|
54
83
|
== Dependencies
|
55
84
|
|
56
|
-
Sinatra
|
57
|
-
RMagick
|
58
|
-
Ruby-HMAC
|
85
|
+
* Sinatra
|
86
|
+
* RMagick
|
87
|
+
* Ruby-HMAC
|
88
|
+
|
89
|
+
RMagick can be a bit tricky to install, these links[http://www.google.com/search?q=install+rmagick] might help.
|
59
90
|
|
60
91
|
== License
|
61
92
|
|
@@ -70,4 +101,3 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
70
101
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
71
102
|
|
72
103
|
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
73
|
-
|
data/config_sample.ru
CHANGED
@@ -1,8 +1,19 @@
|
|
1
1
|
require 'scale_down'
|
2
2
|
|
3
|
-
ScaleDown
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
ScaleDown.tap do |config|
|
4
|
+
|
5
|
+
# This is the shared secret. Use something strong
|
6
|
+
# Perhaps a visit to http://www.random.org/strings/?num=10&len=20&digits=on&upperalpha=on&format=html&rnd=new
|
7
|
+
config.hmac_key = "secret"
|
8
|
+
|
9
|
+
# You can use a different HMAC, see the ruby-hmac gen
|
10
|
+
config.hmac_method = HMAC::SHA1
|
11
|
+
|
12
|
+
# The length of the HMAC signature to use
|
13
|
+
config.hmac_length = 8
|
14
|
+
|
15
|
+
# The root path to the images
|
16
|
+
config.root_path = File.expand_path(File.dirname(__FILE__))+"/public"
|
17
|
+
end
|
7
18
|
|
8
19
|
run ScaleDown::Controller
|
data/lib/scale_down/scaler.rb
CHANGED
@@ -1,12 +1,6 @@
|
|
1
|
-
require 'RMagick'
|
2
|
-
require 'hmac-md5'
|
3
|
-
require 'hmac-sha1'
|
4
|
-
|
5
1
|
class ScaleDown::Scaler
|
6
2
|
|
7
3
|
class << self
|
8
|
-
attr_accessor :hmac_method, :hmac_key, :hmac_length
|
9
|
-
attr_accessor :root_path
|
10
4
|
|
11
5
|
def process(params)
|
12
6
|
scaler = new(params)
|
@@ -20,15 +14,6 @@ class ScaleDown::Scaler
|
|
20
14
|
["Error message", 403]
|
21
15
|
end
|
22
16
|
end
|
23
|
-
|
24
|
-
def valid_hmac?(params)
|
25
|
-
str = [params[:path], "/", params[:filename], "/", params[:geometry]].join
|
26
|
-
hmac(str) == params[:hmac]
|
27
|
-
end
|
28
|
-
|
29
|
-
def hmac(string)
|
30
|
-
hmac_method.new(hmac_key).update(string).to_s[0...hmac_length]
|
31
|
-
end
|
32
17
|
end
|
33
18
|
|
34
19
|
def initialize(params)
|
@@ -51,7 +36,7 @@ class ScaleDown::Scaler
|
|
51
36
|
end
|
52
37
|
|
53
38
|
def valid_hmac?
|
54
|
-
|
39
|
+
ScaleDown.valid_hmac?(@params)
|
55
40
|
end
|
56
41
|
|
57
42
|
def redirect_path
|
@@ -67,11 +52,11 @@ class ScaleDown::Scaler
|
|
67
52
|
end
|
68
53
|
|
69
54
|
def root_path
|
70
|
-
File.join(
|
55
|
+
File.join(ScaleDown.root_path, @params[:path], @params[:filename])
|
71
56
|
end
|
72
57
|
|
73
58
|
def scaled_file_path
|
74
|
-
File.join(
|
59
|
+
File.join(ScaleDown.root_path, redirect_path)
|
75
60
|
end
|
76
61
|
|
77
62
|
def scaled_filename
|
data/lib/scale_down/version.rb
CHANGED
data/lib/scale_down.rb
CHANGED
@@ -3,10 +3,26 @@ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
|
|
3
3
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'sinatra'
|
6
|
+
require 'RMagick'
|
7
|
+
require 'hmac-sha1'
|
6
8
|
|
7
9
|
module ScaleDown
|
8
10
|
require 'scale_down/version'
|
9
11
|
require 'scale_down/controller'
|
10
12
|
require 'scale_down/scaler'
|
11
13
|
require 'scale_down/image'
|
14
|
+
|
15
|
+
class << self
|
16
|
+
attr_accessor :hmac_method, :hmac_key, :hmac_length
|
17
|
+
attr_accessor :root_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.valid_hmac?(params)
|
21
|
+
str = ["/",params[:path], "/", params[:filename], "/", params[:geometry]].join
|
22
|
+
hmac(str) == params[:hmac]
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.hmac(string)
|
26
|
+
hmac_method.new(hmac_key).update(string).to_s[0...hmac_length]
|
27
|
+
end
|
12
28
|
end
|
@@ -4,12 +4,12 @@ class ScaleDown::Scaler::Test < Test::Unit::TestCase
|
|
4
4
|
|
5
5
|
context "Scaler::Test" do
|
6
6
|
setup do
|
7
|
-
ScaleDown
|
8
|
-
ScaleDown
|
9
|
-
ScaleDown
|
10
|
-
ScaleDown
|
7
|
+
ScaleDown.hmac_key = "secret"
|
8
|
+
ScaleDown.hmac_method = HMAC::SHA1
|
9
|
+
ScaleDown.hmac_length = 8
|
10
|
+
ScaleDown.root_path = "/tmp"
|
11
11
|
|
12
|
-
hmac = HMAC::
|
12
|
+
hmac = HMAC::SHA1.new("secret").update("file/path/filename.png/400x300-crop").to_s
|
13
13
|
|
14
14
|
@params = {
|
15
15
|
:path => "file/path",
|
@@ -19,23 +19,13 @@ class ScaleDown::Scaler::Test < Test::Unit::TestCase
|
|
19
19
|
}
|
20
20
|
end
|
21
21
|
|
22
|
-
context "HMAC" do
|
23
|
-
should "validate when the params match the HMAC signature" do
|
24
|
-
assert ScaleDown::Scaler.valid_hmac?(@params)
|
25
|
-
end
|
26
|
-
|
27
|
-
should "not validate when the params do not match the HMAC signature" do
|
28
|
-
assert !ScaleDown::Scaler.valid_hmac?(@params.merge(:path => "file/different"))
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
22
|
context "instance" do
|
33
23
|
setup do
|
34
24
|
@scaler = ScaleDown::Scaler.new @params
|
35
25
|
end
|
36
26
|
|
37
27
|
should "validate the HMAC" do
|
38
|
-
ScaleDown
|
28
|
+
ScaleDown.expects(:valid_hmac?).with(@params).returns true
|
39
29
|
assert @scaler.valid_hmac?
|
40
30
|
end
|
41
31
|
|
@@ -89,7 +79,7 @@ class ScaleDown::Scaler::Test < Test::Unit::TestCase
|
|
89
79
|
|
90
80
|
context "with a valid HMAC" do
|
91
81
|
setup do
|
92
|
-
ScaleDown
|
82
|
+
ScaleDown.expects(:valid_hmac?).returns true
|
93
83
|
ScaleDown::Image.expects(:scale).returns true
|
94
84
|
end
|
95
85
|
|
@@ -104,7 +94,7 @@ class ScaleDown::Scaler::Test < Test::Unit::TestCase
|
|
104
94
|
|
105
95
|
context "without a valid HMAC" do
|
106
96
|
should "return a 403 Forbidden response" do
|
107
|
-
ScaleDown
|
97
|
+
ScaleDown.expects(:valid_hmac?).returns false
|
108
98
|
assert_equal 403, ScaleDown::Scaler.process(@params)[1]
|
109
99
|
end
|
110
100
|
end
|
data/test/scale_down_test.rb
CHANGED
@@ -8,43 +8,69 @@ class ScaleDown::Test < Test::Unit::TestCase
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def valid_get(path)
|
11
|
-
get "
|
11
|
+
get "#{path}/#{ScaleDown.hmac(path)}"
|
12
12
|
end
|
13
13
|
|
14
|
-
context "
|
14
|
+
context "ScaleDown" do
|
15
15
|
setup do
|
16
|
-
ScaleDown
|
17
|
-
ScaleDown
|
18
|
-
ScaleDown
|
19
|
-
ScaleDown
|
20
|
-
|
21
|
-
FileUtils.mkdir_p("/tmp/scale_down/test_images/example_1")
|
22
|
-
FileUtils.cp tests_path("files/graphic.png"), "/tmp/scale_down/test_images/example_1/graphic.png"
|
23
|
-
FileUtils.mkdir_p("/tmp/scale_down/test_images/example_2")
|
24
|
-
FileUtils.cp tests_path("files/invalid_jpeg.jpg"), "/tmp/scale_down/test_images/example_2/invalid_jpeg.jpg"
|
16
|
+
ScaleDown.hmac_key = "secret"
|
17
|
+
ScaleDown.hmac_method = HMAC::SHA1
|
18
|
+
ScaleDown.hmac_length = 8
|
19
|
+
ScaleDown.root_path = "/tmp/scale_down"
|
25
20
|
end
|
26
21
|
|
27
|
-
|
28
|
-
|
29
|
-
|
22
|
+
context "HMAC" do
|
23
|
+
setup do
|
24
|
+
hmac = HMAC::SHA1.new("secret").update("/file/path/filename.png/400x300-crop").to_s
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
26
|
+
@params = {
|
27
|
+
:path => "file/path",
|
28
|
+
:filename => "filename.png",
|
29
|
+
:geometry => "400x300-crop",
|
30
|
+
:hmac => hmac[0...8]
|
31
|
+
}
|
32
|
+
end
|
37
33
|
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
should "validate when the params match the HMAC signature" do
|
35
|
+
assert ScaleDown.valid_hmac?(@params)
|
36
|
+
end
|
37
|
+
|
38
|
+
should "not validate when the params do not match the HMAC signature" do
|
39
|
+
assert !ScaleDown.valid_hmac?(@params.merge(:path => "file/different"))
|
40
|
+
end
|
41
41
|
end
|
42
42
|
|
43
|
-
should "get an invalid image and return a 403" do
|
44
|
-
valid_get 'test_images/example_2/invalid_jpeg.jpg/400x300-cropped'
|
45
43
|
|
46
|
-
|
47
|
-
|
44
|
+
context "integration test" do
|
45
|
+
setup do
|
46
|
+
FileUtils.mkdir_p("/tmp/scale_down/test_images/example_1")
|
47
|
+
FileUtils.cp tests_path("files/graphic.png"), "/tmp/scale_down/test_images/example_1/graphic.png"
|
48
|
+
FileUtils.mkdir_p("/tmp/scale_down/test_images/example_2")
|
49
|
+
FileUtils.cp tests_path("files/invalid_jpeg.jpg"), "/tmp/scale_down/test_images/example_2/invalid_jpeg.jpg"
|
50
|
+
end
|
51
|
+
|
52
|
+
teardown do
|
53
|
+
FileUtils.rm_r("/tmp/scale_down")
|
54
|
+
end
|
55
|
+
|
56
|
+
should "get an image and scale it" do
|
57
|
+
valid_get '/test_images/example_1/graphic.png/400x300-cropped'
|
58
|
+
assert_equal 301, last_response.status
|
59
|
+
assert_equal "/test_images/example_1/scaled/graphic-400x300-cropped.png", last_response["Location"]
|
60
|
+
assert File.exists?("/tmp/scale_down/test_images/example_1/scaled/graphic-400x300-cropped.png")
|
61
|
+
end
|
62
|
+
|
63
|
+
should "get a nonexistant image and return a 404" do
|
64
|
+
valid_get "/test_exmaples/example_none/image.jpg"
|
65
|
+
assert_equal 404, last_response.status
|
66
|
+
end
|
67
|
+
|
68
|
+
should "get an invalid image and return a 403" do
|
69
|
+
valid_get '/test_images/example_2/invalid_jpeg.jpg/400x300-cropped'
|
70
|
+
|
71
|
+
assert_equal 403, last_response.status
|
72
|
+
assert !File.exists?("/tmp/scale_down/test_images/example_2/scaled/invalid_jpeg-400x300-cropped.jpg")
|
73
|
+
end
|
48
74
|
end
|
49
75
|
end
|
50
76
|
end
|
@@ -3,21 +3,19 @@ require File.expand_path(File.dirname(__FILE__))+'/test_helper'
|
|
3
3
|
class ScaleDown::Test < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def scaled_image_src(url)
|
6
|
-
hmac = HMAC::
|
6
|
+
hmac = HMAC::SHA1.new("secret").update(url).to_s[0...8]
|
7
7
|
"http://images.myserver.com#{url}/#{hmac}"
|
8
8
|
end
|
9
9
|
|
10
10
|
setup do
|
11
|
-
ScaleDown
|
12
|
-
ScaleDown
|
13
|
-
ScaleDown
|
14
|
-
ScaleDown
|
11
|
+
ScaleDown.hmac_key = "secret"
|
12
|
+
ScaleDown.hmac_method = HMAC::SHA1
|
13
|
+
ScaleDown.hmac_length = 8
|
14
|
+
ScaleDown.root_path = "/tmp"
|
15
15
|
end
|
16
16
|
|
17
17
|
should "create a URL with the HMAC signature" do
|
18
|
-
hmac = ScaleDown
|
18
|
+
hmac = ScaleDown.hmac("/images/graphic.png/400x300-cropped")
|
19
19
|
assert_equal "http://images.myserver.com/images/graphic.png/400x300-cropped/#{hmac}", scaled_image_src("/images/graphic.png/400x300-cropped")
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
23
|
-
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scale_down
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- John Weir
|