httpthumbnailer 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.5
1
+ 0.0.6
data/bin/httpthumbnailer CHANGED
@@ -18,11 +18,14 @@ sinatra.set :lock, true
18
18
  sinatra.set :boundary, "thumnail image data"
19
19
  sinatra.set :logging, true
20
20
  sinatra.set :debug, true
21
+ sinatra.set :limit_memory, 128*10**6 # B (keep in mem)
22
+ sinatra.set :limit_map, 256*10**6 # B (if not fit in mem, map to disk)
23
+ sinatra.set :limit_disk, 0 # B (if not fit in map use standard IO)
21
24
 
22
25
  sinatra.before do
23
26
  logger.level = Logger::DEBUG if settings.debug == true
24
27
  if $thumbnailer.nil?
25
- $thumbnailer = Thumbnailer.new(:logger => logger)
28
+ $thumbnailer = Thumbnailer.new(:logger => logger, :limit_memory => settings.limit_memory, :limit_map => settings.limit_map, :limit_disk => settings.limit_disk)
26
29
 
27
30
  $thumbnailer.method('crop') do |image, spec|
28
31
  image.resize_to_fill!(spec.width, spec.height)
@@ -100,6 +103,11 @@ sinatra.error Thumbnailer::UnsupportedMediaTypeError do
100
103
  halt 415
101
104
  end
102
105
 
106
+ sinatra.error Thumbnailer::ImageTooLargeError do
107
+ plain_exception(env['sinatra.error'])
108
+ halt 413
109
+ end
110
+
103
111
  sinatra.error 404 do
104
112
  plain_response("Resource '#{request.path_info}' not found")
105
113
  end
@@ -141,3 +141,30 @@ Feature: Generating set of thumbnails with single PUT request
141
141
  And third part mime type will be image/jpeg
142
142
  And there will be no leaked images
143
143
 
144
+ Scenario: Memory limits exhausted while loading
145
+ Given test-large.jpg file content as request body
146
+ When I do PUT request http://localhost:3100/thumbnail/crop,16,16,PNG
147
+ Then response status will be 413
148
+ And response content type will be text/plain
149
+ And response body will be CRLF endend lines like
150
+ """
151
+ Error: Thumbnailer::ImageTooLargeError: Magick::ImageMagickError: cache resources exhausted
152
+ """
153
+ And there will be no leaked images
154
+
155
+ Scenario: Memory limits exhausted while thumbnailing
156
+ Given test.jpg file content as request body
157
+ When I do PUT request http://localhost:3100/thumbnail/crop,16,16,PNG/crop,16000,16000,JPG/crop,16,32,JPEG
158
+ Then response status will be 200
159
+ And I will get multipart response
160
+ Then first part will contain PNG image of size 16x16
161
+ And first part mime type will be image/png
162
+ And second part content type will be text/plain
163
+ And second part body will be CRLF endend lines like
164
+ """
165
+ Error: Magick::ImageMagickError: cache resources exhausted
166
+ """
167
+ Then third part will contain JPEG image of size 16x32
168
+ And third part mime type will be image/jpeg
169
+ And there will be no leaked images
170
+
@@ -55,6 +55,14 @@ Then /(.*) part body will be CRLF endend lines$/ do |part, body|
55
55
  @response_multipart.part[part_no(part)].body.should == body.gsub("\n", "\r\n") + "\r\n"
56
56
  end
57
57
 
58
+ Then /(.*) part body will be CRLF endend lines like$/ do |part, body|
59
+ pbody = @response_multipart.part[part_no(part)].body
60
+ pbody.should match(body)
61
+ pbody.each do |line|
62
+ line[-2,2].should == "\r\n"
63
+ end
64
+ end
65
+
58
66
  Then /(.*) part will contain (.*) image of size (.*)x(.*)/ do |part, format, width, height|
59
67
  mime = @response_multipart.part[part_no(part)].header['Content-Type']
60
68
  data = @response_multipart.part[part_no(part)].body
@@ -77,7 +85,6 @@ And /that image pixel at (.*)x(.*) will be of color (.*)/ do |x, y, color|
77
85
  @image.pixel_color(x.to_i, y.to_i).to_color.sub(/^#/, '0x').should == color
78
86
  end
79
87
 
80
-
81
88
  And /there will be no leaked images/ do
82
89
  HTTPClient.new.get_content("http://localhost:3100/stats/images").to_i.should == 0
83
90
  end
Binary file
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "httpthumbnailer"
8
- s.version = "0.0.5"
8
+ s.version = "0.0.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jakub Pastuszek"]
12
- s.date = "2011-11-29"
12
+ s.date = "2011-11-30"
13
13
  s.description = "Provides HTTP API for thumbnailing images"
14
14
  s.email = "jpastuszek@gmail.com"
15
15
  s.executables = ["httpthumbnailer"]
@@ -30,6 +30,7 @@ Gem::Specification.new do |s|
30
30
  "features/httpthumbnailer.feature",
31
31
  "features/step_definitions/httpthumbnailer_steps.rb",
32
32
  "features/support/env.rb",
33
+ "features/support/test-large.jpg",
33
34
  "features/support/test-transparent.png",
34
35
  "features/support/test.jpg",
35
36
  "features/support/test.txt",
@@ -50,6 +50,12 @@ class Thumbnailer
50
50
  end
51
51
  end
52
52
 
53
+ class ImageTooLargeError < ArgumentError
54
+ def initialize(e)
55
+ super("#{e.class.name}: #{e}")
56
+ end
57
+ end
58
+
53
59
  class ImageHandler
54
60
  class ImageDestroyedError < RuntimeError
55
61
  def initialize
@@ -86,6 +92,7 @@ class Thumbnailer
86
92
  begin
87
93
  @image = Magick::Image.from_blob(io.read).first.strip!
88
94
  rescue Magick::ImageMagickError => e
95
+ raise ImageTooLargeError, e if e.message =~ /cache resources exhausted/
89
96
  raise UnsupportedMediaTypeError, e
90
97
  end
91
98
  @methods = methods
@@ -126,6 +133,11 @@ class Thumbnailer
126
133
 
127
134
  @logger.info "Initializing thumbniler"
128
135
 
136
+ set_limit(:area, options[:limit_area]) if options.member?(:limit_area)
137
+ set_limit(:memory, options[:limit_memory]) if options.member?(:limit_memory)
138
+ set_limit(:map, options[:limit_map]) if options.member?(:limit_map)
139
+ set_limit(:disk, options[:limit_disk]) if options.member?(:limit_disk)
140
+
129
141
  @images = 0
130
142
  Magick.trace_proc = lambda do |which, description, id, method|
131
143
  case which
@@ -159,5 +171,10 @@ class Thumbnailer
159
171
  def method(method, &impl)
160
172
  @methods[method] = impl
161
173
  end
174
+
175
+ def set_limit(limit, value)
176
+ old = Magick.limit_resource(limit, value)
177
+ @logger.info "Changed limit of #{limit} from #{old} to #{value}"
178
+ end
162
179
  end
163
180
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpthumbnailer
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 5
10
- version: 0.0.5
9
+ - 6
10
+ version: 0.0.6
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jakub Pastuszek
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-29 00:00:00 Z
18
+ date: 2011-11-30 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  type: :runtime
@@ -219,6 +219,7 @@ files:
219
219
  - features/httpthumbnailer.feature
220
220
  - features/step_definitions/httpthumbnailer_steps.rb
221
221
  - features/support/env.rb
222
+ - features/support/test-large.jpg
222
223
  - features/support/test-transparent.png
223
224
  - features/support/test.jpg
224
225
  - features/support/test.txt