Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Improvements to testing, gravity and cropping, now uses Mapel, not Mi…

…ni::Magick
  • Loading branch information...
commit a2b5028059a838de5ba22a9d5b1e5c3ef7d25cea 1 parent 5fc8437
Lee Hambley authored
6 example/config.ru
View
@@ -0,0 +1,6 @@
+require 'rubygems'
+require 'bundler/setup'
+
+require 'rack-thumb-proxy'
+
+run Rack::Thumb::Proxy
101 lib/rack-thumb-proxy.rb
View
@@ -42,7 +42,7 @@ def call
format_response!
response.finish
else
- [404, {'Content-Length' => 9}, ['Not Found']]
+ [404, {'Content-Length' => 9.to_s, 'Content-Type' => 'text/plain'}, ['Not Found']]
end
end
@@ -55,6 +55,7 @@ def validate_signature!
def retreive_upstream!
begin
open(request_url, 'rb') do |f|
+ tempfile.binmode
tempfile.write(f.read)
tempfile.flush
end
@@ -67,7 +68,8 @@ def retreive_upstream!
def format_response!
response.status = 200
- response.headers["Content-Length"] = transformed_image_file_size_in_bytes
+ response.headers["Content-Type"] = mime_type_from_request_url
+ response.headers["Content-Length"] = transformed_image_file_size_in_bytes.to_s
response.body << read_tempfile
true
end
@@ -78,23 +80,57 @@ def read_tempfile
end
def tempfile
- @_tempfile ||= Tempfile.new(escaped_request_url)
+ @_tempfile ||= Tempfile.new('rack_thumb_proxy')
+ end
+
+ def tempfile_path
+ tempfile.path
end
def transform_image!
- return true if request_options.empty?
+
+ return true unless should_resize?
+
begin
- require 'mini_magick'
- mmi = MiniMagick::Image.open(tempfile.path)
- mmi.resize(request_options)
- mmi.write tempfile.path
+ require 'mapel'
+
+ width, height = dimensions_from_request_options
+ owidth, oheight = dimensions_from_tempfile
+
+ width = [width, owidth].min if width
+ height = [height, oheight].min if height
+
+ cmd = Mapel(tempfile_path)
+
+ if should_apply_gravity?
+ cmd.gravity(request_gravity)
+ end
+
+ if width && height
+ cmd.resize!(width, height)
+ else
+ cmd.resize(width, height, 0, 0, '>')
+ end
+
+ cmd.to(tempfile_path).run
+
rescue
+ puts $!, $@
write_error_to_response!
return false
end
+
true
end
+ def should_resize?
+ !request_options.empty?
+ end
+
+ def should_apply_gravity?
+ !!request_gravity_shorthand
+ end
+
def should_verify_hash_signature?
configuration.hash_signatures_in_use?
end
@@ -122,11 +158,12 @@ def request_gravity
'sw' => :southwest,
's' => :south,
'se' => :southeast
- }.fetch(request_gravity_shorthand, nil) if request_gravity_shorthand
+ }.fetch(request_gravity_shorthand).to_s if request_gravity_shorthand
end
def request_gravity_shorthand
- @_request_match_data["gravity"]
+ g = @_request_match_data["gravity"]
+ g.empty? ? nil : g
end
def request_url
@@ -141,8 +178,34 @@ def request_matches?
@_request_match_data = @path.match(routing_pattern)
end
+ def witdh_from_tempfile
+ dimensions_from_tempfile.first
+ end
+
+ def height_from_tempfile
+ dimensions_from_tempfile.last
+ end
+
+ def dimensions_from_tempfile
+ require 'mapel' unless defined?(Mapel)
+ Mapel.info(tempfile_path)[:dimensions]
+ end
+
+ def width_from_request_options
+ dimensions_from_request_options.first
+ end
+
+ def height_from_request_options
+ dimensions_from_request_options.last
+ end
+
+ def dimensions_from_request_options
+ width, height = request_options.split('x').map(&:to_i).collect { |dim| dim == 0 ? nil : dim }
+ [width, height]
+ end
+
def transformed_image_file_size_in_bytes
- ::File.size(tempfile.path)
+ ::File.size(tempfile_path)
end
# Examples: http://rubular.com/r/oPRK1t31yv
@@ -156,7 +219,23 @@ def response
def write_error_to_response!
response.status = 500
+ response.headers['Content-Type'] = 'text/plain'
response.body << $!.message
+ response.body << "\n\n"
+ response.body << $!.backtrace.join("\n")
+ end
+
+ def request_url_file_extension
+ ::File.extname(request_url)
+ end
+
+ def mime_type_from_request_url
+ {
+ '.png' => 'image/png',
+ '.gif' => 'image/gif',
+ '.jpg' => 'image/jpg',
+ '.jpeg' => 'image/jpeg'
+ }.fetch(request_url_file_extension)
end
end
6 rack-thumb-proxy.gemspec
View
@@ -5,8 +5,8 @@ Gem::Specification.new do |gem|
gem.authors = ["Lee Hambley"]
gem.email = ["lee.hambley@gmail.com"]
- gem.description = %q{TODO: Write a gem description}
- gem.summary = %q{TODO: Write a gem summary}
+ gem.description = %q{ Rack middleware for resizing proxied requests for images which don't reside on your own servers. }
+ gem.summary = %q{ For more information see https://github.com/leehambley/rack-thumb-proxy }
gem.homepage = ""
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
@@ -22,7 +22,7 @@ Gem::Specification.new do |gem|
gem.add_development_dependency 'minitest', '~> 2.11'
gem.add_development_dependency 'webmock', '~> 1.8.0'
gem.add_development_dependency 'rack-test', '~> 0.6.1'
+ gem.add_development_dependency 'mapel'
gem.add_development_dependency 'dimensions'
- gem.add_development_dependency 'mini_magick'
end
2  test/test_helper.rb
View
@@ -20,4 +20,4 @@
WebMock.disable_net_connect!
require 'ruby-debug'
-require 'mini_magick'
+require 'mapel'
16 test/test_rack_thumb_proxy.rb
View
@@ -14,8 +14,8 @@ def test_it_should_repond_with_not_found_when_the_upstream_url_is_bunk
end
def test_it_should_return_success_with_the_correct_content_length_when_a_matching_url_is_found_for_a_noop_image
- stub_image_request!('250x.gif', 'http://www.example.com/images/kittens.gif')
- get '/' + escape('http://www.example.com/images/kittens.gif')
+ stub_image_request!('250x.gif', 'http://www.example.com/images/noop-kittens.gif')
+ get '/' + escape('http://www.example.com/images/noop-kittens.gif')
assert last_response.ok?
assert_equal file_size_for_fixture('250x.gif').to_s, last_response.headers.fetch('Content-Length')
assert_equal file_hash_for_fixture('250x.gif'), file_hash_from_string(last_response.body)
@@ -29,6 +29,13 @@ def test_it_should_return_a_smaller_image_when_resizing_with_minimagick
assert_dimensions last_response.body, 50, 50
end
+ def test_it_should_crop_when_the_ratio_cannot_be_maintained
+ stub_image_request!('200x100.gif', 'http://www.example.com/images/sharkjumping.gif')
+ get '/50x50/' + escape('http://www.example.com/images/sharkjumping.gif')
+ assert last_response.ok?
+ assert_dimensions last_response.body, 50, 50
+ end
+
def test_it_should_retain_the_aspec_ratio
stub_image_request!('200x100.gif', 'http://www.example.com/images/sharkjumping.gif')
get '/50x/' + escape('http://www.example.com/images/sharkjumping.gif')
@@ -37,7 +44,6 @@ def test_it_should_retain_the_aspec_ratio
end
def test_it_should_accept_the_gravity_setting_without_breaking_the_resize
- skip
stub_image_request!('200x100.gif', 'http://www.example.com/images/sharkjumping.gif')
get '/50x50e/' + escape('http://www.example.com/images/sharkjumping.gif')
assert last_response.ok?
@@ -48,6 +54,10 @@ def test_it_should_accept_the_gravity_setting_without_breaking_the_resize
refute_equal file_hash_from_string(east), file_hash_from_string(west)
end
+ def test_should_respond_with_the_proper_mimetype
+
+ end
+
private
def stub_image_request!(file, url)
Please sign in to comment.
Something went wrong with that request. Please try again.