httpimagestore 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -11,7 +11,7 @@ gem "mime-types", "~> 1.17.2"
11
11
  # Add dependencies to develop your gem here.
12
12
  # Include everything needed to run rake, tests, features, etc.
13
13
  group :development do
14
- gem "rspec", "~> 2.3.0"
14
+ gem "rspec", "~> 2.8.0"
15
15
  gem "cucumber", ">= 0"
16
16
  gem "bundler", "~> 1.0.0"
17
17
  gem "jeweler", "~> 1.6.4"
data/Gemfile.lock CHANGED
@@ -56,14 +56,14 @@ GEM
56
56
  rdoc (3.11)
57
57
  json (~> 1.4)
58
58
  rmagick (2.13.1)
59
- rspec (2.3.0)
60
- rspec-core (~> 2.3.0)
61
- rspec-expectations (~> 2.3.0)
62
- rspec-mocks (~> 2.3.0)
63
- rspec-core (2.3.1)
64
- rspec-expectations (2.3.0)
59
+ rspec (2.8.0)
60
+ rspec-core (~> 2.8.0)
61
+ rspec-expectations (~> 2.8.0)
62
+ rspec-mocks (~> 2.8.0)
63
+ rspec-core (2.8.0)
64
+ rspec-expectations (2.8.0)
65
65
  diff-lcs (~> 1.1.2)
66
- rspec-mocks (2.3.0)
66
+ rspec-mocks (2.8.0)
67
67
  ruby-ip (0.9.0)
68
68
  s3 (0.3.9)
69
69
  proxies (~> 0.2.0)
@@ -90,7 +90,7 @@ DEPENDENCIES
90
90
  prawn (= 0.8.4)
91
91
  rcov
92
92
  rdoc (~> 3.9)
93
- rspec (~> 2.3.0)
93
+ rspec (~> 2.8.0)
94
94
  ruby-ip (~> 0.9)
95
95
  s3 (~> 0.3)
96
96
  sinatra (>= 1.2.6)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
data/bin/httpimagestore CHANGED
@@ -17,13 +17,13 @@ options = CLI.new do
17
17
  end.parse!
18
18
 
19
19
  require 'sinatra/base'
20
- require 's3'
21
20
  require 'httpthumbnailer-client'
22
21
  require 'digest/sha2'
23
22
 
24
23
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
25
24
  require 'httpimagestore/configuration'
26
- require 'httpimagestore/pathname'
25
+ require 'httpimagestore/image_path'
26
+ require 'httpimagestore/s3_service'
27
27
 
28
28
  sinatra = Sinatra.new
29
29
 
@@ -43,33 +43,19 @@ sinatra.set :uri_encode, (not options.no_uri_encode)
43
43
 
44
44
  Configuration.from_file(options.config).put(sinatra)
45
45
 
46
- class S3Put
47
- def initialize(key_id, key_secret, bucket, options = {})
48
- @options = options
49
- @logger = (options[:logger] or Logger.new('/dev/null'))
50
-
51
- @s3 = S3::Service.new(:access_key_id => key_id, :secret_access_key => key_secret)
52
-
53
- @logger.info "Getting bucket: #{bucket}"
54
- @bucket = @s3.buckets.find(bucket) or fail "no buckte '#{bucket}' found"
46
+ class ThumbnailingError < RuntimeError
47
+ def initialize(thumbnail_class, remote_error)
48
+ @remote_error = remote_error
49
+ super "Thumbnailing for class '#{thumbnail_class.name}' failed: #{remote_error.message}"
55
50
  end
56
51
 
57
- def put_image(image_path, content_type, data)
58
- @logger.info "Putting image in bucket '#{@bucket.name}': #{image_path}"
59
-
60
- file = @bucket.objects.build(image_path)
61
- file.content_type = content_type
62
- file.content = data
63
- file.save
64
-
65
- "http://#{@bucket.name}.s3.amazonaws.com/#{image_path}"
66
- end
52
+ attr_reader :remote_error
67
53
  end
68
54
 
69
55
  sinatra.before do
70
56
  logger.level = Logger::DEBUG if settings.logging and settings.debug
71
57
  # singletons
72
- $s3 ||= S3Put.new(settings.s3_key_id, settings.s3_key_secret, settings.s3_bucket, :logger => logger)
58
+ $s3 ||= S3Service.new(settings.s3_key_id, settings.s3_key_secret, settings.s3_bucket, :logger => logger)
73
59
  $thumbnailer ||= HTTPThumbnailerClient.new(settings.thumbnailer_url)
74
60
  end
75
61
 
@@ -87,54 +73,42 @@ sinatra.helpers do
87
73
  def digest(data)
88
74
  Digest::SHA2.new.update(data).to_s[0,16]
89
75
  end
90
-
91
- class BadRequestError < RuntimeError
92
- end
93
-
94
- class ThumbnailingError < RuntimeError
95
- def initialize(thumbnail_class, remote_error)
96
- @remote_error = remote_error
97
- super "Thumbnailing for class '#{thumbnail_class.name}' failed: #{remote_error.message}"
98
- end
99
-
100
- attr_reader :remote_error
101
- end
102
76
  end
103
77
 
104
78
  sinatra.get '/' do
105
79
  "hello"
106
80
  end
107
81
 
108
- sinatra.put %r{/thumbnail/([^/]*)/?(.*)} do |classes, image_path|
109
- if image_path.empty?
110
- image_path = Pathname.new(image_path).extend(Pathname::AutoPath)
111
- else
112
- image_path = Pathname.new(image_path).extend(Pathname::CustomPath)
113
- end
82
+ sinatra.put %r{/thumbnail/([^/]*)/?(.*)} do |thumbnail_classes, image_path|
83
+ thumbnail_classes = thumbnail_classes.split(',').map{|thumbnail_class| settings.thumbnail_classes[thumbnail_class]}
114
84
 
115
- classes = classes.split(',').map{|tc| settings.thumbnail_classes[tc]}
116
85
  image = request.body.read
86
+ image_hash = digest(image)
87
+
88
+ unless image_path.empty?
89
+ image_path = ImagePath::Custom.new(image_hash, image_path)
90
+ else
91
+ image_path = ImagePath::Auto.new(image_hash)
92
+ end
117
93
 
118
- thumbs = $thumbnailer.thumbnail(image) do
119
- classes.each do |tc|
120
- thumbnail tc.method, tc.width, tc.height, tc.format, tc.options
94
+ thumbnails = $thumbnailer.thumbnail(image) do
95
+ thumbnail_classes.each do |thumbnail_class|
96
+ thumbnail thumbnail_class.method, thumbnail_class.width, thumbnail_class.height, thumbnail_class.format, thumbnail_class.options
121
97
  end
122
98
  end
123
99
 
124
100
  # check for errors
125
- thumbs.zip(classes).each do |thumb, thumbnail_class|
126
- raise ThumbnailingError.new(thumbnail_class, thumb) if thumb.kind_of? HTTPThumbnailerClient::ThumbnailingError
101
+ thumbnails.zip(thumbnail_classes).each do |thumbnail, thumbnail_class|
102
+ raise ThumbnailingError.new(thumbnail_class, thumbnail) if thumbnail.kind_of? HTTPThumbnailerClient::ThumbnailingError
127
103
  end
128
104
 
129
105
  urls = []
130
106
 
131
- image_hash = digest(image)
132
-
133
107
  # store all images
134
- urls << $s3.put_image(image_path.original_image(image_hash, thumbs.input_mime_type).to_s, thumbs.input_mime_type, image)
108
+ urls << $s3.put_image(image_path.original_image(thumbnails.input_mime_type), thumbnails.input_mime_type, image)
135
109
 
136
- thumbs.zip(classes).each do |thumb, thumbnail_class|
137
- urls << $s3.put_image(image_path.thumbnail_image(image_hash, thumb.mime_type, thumbnail_class.name).to_s, thumb.mime_type, thumb.data)
110
+ thumbnails.zip(thumbnail_classes).each do |thumbnail, thumbnail_class|
111
+ urls << $s3.put_image(image_path.thumbnail_image(thumbnail.mime_type, thumbnail_class.name), thumbnail.mime_type, thumbnail.data)
138
112
  end
139
113
 
140
114
  status 200
@@ -162,10 +136,6 @@ sinatra.error ThumbnailingError do
162
136
  end
163
137
  end
164
138
 
165
- sinatra.error BadRequestError do
166
- halt_exception(400, env['sinatra.error'])
167
- end
168
-
169
139
  sinatra.error Configuration::ThumbnailClassDoesNotExistError do
170
140
  halt_exception(404, env['sinatra.error'])
171
141
  end
@@ -12,7 +12,7 @@ Feature: Storing of original image and specified classes of its thumbnails on S3
12
12
 
13
13
  thumbnail_class 'small', 'crop', 128, 128
14
14
  thumbnail_class 'tiny', 'crop', 32, 32
15
- thumbnail_class 'png', 'crop', 32, 32, 'PNG'
15
+ thumbnail_class 'tiny_png', 'crop', 32, 32, 'PNG'
16
16
  thumbnail_class 'bad', 'crop', 0, 0
17
17
  thumbnail_class 'superlarge', 'crop', 16000, 16000
18
18
  thumbnail_class 'large_png', 'crop', 7000, 7000, 'PNG'
@@ -24,84 +24,74 @@ Feature: Storing of original image and specified classes of its thumbnails on S3
24
24
  Scenario: Putting original and its thumbnails to S3 bucket
25
25
  Given there is no 4006450256177f4a.jpg file in S3 bucket
26
26
  And there is no 4006450256177f4a/small.jpg file in S3 bucket
27
- And there is no 4006450256177f4a/tiny.jpg file in S3 bucket
27
+ And there is no 4006450256177f4a/tiny_png.png file in S3 bucket
28
28
  Given test.jpg file content as request body
29
- When I do PUT request http://localhost:3000/thumbnail/small,tiny
29
+ When I do PUT request http://localhost:3000/thumbnail/small,tiny_png
30
30
  Then response status will be 200
31
31
  And response content type will be text/uri-list
32
32
  And response body will be CRLF ended lines
33
33
  """
34
34
  http://issthumbtest.s3.amazonaws.com/4006450256177f4a.jpg
35
35
  http://issthumbtest.s3.amazonaws.com/4006450256177f4a/small.jpg
36
- http://issthumbtest.s3.amazonaws.com/4006450256177f4a/tiny.jpg
37
- """
38
- And http://issthumbtest.s3.amazonaws.com/4006450256177f4a.jpg will contain JPEG image of size 509x719
39
- And http://issthumbtest.s3.amazonaws.com/4006450256177f4a/small.jpg will contain JPEG image of size 128x128
40
- And http://issthumbtest.s3.amazonaws.com/4006450256177f4a/tiny.jpg will contain JPEG image of size 32x32
36
+ http://issthumbtest.s3.amazonaws.com/4006450256177f4a/tiny_png.png
37
+ """
38
+ Then http://issthumbtest.s3.amazonaws.com/4006450256177f4a.jpg will contain JPEG image of size 509x719
39
+ And http://issthumbtest.s3.amazonaws.com/4006450256177f4a.jpg content type will be image/jpeg
40
+ Then http://issthumbtest.s3.amazonaws.com/4006450256177f4a/small.jpg will contain JPEG image of size 128x128
41
+ And http://issthumbtest.s3.amazonaws.com/4006450256177f4a/small.jpg content type will be image/jpeg
42
+ Then http://issthumbtest.s3.amazonaws.com/4006450256177f4a/tiny_png.png will contain PNG image of size 32x32
43
+ And http://issthumbtest.s3.amazonaws.com/4006450256177f4a/tiny_png.png content type will be image/png
41
44
 
42
45
  Scenario: Putting original and its thumbnails to S3 bucket under custom path
43
46
  Given there is no test/image/4006450256177f4a/test.jpg file in S3 bucket
44
47
  And there is no test/image/4006450256177f4a/test-small.jpg file in S3 bucket
45
- And there is no test/image/4006450256177f4a/test-tiny.jpg file in S3 bucket
48
+ And there is no test/image/4006450256177f4a/test-tiny_png.png file in S3 bucket
46
49
  Given test.jpg file content as request body
47
- When I do PUT request http://localhost:3000/thumbnail/small,tiny/test/image/test.jpg
50
+ When I do PUT request http://localhost:3000/thumbnail/small,tiny_png/test/image/test
48
51
  Then response status will be 200
49
52
  And response content type will be text/uri-list
50
53
  And response body will be CRLF ended lines
51
54
  """
52
55
  http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg
53
56
  http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-small.jpg
54
- http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg
55
- """
56
- And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg will contain JPEG image of size 509x719
57
- And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-small.jpg will contain JPEG image of size 128x128
58
- And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg will contain JPEG image of size 32x32
59
-
60
- Scenario: Putting original and its thumbnails to S3 bucket under custom path with UTF characters (encoded) in the path and name
61
- Given there is no test/图像/4006450256177f4a/测试.jpg file in S3 bucket
62
- And there is no test/图像/4006450256177f4a/测试-small.jpg file in S3 bucket
63
- Given test.jpg file content as request body
64
- When I do PUT request http://localhost:3000/thumbnail/small/test/图像/测试.jpg
65
- Then response status will be 200
66
- And response content type will be text/uri-list
67
- And response body will be CRLF ended lines
68
- """
69
- http://issthumbtest.s3.amazonaws.com/test/%E5%9B%BE%E5%83%8F/4006450256177f4a/%E6%B5%8B%E8%AF%95.jpg
70
- http://issthumbtest.s3.amazonaws.com/test/%E5%9B%BE%E5%83%8F/4006450256177f4a/%E6%B5%8B%E8%AF%95-small.jpg
57
+ http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny_png.png
71
58
  """
72
- And http://issthumbtest.s3.amazonaws.com/test/图像/4006450256177f4a/测试.jpg will contain JPEG image of size 509x719
73
- And http://issthumbtest.s3.amazonaws.com/test/图像/4006450256177f4a/测试-small.jpg will contain JPEG image of size 128x128
59
+ Then http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg will contain JPEG image of size 509x719
60
+ And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg content type will be image/jpeg
61
+ Then http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-small.jpg will contain JPEG image of size 128x128
62
+ And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-small.jpg content type will be image/jpeg
63
+ Then http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny_png.png will contain PNG image of size 32x32
64
+ And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny_png.png content type will be image/png
74
65
 
75
- Scenario: Input image content type determined from content
66
+ Scenario: Custom path name can contain file name extension that may be used as failback to content based detection
76
67
  Given there is no test/image/4006450256177f4a/test.jpg file in S3 bucket
68
+ And there is no test/image/4006450256177f4a/test-tiny_png.jpg file in S3 bucket
77
69
  Given test.jpg file content as request body
78
- And Content-Type header set to application/octet-stream
79
- When I do PUT request http://localhost:3000/thumbnail/tiny/test/image/test.jpg
70
+ When I do PUT request http://localhost:3000/thumbnail/tiny_png/test/image/test.jpg
80
71
  Then response status will be 200
81
72
  And response content type will be text/uri-list
82
73
  And response body will be CRLF ended lines
83
74
  """
84
75
  http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg
85
- http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg
76
+ http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny_png.png
86
77
  """
87
78
  And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg content type will be image/jpeg
79
+ And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny_png.png content type will be image/png
88
80
 
89
- Scenario: Thumbnail image content type and file extension determined from configured format
90
- Given there is no test/image/4006450256177f4a/test.jpg file in S3 bucket
91
- And there is no test/image/4006450256177f4a/test-tiny.jpg file in S3 bucket
92
- And there is no test/image/4006450256177f4a/test-png.png file in S3 bucket
81
+ Scenario: Custom path name encoding when UTF-8 characters can be used
82
+ Given there is no test/图像/4006450256177f4a/测试.jpg file in S3 bucket
83
+ And there is no test/图像/4006450256177f4a/测试-small.jpg file in S3 bucket
93
84
  Given test.jpg file content as request body
94
- When I do PUT request http://localhost:3000/thumbnail/tiny,png/test/image/test.jpg
85
+ When I do PUT request http://localhost:3000/thumbnail/small/test/图像/测试
95
86
  Then response status will be 200
96
87
  And response content type will be text/uri-list
97
88
  And response body will be CRLF ended lines
98
89
  """
99
- http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test.jpg
100
- http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg
101
- http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-png.png
90
+ http://issthumbtest.s3.amazonaws.com/test/%E5%9B%BE%E5%83%8F/4006450256177f4a/%E6%B5%8B%E8%AF%95.jpg
91
+ http://issthumbtest.s3.amazonaws.com/test/%E5%9B%BE%E5%83%8F/4006450256177f4a/%E6%B5%8B%E8%AF%95-small.jpg
102
92
  """
103
- And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-tiny.jpg content type will be image/jpeg
104
- And http://issthumbtest.s3.amazonaws.com/test/image/4006450256177f4a/test-png.png content type will be image/png
93
+ And http://issthumbtest.s3.amazonaws.com/test/图像/4006450256177f4a/测试.jpg will contain JPEG image of size 509x719
94
+ And http://issthumbtest.s3.amazonaws.com/test/图像/4006450256177f4a/测试-small.jpg will contain JPEG image of size 128x128
105
95
 
106
96
  Scenario: Reporting of missing resource
107
97
  When I do GET request http://localhost:3000/blah
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "httpimagestore"
8
- s.version = "0.2.0"
8
+ s.version = "0.2.1"
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"]
@@ -35,10 +35,11 @@ Gem::Specification.new do |s|
35
35
  "features/support/test.txt",
36
36
  "httpimagestore.gemspec",
37
37
  "lib/httpimagestore/configuration.rb",
38
- "lib/httpimagestore/pathname.rb",
38
+ "lib/httpimagestore/image_path.rb",
39
+ "lib/httpimagestore/s3_service.rb",
39
40
  "lib/httpimagestore/thumbnail_class.rb",
40
41
  "spec/configuration_spec.rb",
41
- "spec/pathname_spec.rb",
42
+ "spec/image_path_spec.rb",
42
43
  "spec/spec_helper.rb",
43
44
  "spec/test.cfg"
44
45
  ]
@@ -59,7 +60,7 @@ Gem::Specification.new do |s|
59
60
  s.add_runtime_dependency(%q<ruby-ip>, ["~> 0.9"])
60
61
  s.add_runtime_dependency(%q<cli>, ["~> 1.1.0"])
61
62
  s.add_runtime_dependency(%q<mime-types>, ["~> 1.17.2"])
62
- s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
63
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
63
64
  s.add_development_dependency(%q<cucumber>, [">= 0"])
64
65
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
65
66
  s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
@@ -76,7 +77,7 @@ Gem::Specification.new do |s|
76
77
  s.add_dependency(%q<ruby-ip>, ["~> 0.9"])
77
78
  s.add_dependency(%q<cli>, ["~> 1.1.0"])
78
79
  s.add_dependency(%q<mime-types>, ["~> 1.17.2"])
79
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
80
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
80
81
  s.add_dependency(%q<cucumber>, [">= 0"])
81
82
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
82
83
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
@@ -94,7 +95,7 @@ Gem::Specification.new do |s|
94
95
  s.add_dependency(%q<ruby-ip>, ["~> 0.9"])
95
96
  s.add_dependency(%q<cli>, ["~> 1.1.0"])
96
97
  s.add_dependency(%q<mime-types>, ["~> 1.17.2"])
97
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
98
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
98
99
  s.add_dependency(%q<cucumber>, [">= 0"])
99
100
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
100
101
  s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
@@ -0,0 +1,54 @@
1
+ require 'mime/types'
2
+ require 'pathname'
3
+
4
+ class ImagePath
5
+ class CouldNotDetermineFileExtensionError < ArgumentError
6
+ def initialize(mime_type)
7
+ super "could not determine file extension for mime type: #{mime_type}"
8
+ end
9
+ end
10
+
11
+ def initialize(id)
12
+ @id = id.to_s
13
+ end
14
+
15
+ private
16
+
17
+ def mime_extension(mime_type)
18
+ mime = MIME::Types[mime_type].first or raise CouldNotDetermineFileExtensionError, mime_type
19
+ '.' + (mime.extensions.select{|e| e.length == 3}.first or mime.extensions.first)
20
+ end
21
+
22
+ class Auto < ImagePath
23
+ def original_image(mime_type)
24
+ "#{@id}#{mime_extension(mime_type)}"
25
+ end
26
+
27
+ def thumbnail_image(mime_type, thumbnail_class)
28
+ "#{@id}/#{thumbnail_class}#{mime_extension(mime_type)}"
29
+ end
30
+ end
31
+
32
+ class Custom < ImagePath
33
+ def initialize(id, path)
34
+ super(id)
35
+ @path = Pathname.new(path)
36
+ end
37
+
38
+ def original_image(mime_type)
39
+ extension = begin
40
+ mime_extension(mime_type)
41
+ rescue CouldNotDetermineFileExtensionError
42
+ raise if @path.extname.empty?
43
+ @path.extname
44
+ end
45
+
46
+ (@path.dirname + @id + "#{@path.basename(@path.extname)}#{extension}").to_s
47
+ end
48
+
49
+ def thumbnail_image(mime_type, thumbnail_class)
50
+ (@path.dirname + @id + "#{@path.basename(@path.extname)}-#{thumbnail_class}#{mime_extension(mime_type)}").to_s
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,25 @@
1
+ require 's3'
2
+
3
+ class S3Service
4
+ def initialize(key_id, key_secret, bucket, options = {})
5
+ @options = options
6
+ @logger = (options[:logger] or Logger.new('/dev/null'))
7
+
8
+ @s3 = S3::Service.new(:access_key_id => key_id, :secret_access_key => key_secret)
9
+
10
+ @logger.info "Getting bucket: #{bucket}"
11
+ @bucket = @s3.buckets.find(bucket) or fail "no buckte '#{bucket}' found"
12
+ end
13
+
14
+ def put_image(image_path, content_type, data)
15
+ @logger.info "Putting image in bucket '#{@bucket.name}': #{image_path}"
16
+
17
+ file = @bucket.objects.build(image_path)
18
+ file.content_type = content_type
19
+ file.content = data
20
+ file.save
21
+
22
+ "http://#{@bucket.name}.s3.amazonaws.com/#{image_path}"
23
+ end
24
+ end
25
+
@@ -0,0 +1,72 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'httpimagestore/image_path'
3
+ require 'pathname'
4
+
5
+ shared_examples "extension handling" do |image_path|
6
+ describe "#original_image" do
7
+ it "determines extension based on mime type" do
8
+ Pathname.new(image_path.original_image("image/jpeg")).extname.should == ".jpg"
9
+ Pathname.new(image_path.original_image("image/tiff")).extname.should == ".tif"
10
+ Pathname.new(image_path.original_image("image/png")).extname.should == ".png"
11
+ end
12
+
13
+ it "should fail if provided extension from mime type could not be determined" do
14
+ lambda {
15
+ image_path.original_image("image/xyz")
16
+ }.should raise_error ImagePath::CouldNotDetermineFileExtensionError, "could not determine file extension for mime type: image/xyz"
17
+ end
18
+ end
19
+
20
+ describe "#thumbnail_image" do
21
+ it "determines extension based on mime type" do
22
+ Pathname.new(image_path.thumbnail_image("image/jpeg", "small")).extname.should == ".jpg"
23
+ Pathname.new(image_path.thumbnail_image("image/tiff", "small")).extname.should == ".tif"
24
+ Pathname.new(image_path.thumbnail_image("image/png", "small")).extname.should == ".png"
25
+ end
26
+
27
+ it "should fail if provided extension from mime type could not be determined" do
28
+ lambda {
29
+ image_path.thumbnail_image("image/xyz", "small")
30
+ }.should raise_error ImagePath::CouldNotDetermineFileExtensionError, "could not determine file extension for mime type: image/xyz"
31
+ end
32
+ end
33
+ end
34
+
35
+ describe ImagePath do
36
+ describe ImagePath::Auto do
37
+ describe "#original_image" do
38
+ it "returns path in format <id>.<ext>" do
39
+ ImagePath::Auto.new(123).original_image("image/jpeg").should == "123.jpg"
40
+ end
41
+ end
42
+
43
+ describe "#thumbnail_image" do
44
+ it "returns path in format <id>/<class>.<ext>" do
45
+ ImagePath::Auto.new(123).thumbnail_image("image/jpeg", "small").should == "123/small.jpg"
46
+ end
47
+ end
48
+
49
+ include_examples "extension handling", ImagePath::Auto.new(123)
50
+ end
51
+
52
+ describe ImagePath::Custom do
53
+ describe "#original_image" do
54
+ it "returns path in format abc/<id>/xyz.<ext>" do
55
+ ImagePath::Custom.new(123, "test/file/path.jpg").original_image("image/jpeg").should == "test/file/123/path.jpg"
56
+ end
57
+
58
+ it "should fail back to provided extension if extension from mime type could not be determined" do
59
+ Pathname.new(ImagePath::Custom.new(123, "test/file/path.abc").original_image("image/xyz")).extname.should == ".abc"
60
+ end
61
+ end
62
+
63
+ describe "#thumbnail_image" do
64
+ it "returns path in format abc/<id>/xyz-<class>.<ext>" do
65
+ ImagePath::Custom.new(123, "test/file/path.jpg").thumbnail_image("image/jpeg", "small").should == "test/file/123/path-small.jpg"
66
+ end
67
+ end
68
+
69
+ include_examples "extension handling", ImagePath::Custom.new(123, "test/file/path")
70
+ end
71
+ end
72
+
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: 23
4
+ hash: 21
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 2
9
- - 0
10
- version: 0.2.0
9
+ - 1
10
+ version: 0.2.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jakub Pastuszek
@@ -134,12 +134,12 @@ dependencies:
134
134
  requirements:
135
135
  - - ~>
136
136
  - !ruby/object:Gem::Version
137
- hash: 3
137
+ hash: 47
138
138
  segments:
139
139
  - 2
140
- - 3
140
+ - 8
141
141
  - 0
142
- version: 2.3.0
142
+ version: 2.8.0
143
143
  prerelease: false
144
144
  name: rspec
145
145
  version_requirements: *id008
@@ -291,10 +291,11 @@ files:
291
291
  - features/support/test.txt
292
292
  - httpimagestore.gemspec
293
293
  - lib/httpimagestore/configuration.rb
294
- - lib/httpimagestore/pathname.rb
294
+ - lib/httpimagestore/image_path.rb
295
+ - lib/httpimagestore/s3_service.rb
295
296
  - lib/httpimagestore/thumbnail_class.rb
296
297
  - spec/configuration_spec.rb
297
- - spec/pathname_spec.rb
298
+ - spec/image_path_spec.rb
298
299
  - spec/spec_helper.rb
299
300
  - spec/test.cfg
300
301
  homepage: http://github.com/jpastuszek/httpimagestore
@@ -1,33 +0,0 @@
1
- require 'mime/types'
2
-
3
- class Pathname
4
- def mime_extension(mime_type)
5
- mime = MIME::Types[mime_type].first or return extname
6
- '.' + (mime.extensions.select{|e| e.length == 3}.first or mime.extensions.first)
7
- end
8
-
9
- module AutoPath
10
- # <id>.<ext>
11
- def original_image(id, mime_type)
12
- "#{id.to_s}#{mime_extension(mime_type)}"
13
- end
14
-
15
- # <id>/<class>.<ext>
16
- def thumbnail_image(id, mime_type, thumbnail_class)
17
- "#{id.to_s}/#{thumbnail_class}#{mime_extension(mime_type)}"
18
- end
19
- end
20
-
21
- module CustomPath
22
- # abc/xyz.jpg => abc/<id>/xyz.jpg
23
- def original_image(id, mime_type)
24
- dirname + id.to_s + basename
25
- end
26
-
27
- # abc/xyz.jpg => abc/<id>/xyz-<class>.jpg
28
- def thumbnail_image(id, mime_type, thumbnail_class)
29
- dirname + id.to_s + "#{basename(extname)}-#{thumbnail_class}#{mime_extension(mime_type)}"
30
- end
31
- end
32
- end
33
-
@@ -1,17 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
- require 'httpimagestore/pathname'
3
-
4
- describe Pathname do
5
- describe "#original_image" do
6
- it "returns path with tid" do
7
- Pathname.new("test/file/path.jpg").original_image(123).to_s.should == "test/file/123/path.jpg"
8
- end
9
- end
10
-
11
- describe "#thumbnail_image" do
12
- it "returns path with tid and thumbnail class name in file name" do
13
- Pathname.new("test/file/path.jpg").thumbnail_image(123, 'small').to_s.should == "test/file/123/path-small.jpg"
14
- end
15
- end
16
- end
17
-