httpimagestore 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source "http://rubygems.org"
3
3
  gem "sinatra", ">= 1.2.6"
4
4
  gem "mongrel", ">= 1.1.5"
5
5
  gem "s3", "~> 0.3"
6
- gem "httpthumbnailer-client", "~> 0.0.1"
6
+ gem "httpthumbnailer-client", "~> 0.0.3"
7
7
 
8
8
  # Add dependencies to develop your gem here.
9
9
  # Include everything needed to run rake, tests, features, etc.
@@ -15,5 +15,5 @@ group :development do
15
15
  gem "rcov", ">= 0"
16
16
  gem "rdoc", "~> 3.9"
17
17
  gem "daemon", "~> 1"
18
- gem "httpthumbnailer", "~> 0.0.1"
18
+ gem "httpthumbnailer", "~> 0.0.7"
19
19
  end
data/Gemfile.lock CHANGED
@@ -3,10 +3,10 @@ GEM
3
3
  specs:
4
4
  builder (3.0.0)
5
5
  cgi_multipart_eof_fix (2.5.0)
6
- cucumber (1.1.2)
6
+ cucumber (1.1.3)
7
7
  builder (>= 2.1.2)
8
8
  diff-lcs (>= 1.1.2)
9
- gherkin (~> 2.6.2)
9
+ gherkin (~> 2.6.7)
10
10
  json (>= 1.4.6)
11
11
  term-ansicolor (>= 1.0.6)
12
12
  daemon (1.1.0)
@@ -14,23 +14,23 @@ GEM
14
14
  diff-lcs (1.1.3)
15
15
  fastthread (1.0.7)
16
16
  gem_plugin (0.2.3)
17
- gherkin (2.6.5)
17
+ gherkin (2.6.8)
18
18
  json (>= 1.4.6)
19
19
  git (1.2.5)
20
- haml (3.1.3)
20
+ haml (3.1.4)
21
21
  httpclient (2.2.3)
22
- httpthumbnailer (0.0.1)
22
+ httpthumbnailer (0.0.7)
23
23
  haml (~> 3)
24
24
  mongrel (>= 1.1.5)
25
25
  rmagick (~> 2)
26
26
  sinatra (>= 1.2.6)
27
- httpthumbnailer-client (0.0.1)
27
+ httpthumbnailer-client (0.0.3)
28
28
  httpclient (>= 2.2.1)
29
29
  jeweler (1.6.4)
30
30
  bundler (~> 1.0)
31
31
  git (>= 1.2.5)
32
32
  rake
33
- json (1.6.1)
33
+ json (1.6.2)
34
34
  mongrel (1.1.5)
35
35
  cgi_multipart_eof_fix (>= 2.4)
36
36
  daemons (>= 1.0.3)
@@ -42,7 +42,8 @@ GEM
42
42
  rack
43
43
  rake (0.9.2.2)
44
44
  rcov (0.9.11)
45
- rdoc (3.9.4)
45
+ rdoc (3.11)
46
+ json (~> 1.4)
46
47
  rmagick (2.13.1)
47
48
  rspec (2.3.0)
48
49
  rspec-core (~> 2.3.0)
@@ -68,8 +69,8 @@ DEPENDENCIES
68
69
  bundler (~> 1.0.0)
69
70
  cucumber
70
71
  daemon (~> 1)
71
- httpthumbnailer (~> 0.0.1)
72
- httpthumbnailer-client (~> 0.0.1)
72
+ httpthumbnailer (~> 0.0.7)
73
+ httpthumbnailer-client (~> 0.0.3)
73
74
  jeweler (~> 1.6.4)
74
75
  mongrel (>= 1.1.5)
75
76
  rcov
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
data/bin/httpimagestore CHANGED
@@ -45,19 +45,36 @@ end
45
45
 
46
46
  sinatra.before do
47
47
  # singletons
48
- @s3 ||= S3Put.new(settings.s3_key_id, settings.s3_key_secret, settings.s3_bucket, :logger => logger)
49
- @thumbnailer ||= HTTPThumbnailerClient.new(settings.thumbnailer_url)
48
+ $s3 ||= S3Put.new(settings.s3_key_id, settings.s3_key_secret, settings.s3_bucket, :logger => logger)
49
+ $thumbnailer ||= HTTPThumbnailerClient.new(settings.thumbnailer_url)
50
50
  end
51
51
 
52
52
  sinatra.helpers do
53
- def plain_exception(exception)
53
+ def hatl_response(status, msg)
54
54
  headers "Content-Type" => "text/plain"
55
- body "Error: #{exception.class.name}: #{exception}\n"
55
+ body msg.gsub("\n", "\r\n") + "\r\n"
56
+ halt status
57
+ end
58
+
59
+ def halt_exception(status, exception)
60
+ hatl_response(status, "Error: #{exception.class.name}: #{exception}")
56
61
  end
57
62
 
58
63
  def digest(data)
59
64
  Digest::SHA2.new.update(data).to_s[0,16]
60
65
  end
66
+
67
+ class BadRequestError < RuntimeError
68
+ end
69
+
70
+ class ThumbnailingError < RuntimeError
71
+ def initialize(thumbnail_class, remote_error)
72
+ @remote_error = remote_error
73
+ super "Thumbnailing for class '#{thumbnail_class.name}' failed: #{remote_error.message}"
74
+ end
75
+
76
+ attr_reader :remote_error
77
+ end
61
78
  end
62
79
 
63
80
  sinatra.get '/' do
@@ -65,22 +82,31 @@ sinatra.get '/' do
65
82
  end
66
83
 
67
84
  sinatra.put %r{/thumbnail/([^/]*)/(.*)} do |classes, image_path|
68
- urls = []
85
+ raise BadRequestError, "Path is empty" if image_path.empty?
86
+ image_path = Pathname.new(image_path)
69
87
 
70
- classes = classes.split(',').map{|tc| settings.thumbnail_classes[tc] or fail "Class '#{tc}' not configured"}
88
+ classes = classes.split(',').map{|tc| settings.thumbnail_classes[tc]}
71
89
  image = request.body.read
72
90
  image_hash = digest(image)
73
91
 
74
- urls << @s3.put_image(Pathname.new(image_path).original_image(image_hash).to_s, response.headers['Content-Type'], image)
75
-
76
- thumbs = @thumbnailer.thumbnail(image) do
92
+ thumbs = $thumbnailer.thumbnail(image) do
77
93
  classes.each do |tc|
78
94
  thumbnail tc.method, tc.width, tc.height, tc.format, tc.options
79
95
  end
80
96
  end
81
97
 
98
+ # check for errors
99
+ thumbs.zip(classes).each do |thumb, thumbnail_class|
100
+ raise ThumbnailingError.new(thumbnail_class, thumb) if thumb.kind_of? HTTPThumbnailerClient::ThumbnailingError
101
+ end
102
+
103
+ urls = []
104
+
105
+ # store all images
106
+ urls << $s3.put_image(image_path.original_image(image_hash).to_s, response.headers['Content-Type'], image)
107
+
82
108
  thumbs.zip(classes).each do |thumb, thumbnail_class|
83
- urls << @s3.put_image(Pathname.new(image_path).thumbnail_image(image_hash, thumbnail_class.name).to_s, thumb.mime_type, thumb.data)
109
+ urls << $s3.put_image(image_path.thumbnail_image(image_hash, thumbnail_class.name).to_s, thumb.mime_type, thumb.data)
84
110
  end
85
111
 
86
112
  status 200
@@ -88,9 +114,45 @@ sinatra.put %r{/thumbnail/([^/]*)/(.*)} do |classes, image_path|
88
114
  body urls.map{|u| u + "\r\n"}.join
89
115
  end
90
116
 
117
+ sinatra.error HTTPThumbnailerClient::UnsupportedMediaTypeError do
118
+ halt_exception(415, env['sinatra.error'])
119
+ end
120
+
121
+ sinatra.error HTTPThumbnailerClient::ImageTooLargeError do
122
+ halt_exception(413, env['sinatra.error'])
123
+ end
124
+
125
+ # problem with singe thumbnail
126
+ sinatra.error ThumbnailingError do
127
+ e = env['sinatra.error']
128
+ case e.remote_error.type
129
+ when "Thumbnailer::ImageTooLargeError"
130
+ halt_exception(413, e)
131
+ else
132
+ halt_exception(500, e)
133
+ end
134
+ end
135
+
136
+ sinatra.error BadRequestError do
137
+ halt_exception(400, env['sinatra.error'])
138
+ end
139
+
140
+ sinatra.error Configuration::ThumbnailClassDoesNotExistError do
141
+ halt_exception(404, env['sinatra.error'])
142
+ end
143
+
144
+ sinatra.error Sinatra::NotFound do
145
+ hatl_response(404, "Resource '#{request.path_info}' not found")
146
+ end
147
+
91
148
  sinatra.error do
92
- plain_exception(env['sinatra.error'])
149
+ halt_exception(500, env['sinatra.error'])
93
150
  end
94
151
 
95
- sinatra.run!
152
+ begin
153
+ sinatra.run!
154
+ rescue Errno::EACCES, Errno::EADDRNOTAVAIL, SocketError => e
155
+ puts "Error: failed to bind HTTP server socket (#{options[:bind]}): #{e}"
156
+ exit 5
157
+ end
96
158
 
@@ -4,29 +4,117 @@ Feature: Original image and it's thumnails generation and storing on S2
4
4
  The respons will be paths to files storred in S3
5
5
 
6
6
  Background:
7
+ Given httpimagestore log is empty
7
8
  Given httpimagestore server is running at http://localhost:3000/ with the following configuration
8
9
  """
9
10
  s3_key 'AKIAJMUYVYOSACNXLPTQ', 'MAeGhvW+clN7kzK3NboASf3/kZ6a81PRtvwMZj4Y'
10
- s3_bucket 'rhthumbnails'
11
+ s3_bucket 'issthumbtest'
11
12
 
12
13
  thumbnail_class 'small', 'crop', 128, 128
13
14
  thumbnail_class 'tiny', 'crop', 32, 32
15
+ thumbnail_class 'bad', 'crop', 0, 0
16
+ thumbnail_class 'superlarge', 'crop', 16000, 16000
14
17
  """
18
+ Given httpthumbnailer log is empty
15
19
  Given httpthumbnailer server is running at http://localhost:3100/
20
+ Given issthumbtest S3 bucket with key AKIAJMUYVYOSACNXLPTQ and secret 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
16
21
 
17
22
  Scenario: Putting thumbnails and original to S3 bucket
23
+ Given there is no test/image/4006450256177f4a/test.jpg file in S3 bucket
24
+ And there is no test/image/4006450256177f4a/test-small.jpg file in S3 bucket
25
+ And there is no test/image/4006450256177f4a/test-tiny.jpg file in S3 bucket
18
26
  Given test.jpg file content as request body
19
27
  When I do PUT request http://localhost:3000/thumbnail/small,tiny/test/image/test.jpg
20
28
  Then response status will be 200
21
29
  And response content type will be text/uri-list
22
30
  And response body will be CRLF endend lines
23
31
  """
24
- http://rhthumbnails.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg
25
- http://rhthumbnails.s3.amazonaws.com/test/image/4006450256177f4a/test-small.jpg
26
- http://rhthumbnails.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg
32
+ http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg
33
+ http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-small.jpg
34
+ http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg
35
+ """
36
+ And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg will contain JPEG image of size 509x719
37
+ And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-small.jpg will contain JPEG image of size 128x128
38
+ And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg will contain JPEG image of size 32x32
39
+
40
+ Scenario: Reporitng of missing resource
41
+ When I do GET request http://localhost:3000/blah
42
+ Then response status will be 404
43
+ And response content type will be text/plain
44
+ And response body will be CRLF endend lines
45
+ """
46
+ Resource '/blah' not found
47
+ """
48
+
49
+ Scenario: Reporitng of unsupported media type
50
+ Given there is no test/image/4006450256177f4a/test.jpg file in S3 bucket
51
+ And there is no test/image/4006450256177f4a/test-small.jpg file in S3 bucket
52
+ And there is no test/image/4006450256177f4a/test-tiny.jpg file in S3 bucket
53
+ Given test.txt file content as request body
54
+ When I do PUT request http://localhost:3000/thumbnail/small,tiny/test/image/test.jpg
55
+ Then response status will be 415
56
+ And response content type will be text/plain
57
+ And response body will be CRLF endend lines like
58
+ """
59
+ Error: HTTPThumbnailerClient::UnsupportedMediaTypeError:
60
+ """
61
+ And S3 bucket will not contain test/image/4006450256177f4a/test.jpg
62
+ And S3 bucket will not contain test/image/4006450256177f4a/test-small.jpg
63
+ And S3 bucket will not contain test/image/4006450256177f4a/test-tiny.jpg
64
+
65
+ Scenario: Reporitng and handling of thumbnailing errors
66
+ Given there is no test/image/4006450256177f4a/test.jpg file in S3 bucket
67
+ And there is no test/image/4006450256177f4a/test-small.jpg file in S3 bucket
68
+ And there is no test/image/4006450256177f4a/test-tiny.jpg file in S3 bucket
69
+ Given test.jpg file content as request body
70
+ When I do PUT request http://localhost:3000/thumbnail/small,tiny,bad/test/image/test.jpg
71
+ Then response status will be 500
72
+ And response content type will be text/plain
73
+ And response body will be CRLF endend lines like
74
+ """
75
+ Error: ThumbnailingError: Thumbnailing for class 'bad' failed: Error: ArgumentError:
76
+ """
77
+ And S3 bucket will not contain test/image/4006450256177f4a/test.jpg
78
+ And S3 bucket will not contain test/image/4006450256177f4a/test-small.jpg
79
+ And S3 bucket will not contain test/image/4006450256177f4a/test-tiny.jpg
27
80
 
81
+ Scenario: Reporting of missing class error
82
+ Given test.jpg file content as request body
83
+ When I do PUT request http://localhost:3000/thumbnail/small,bogous,bad/test/image/test.jpg
84
+ Then response status will be 404
85
+ And response content type will be text/plain
86
+ And response body will be CRLF endend lines like
87
+ """
88
+ Error: Configuration::ThumbnailClassDoesNotExistError: Class 'bogous' does not exist
89
+ """
90
+
91
+ Scenario: Handling of bad path
92
+ Given test.jpg file content as request body
93
+ When I do PUT request http://localhost:3000/thumbnail/small/
94
+ Then response status will be 400
95
+ And response content type will be text/plain
96
+ And response body will be CRLF endend lines like
97
+ """
98
+ Error: BadRequestError: Path is empty
99
+ """
100
+
101
+ Scenario: Too large image - uploaded image too big to load
102
+ Given test-large.jpg file content as request body
103
+ When I do PUT request http://localhost:3000/thumbnail/small/test/image/test.jpg
104
+ Then response status will be 413
105
+ And response content type will be text/plain
106
+ And response body will be CRLF endend lines like
107
+ """
108
+ Error: HTTPThumbnailerClient::ImageTooLargeError:
109
+ """
110
+
111
+ Scenario: Too large image - memory exhausted when thmbnailing
112
+ Given test.jpg file content as request body
113
+ When I do PUT request http://localhost:3000/thumbnail/superlarge/test/image/test.jpg
114
+ Then response status will be 413
115
+ And response content type will be text/plain
116
+ And response body will be CRLF endend lines like
117
+ """
118
+ Error: ThumbnailingError: Thumbnailing for class 'superlarge' failed: Error: Thumbnailer::ImageTooLargeError:
28
119
  """
29
- And http://rhthumbnails.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg will contain JPEG image of size 509x719
30
- And http://rhthumbnails.s3.amazonaws.com/test/image/4006450256177f4a/test-small.jpg will contain JPEG image of size 128x128
31
- And http://rhthumbnails.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg will contain JPEG image of size 32x32
32
120
 
@@ -24,10 +24,26 @@ Given /httpthumbnailer server is running at (.*)/ do |url|
24
24
  )
25
25
  end
26
26
 
27
+ Given /httpimagestore log is empty/ do
28
+ (support_dir + 'server.log').truncate(0)
29
+ end
30
+
31
+ Given /httpthumbnailer log is empty/ do
32
+ (support_dir + 'thumbniler.log').truncate(0)
33
+ end
34
+
27
35
  Given /(.*) file content as request body/ do |file|
28
36
  @request_body = File.open(support_dir + file){|f| f.read }
29
37
  end
30
38
 
39
+ Given /(.*) S3 bucket with key (.*) and secret (.*)/ do |bucket, key_id, key_secret|
40
+ @bucket = S3::Service.new(:access_key_id => key_id, :secret_access_key => key_secret).buckets.find(bucket)
41
+ end
42
+
43
+ Given /there is no (.*) file in S3 bucket/ do |path|
44
+ @bucket.objects.find(path).destroy rescue S3::Error::NoSuchKey
45
+ end
46
+
31
47
  When /I do (.*) request (.*)/ do |method, uri|
32
48
  @response = HTTPClient.new.request(method, uri, nil, @request_body)
33
49
  end
@@ -40,18 +56,34 @@ Then /response content type will be (.*)/ do |content_type|
40
56
  @response.header['Content-Type'].first.should == content_type
41
57
  end
42
58
 
43
- Then /response body will be CRLF endend lines/ do |body|
44
- @response.body.should == body.gsub!("\n", "\r\n")
59
+ Then /response body will be CRLF endend lines like/ do |body|
60
+ @response.body.should match(body)
61
+ @response.body.each do |line|
62
+ line[-2,2].should == "\r\n"
63
+ end
64
+ end
65
+
66
+ Then /response body will be CRLF endend lines$/ do |body|
67
+ @response.body.should == body.gsub("\n", "\r\n") + "\r\n"
45
68
  end
46
69
 
47
- Then /(.*) will contain (.*) image of size (.*)/ do |url, image_type, image_size|
70
+ Then /(.*) will contain (.*) image of size (.*)x(.*)/ do |url, format, width, height|
48
71
  data = get(url)
49
- Open3.popen3('identify -') do |stdin, stdout, stderr|
50
- stdin.write data
51
- stdin.close
52
- path, type, size, *rest = *stdout.read.split(' ')
53
- type.should == image_type
54
- size.should == image_size
72
+
73
+ @image.destroy! if @image
74
+ @image = Magick::Image.from_blob(data).first
75
+
76
+ @image.format.should == format
77
+ @image.columns.should == width.to_i
78
+ @image.rows.should == height.to_i
79
+ end
80
+
81
+ Then /S3 bucket will not contain (.*)/ do |path|
82
+ begin
83
+ @bucket.objects.find(path)
84
+ true.should eq(false, "object #{path} found in bucket")
85
+ rescue S3::Error::NoSuchKey
86
+ true.should == true
55
87
  end
56
88
  end
57
89
 
@@ -16,6 +16,8 @@ require 'httpclient'
16
16
  require "open3"
17
17
  require "thread"
18
18
  require 'tempfile'
19
+ require 'RMagick'
20
+ require 's3'
19
21
 
20
22
  def gem_dir
21
23
  Pathname.new(__FILE__).dirname + '..' + '..'
Binary file
@@ -0,0 +1 @@
1
+ hello world
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "httpimagestore"
8
- s.version = "0.0.3"
8
+ s.version = "0.0.4"
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-25"
12
+ s.date = "2011-11-30"
13
13
  s.description = "Thumbnails images using httpthumbnailer and stored data on HTTP server (S3)"
14
14
  s.email = "jpastuszek@gmail.com"
15
15
  s.executables = ["httpimagestore"]
@@ -30,7 +30,9 @@ Gem::Specification.new do |s|
30
30
  "features/httpimagestore.feature",
31
31
  "features/step_definitions/httpimagestore_steps.rb",
32
32
  "features/support/env.rb",
33
+ "features/support/test-large.jpg",
33
34
  "features/support/test.jpg",
35
+ "features/support/test.txt",
34
36
  "httpimagestore.gemspec",
35
37
  "lib/httpimagestore/configuration.rb",
36
38
  "lib/httpimagestore/pathname.rb",
@@ -53,7 +55,7 @@ Gem::Specification.new do |s|
53
55
  s.add_runtime_dependency(%q<sinatra>, [">= 1.2.6"])
54
56
  s.add_runtime_dependency(%q<mongrel>, [">= 1.1.5"])
55
57
  s.add_runtime_dependency(%q<s3>, ["~> 0.3"])
56
- s.add_runtime_dependency(%q<httpthumbnailer-client>, ["~> 0.0.1"])
58
+ s.add_runtime_dependency(%q<httpthumbnailer-client>, ["~> 0.0.3"])
57
59
  s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
58
60
  s.add_development_dependency(%q<cucumber>, [">= 0"])
59
61
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
@@ -61,12 +63,12 @@ Gem::Specification.new do |s|
61
63
  s.add_development_dependency(%q<rcov>, [">= 0"])
62
64
  s.add_development_dependency(%q<rdoc>, ["~> 3.9"])
63
65
  s.add_development_dependency(%q<daemon>, ["~> 1"])
64
- s.add_development_dependency(%q<httpthumbnailer>, ["~> 0.0.1"])
66
+ s.add_development_dependency(%q<httpthumbnailer>, ["~> 0.0.7"])
65
67
  else
66
68
  s.add_dependency(%q<sinatra>, [">= 1.2.6"])
67
69
  s.add_dependency(%q<mongrel>, [">= 1.1.5"])
68
70
  s.add_dependency(%q<s3>, ["~> 0.3"])
69
- s.add_dependency(%q<httpthumbnailer-client>, ["~> 0.0.1"])
71
+ s.add_dependency(%q<httpthumbnailer-client>, ["~> 0.0.3"])
70
72
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
71
73
  s.add_dependency(%q<cucumber>, [">= 0"])
72
74
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
@@ -74,13 +76,13 @@ Gem::Specification.new do |s|
74
76
  s.add_dependency(%q<rcov>, [">= 0"])
75
77
  s.add_dependency(%q<rdoc>, ["~> 3.9"])
76
78
  s.add_dependency(%q<daemon>, ["~> 1"])
77
- s.add_dependency(%q<httpthumbnailer>, ["~> 0.0.1"])
79
+ s.add_dependency(%q<httpthumbnailer>, ["~> 0.0.7"])
78
80
  end
79
81
  else
80
82
  s.add_dependency(%q<sinatra>, [">= 1.2.6"])
81
83
  s.add_dependency(%q<mongrel>, [">= 1.1.5"])
82
84
  s.add_dependency(%q<s3>, ["~> 0.3"])
83
- s.add_dependency(%q<httpthumbnailer-client>, ["~> 0.0.1"])
85
+ s.add_dependency(%q<httpthumbnailer-client>, ["~> 0.0.3"])
84
86
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
85
87
  s.add_dependency(%q<cucumber>, [">= 0"])
86
88
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
@@ -88,7 +90,7 @@ Gem::Specification.new do |s|
88
90
  s.add_dependency(%q<rcov>, [">= 0"])
89
91
  s.add_dependency(%q<rdoc>, ["~> 3.9"])
90
92
  s.add_dependency(%q<daemon>, ["~> 1"])
91
- s.add_dependency(%q<httpthumbnailer>, ["~> 0.0.1"])
93
+ s.add_dependency(%q<httpthumbnailer>, ["~> 0.0.7"])
92
94
  end
93
95
  end
94
96
 
@@ -2,8 +2,17 @@ require 'httpimagestore/thumbnail_class'
2
2
  require 'pathname'
3
3
 
4
4
  class Configuration
5
+ class ThumbnailClassDoesNotExistError < RuntimeError
6
+ def initialize(name)
7
+ super "Class '#{name}' does not exist"
8
+ end
9
+ end
10
+
5
11
  def initialize(&block)
6
- @thumbnail_classes = {}
12
+ @thumbnail_classes = Hash.new do |h, k|
13
+ raise ThumbnailClassDoesNotExistError, k
14
+ end
15
+
7
16
  @thumbnailer_url = "http://localhost:3100"
8
17
 
9
18
  @port = 3000
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpimagestore
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
9
+ - 4
10
+ version: 0.0.4
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-25 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
@@ -71,12 +71,12 @@ dependencies:
71
71
  requirements:
72
72
  - - ~>
73
73
  - !ruby/object:Gem::Version
74
- hash: 29
74
+ hash: 25
75
75
  segments:
76
76
  - 0
77
77
  - 0
78
- - 1
79
- version: 0.0.1
78
+ - 3
79
+ version: 0.0.3
80
80
  prerelease: false
81
81
  name: httpthumbnailer-client
82
82
  version_requirements: *id004
@@ -192,12 +192,12 @@ dependencies:
192
192
  requirements:
193
193
  - - ~>
194
194
  - !ruby/object:Gem::Version
195
- hash: 29
195
+ hash: 17
196
196
  segments:
197
197
  - 0
198
198
  - 0
199
- - 1
200
- version: 0.0.1
199
+ - 7
200
+ version: 0.0.7
201
201
  prerelease: false
202
202
  name: httpthumbnailer
203
203
  version_requirements: *id012
@@ -223,7 +223,9 @@ files:
223
223
  - features/httpimagestore.feature
224
224
  - features/step_definitions/httpimagestore_steps.rb
225
225
  - features/support/env.rb
226
+ - features/support/test-large.jpg
226
227
  - features/support/test.jpg
228
+ - features/support/test.txt
227
229
  - httpimagestore.gemspec
228
230
  - lib/httpimagestore/configuration.rb
229
231
  - lib/httpimagestore/pathname.rb