httpthumbnailer-client 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -12,5 +12,5 @@ group :development do
12
12
  gem "rcov", ">= 0"
13
13
  gem "rdoc", "~> 3.9"
14
14
  gem "daemon", "~> 1"
15
- gem "httpthumbnailer", "~> 0.0.1"
15
+ gem "httpthumbnailer", "~> 0.0.5"
16
16
  end
data/Gemfile.lock CHANGED
@@ -17,9 +17,9 @@ GEM
17
17
  gherkin (2.6.7)
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.5)
23
23
  haml (~> 3)
24
24
  mongrel (>= 1.1.5)
25
25
  rmagick (~> 2)
@@ -64,7 +64,7 @@ DEPENDENCIES
64
64
  cucumber
65
65
  daemon (~> 1)
66
66
  httpclient (>= 2.2.1)
67
- httpthumbnailer (~> 0.0.1)
67
+ httpthumbnailer (~> 0.0.5)
68
68
  jeweler (~> 1.6.4)
69
69
  rcov
70
70
  rdoc (~> 3.9)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "httpthumbnailer-client"
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
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-23"
12
+ s.date = "2011-11-29"
13
13
  s.description = "Thumbnails images using httpthumbniler server"
14
14
  s.email = "jpastuszek@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -33,7 +33,8 @@ Gem::Specification.new do |s|
33
33
  "spec/httpthumbnailer-client_spec.rb",
34
34
  "spec/multipart_response_spec.rb",
35
35
  "spec/spec_helper.rb",
36
- "spec/test.jpg"
36
+ "spec/test.jpg",
37
+ "spec/test.txt"
37
38
  ]
38
39
  s.homepage = "http://github.com/jpastuszek/httpthumbnailer-client"
39
40
  s.licenses = ["MIT"]
@@ -53,7 +54,7 @@ Gem::Specification.new do |s|
53
54
  s.add_development_dependency(%q<rcov>, [">= 0"])
54
55
  s.add_development_dependency(%q<rdoc>, ["~> 3.9"])
55
56
  s.add_development_dependency(%q<daemon>, ["~> 1"])
56
- s.add_development_dependency(%q<httpthumbnailer>, ["~> 0.0.1"])
57
+ s.add_development_dependency(%q<httpthumbnailer>, ["~> 0.0.5"])
57
58
  else
58
59
  s.add_dependency(%q<httpclient>, [">= 2.2.1"])
59
60
  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
@@ -63,7 +64,7 @@ Gem::Specification.new do |s|
63
64
  s.add_dependency(%q<rcov>, [">= 0"])
64
65
  s.add_dependency(%q<rdoc>, ["~> 3.9"])
65
66
  s.add_dependency(%q<daemon>, ["~> 1"])
66
- s.add_dependency(%q<httpthumbnailer>, ["~> 0.0.1"])
67
+ s.add_dependency(%q<httpthumbnailer>, ["~> 0.0.5"])
67
68
  end
68
69
  else
69
70
  s.add_dependency(%q<httpclient>, [">= 2.2.1"])
@@ -74,7 +75,7 @@ Gem::Specification.new do |s|
74
75
  s.add_dependency(%q<rcov>, [">= 0"])
75
76
  s.add_dependency(%q<rdoc>, ["~> 3.9"])
76
77
  s.add_dependency(%q<daemon>, ["~> 1"])
77
- s.add_dependency(%q<httpthumbnailer>, ["~> 0.0.1"])
78
+ s.add_dependency(%q<httpthumbnailer>, ["~> 0.0.5"])
78
79
  end
79
80
  end
80
81
 
@@ -3,6 +3,15 @@ require 'httpclient'
3
3
  require 'httpthumbnailer-client/multipart_response'
4
4
 
5
5
  class HTTPThumbnailerClient
6
+ class UnsupportedMediaTypeError < ArgumentError
7
+ end
8
+
9
+ class UnknownResponseType < ArgumentError
10
+ end
11
+
12
+ class RemoteServerError < ArgumentError
13
+ end
14
+
6
15
  class URIBuilder
7
16
  def initialize(service_uri, &block)
8
17
  @specs = []
@@ -42,15 +51,46 @@ class HTTPThumbnailerClient
42
51
  attr_reader :mime_type, :data
43
52
  end
44
53
 
54
+ class ThumbnailingError
55
+ def initialize(msg)
56
+ @message = msg
57
+ end
58
+
59
+ attr_reader :message
60
+ end
61
+
45
62
  def initialize(server_url)
46
63
  @server_url = server_url
47
64
  end
48
65
 
49
66
  def thumbnail(data, &block)
50
67
  uri = URIBuilder.thumbnail(&block)
51
- res = HTTPClient.new.request('PUT', "#{@server_url}#{uri}", nil, data)
52
- MultipartResponse.new(res.header['Content-Type'].last, res.body).parts.map do |part|
53
- Thumbnail.new(part.header['Content-Type'], part.body)
68
+ response = HTTPClient.new.request('PUT', "#{@server_url}#{uri}", nil, data)
69
+ content_type = response.header['Content-Type'].last
70
+
71
+ case content_type
72
+ when 'text/plain'
73
+ case response.status
74
+ when 415
75
+ raise UnsupportedMediaTypeError, response.body.delete("\r")
76
+ else
77
+ raise RemoteServerError, response.body.delete("\r")
78
+ end
79
+ when /^multipart\/mixed/
80
+ MultipartResponse.new(content_type, response.body).parts.map do |part|
81
+ part_content_type = part.header['Content-Type']
82
+
83
+ case part_content_type
84
+ when 'text/plain'
85
+ ThumbnailingError.new(part.body.delete("\r"))
86
+ when /^image\//
87
+ Thumbnail.new(part_content_type, part.body)
88
+ else
89
+ raise UnknownResponseType, part_content_type
90
+ end
91
+ end
92
+ else
93
+ raise UnknownResponseType, content_type
54
94
  end
55
95
  end
56
96
  end
@@ -13,35 +13,90 @@ end
13
13
 
14
14
  describe HTTPThumbnailerClient do
15
15
  before :all do
16
- server_start
17
- @data = File.read(spec_dir + 'test.jpg')
16
+ log = spec_dir + 'server.log'
17
+ log.truncate(0)
18
+
19
+ start_server(
20
+ "httpthumbnailer",
21
+ '/tmp/httpthumbnailer.pid',
22
+ log,
23
+ 'http://localhost:3100/'
24
+ )
18
25
  end
19
26
 
20
27
  after :all do
21
- server_stop
28
+ stop_server('/tmp/httpthumbnailer.pid')
22
29
  end
23
30
 
24
31
  it "should return set of thumbnails matching specified specification" do
25
- thumbs = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail(@data) do
32
+ thumbs = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail((spec_dir + 'test.jpg').read) do
26
33
  thumbnail 'crop', 6, 3, 'JPEG'
27
34
  thumbnail 'crop', 8, 8, 'PNG'
28
35
  thumbnail 'crop', 4, 4, 'PNG'
29
36
  end
30
37
 
38
+ thumbs[0].should be_kind_of HTTPThumbnailerClient::Thumbnail
31
39
  thumbs[0].mime_type.should == 'image/jpeg'
32
- t, s = identify(thumbs[0].data)
33
- t.should == 'JPEG'
34
- s.should == '6x3'
40
+ i = identify(thumbs[0].data)
41
+ i.format.should == 'JPEG'
42
+ i.width.should == 6
43
+ i.height.should == 3
35
44
 
45
+ thumbs[1].should be_kind_of HTTPThumbnailerClient::Thumbnail
36
46
  thumbs[1].mime_type.should == 'image/png'
37
- t, s = identify(thumbs[1].data)
38
- t.should == 'PNG'
39
- s.should == '8x8'
47
+ i = identify(thumbs[1].data)
48
+ i.format.should == 'PNG'
49
+ i.width.should == 8
50
+ i.height.should == 8
40
51
 
52
+ thumbs[2].should be_kind_of HTTPThumbnailerClient::Thumbnail
41
53
  thumbs[2].mime_type.should == 'image/png'
42
- t, s = identify(thumbs[2].data)
43
- t.should == 'PNG'
44
- s.should == '4x4'
54
+ i = identify(thumbs[2].data)
55
+ i.format.should == 'PNG'
56
+ i.width.should == 4
57
+ i.height.should == 4
58
+ end
59
+
60
+ it "should raise HTTPThumbnailerClient::UnsupportedMediaTypeError error on unsupported media type" do
61
+ lambda {
62
+ HTTPThumbnailerClient.new('http://localhost:3100').thumbnail((spec_dir + 'test.txt').read) do
63
+ thumbnail 'crop', 6, 3, 'JPEG'
64
+ thumbnail 'crop', 8, 8, 'PNG'
65
+ end
66
+ }.should raise_error HTTPThumbnailerClient::UnsupportedMediaTypeError
67
+ end
68
+
69
+ it "should raise HTTPThumbnailerClient::RemoteServerError error on 404 server error" do
70
+ lambda {
71
+ HTTPThumbnailerClient.new('http://localhost:3100/blah').thumbnail((spec_dir + 'test.jpg').read) do
72
+ thumbnail 'crop', 6, 3, 'JPEG'
73
+ end
74
+ }.should raise_error HTTPThumbnailerClient::RemoteServerError
75
+ end
76
+
77
+ it "should return HTTPThumbnailerClient::ThumbnailingError object with set of returned thumbnail in case of error with particluar thumbanil" do
78
+ thumbs = HTTPThumbnailerClient.new('http://localhost:3100').thumbnail((spec_dir + 'test.jpg').read) do
79
+ thumbnail 'crop', 6, 3, 'JPEG'
80
+ thumbnail 'crop', 0, 0, 'PNG'
81
+ thumbnail 'crop', 4, 4, 'PNG'
82
+ end
83
+
84
+ thumbs[0].should be_kind_of HTTPThumbnailerClient::Thumbnail
85
+ thumbs[0].mime_type.should == 'image/jpeg'
86
+ i = identify(thumbs[0].data)
87
+ i.format.should == 'JPEG'
88
+ i.width.should == 6
89
+ i.height.should == 3
90
+
91
+ thumbs[1].should be_kind_of HTTPThumbnailerClient::ThumbnailingError
92
+ thumbs[1].message.should == "Error: ArgumentError: invalid result dimension (0, 0 given)\n"
93
+
94
+ thumbs[2].should be_kind_of HTTPThumbnailerClient::Thumbnail
95
+ thumbs[2].mime_type.should == 'image/png'
96
+ i = identify(thumbs[2].data)
97
+ i.format.should == 'PNG'
98
+ i.width.should == 4
99
+ i.height.should == 4
45
100
  end
46
101
  end
47
102
 
data/spec/spec_helper.rb CHANGED
@@ -11,6 +11,7 @@ RSpec.configure do |config|
11
11
  end
12
12
 
13
13
  require 'daemon'
14
+ require 'RMagick'
14
15
 
15
16
  def gem_dir
16
17
  Pathname.new(__FILE__).dirname + '..'
@@ -20,16 +21,34 @@ def spec_dir
20
21
  gem_dir + 'spec'
21
22
  end
22
23
 
23
- def server_start
24
- File.exist?("/tmp/httpthumbnailer.pid") and server_stop
25
- fork do
26
- Daemon.daemonize("/tmp/httpthumbnailer.pid", spec_dir + 'server.log')
27
- exec("httpthumbnailer")
24
+ def identify(data)
25
+ image = Magick::Image.from_blob(data).first
26
+ out = Struct.new(:format, :width, :height).new(image.format, image.columns, image.rows)
27
+ image.destroy!
28
+ out
29
+ end
30
+
31
+ def get(url)
32
+ HTTPClient.new.get_content(url)
33
+ end
34
+
35
+ def start_server(cmd, pid_file, log_file, test_url)
36
+ stop_server(pid_file)
37
+
38
+ fork do
39
+ Daemon.daemonize(pid_file, log_file)
40
+ exec(cmd)
41
+ end
42
+ Process.wait
43
+
44
+ ppid = Process.pid
45
+ at_exit do
46
+ stop_server(pid_file) if Process.pid == ppid
28
47
  end
29
48
 
30
49
  Timeout.timeout(10) do
31
- begin
32
- server_get '/'
50
+ begin
51
+ get test_url
33
52
  rescue Errno::ECONNREFUSED
34
53
  sleep 0.1
35
54
  retry
@@ -37,32 +56,21 @@ def server_start
37
56
  end
38
57
  end
39
58
 
40
- def server_stop
41
- File.open("/tmp/httpthumbnailer.pid") do |pidf|
42
- pid = pidf.read
59
+ def stop_server(pid_file)
60
+ pid_file = Pathname.new(pid_file)
61
+ return unless pid_file.exist?
43
62
 
44
- Timeout.timeout(10) do
45
- begin
46
- loop do
47
- ret = Process.kill("TERM", pid.strip.to_i)
48
- sleep 0.1
49
- end
50
- rescue Errno::ESRCH
63
+ pid = pid_file.read.strip.to_i
64
+
65
+ Timeout.timeout(20) do
66
+ begin
67
+ loop do
68
+ Process.kill("TERM", pid)
69
+ sleep 0.1
51
70
  end
71
+ rescue Errno::ESRCH
72
+ pid_file.unlink
52
73
  end
53
74
  end
54
75
  end
55
76
 
56
- def server_get(uri)
57
- HTTPClient.new.get_content("http://localhost:3100#{uri}")
58
- end
59
-
60
- def identify(data)
61
- Open3.popen3('identify -') do |stdin, stdout, stderr|
62
- stdin.write data
63
- stdin.close
64
- path, type, size, *rest = *stdout.read.split(' ')
65
- return type, size
66
- end
67
- end
68
-
data/spec/test.txt ADDED
@@ -0,0 +1 @@
1
+ hello world
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpthumbnailer-client
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
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-23 00:00:00 Z
18
+ date: 2011-11-29 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  type: :runtime
@@ -145,12 +145,12 @@ dependencies:
145
145
  requirements:
146
146
  - - ~>
147
147
  - !ruby/object:Gem::Version
148
- hash: 29
148
+ hash: 21
149
149
  segments:
150
150
  - 0
151
151
  - 0
152
- - 1
153
- version: 0.0.1
152
+ - 5
153
+ version: 0.0.5
154
154
  prerelease: false
155
155
  name: httpthumbnailer
156
156
  version_requirements: *id009
@@ -181,6 +181,7 @@ files:
181
181
  - spec/multipart_response_spec.rb
182
182
  - spec/spec_helper.rb
183
183
  - spec/test.jpg
184
+ - spec/test.txt
184
185
  homepage: http://github.com/jpastuszek/httpthumbnailer-client
185
186
  licenses:
186
187
  - MIT