image8 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/Gemfile +4 -2
  2. data/image8.gemspec +5 -3
  3. data/lib/image8.rb +81 -60
  4. metadata +33 -7
data/Gemfile CHANGED
@@ -1,5 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gem "async_sinatra", "0.1.5"
3
+ gem "async_sinatra", "0.2.1"
4
4
  gem "em-http-request", "0.2.7"
5
- gem "image_science", "1.2.1"
5
+ gem "em-synchrony", "0.1.5"
6
+ gem "json", ">= 1.2.4"
7
+ gem "rmagick", "2.13.1"
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "image8"
3
- s.version = "0.3.1"
4
- s.date = "2010-06-18"
3
+ s.version = "0.3.2"
4
+ s.date = "2010-06-24"
5
5
  s.summary = "dynamic image resizing."
6
6
  s.email = "harry@vangberg.name"
7
7
  s.homepage = "http://github.com/ichverstehe/image8"
@@ -14,8 +14,10 @@ Gem::Specification.new do |s|
14
14
  "lib/image8.rb",
15
15
  ]
16
16
  s.add_dependency "sinatra", ">= 1.0"
17
- s.add_dependency "async_sinatra", ">= 0.1.5"
17
+ s.add_dependency "async_sinatra", ">= 0.2.1"
18
18
  s.add_dependency "em-http-request", ">= 0.2.7"
19
+ s.add_dependency "em-synchrony", ">= 0.1.5"
20
+ s.add_dependency "json"
19
21
  s.add_dependency "rmagick", ">= 2.13.1"
20
22
  end
21
23
 
@@ -1,6 +1,9 @@
1
1
  require "uri"
2
2
  require "sinatra/async"
3
- require "em-http"
3
+ require "em-synchrony"
4
+ require "em-synchrony/em-http"
5
+ require "fiber"
6
+ require "json"
4
7
  require "RMagick"
5
8
 
6
9
  class Image8 < Sinatra::Base
@@ -9,79 +12,97 @@ class Image8 < Sinatra::Base
9
12
 
10
13
  register Sinatra::Async
11
14
 
12
- aget %r|/([0-9x]+)/(.*)| do |format, uri|
13
- if uri.strip.empty?
14
- status 404
15
- body "No such image."
16
- end
15
+ aget %r[/(resize|crop)/([0-9x]+)/(.*)] do |action, format, uri|
16
+ EM.synchrony do
17
+ puts "uri: #{uri.inspect} - #{uri.class}"
18
+
19
+ if uri.strip.empty?
20
+ status 404
21
+ body "No such image."
22
+ else
23
+ # This is retarded.
24
+ uri = append_query_string(uri)
25
+ doc = doc_uri(uri, format, action)
17
26
 
18
- puts "uri: #{uri.inspect} - #{uri.class}"
27
+ expires 31_536_000 # 1 year
28
+ request = EM::HttpRequest.new(doc).get(:timeout => 5)
29
+ if request.response_header.status == 200
30
+ puts "Serving straight from cache.."
31
+ content_type request.response_header["CONTENT_TYPE"]
32
+ body request.response
33
+ else
34
+ original, rev = download_original(uri)
35
+ image = transform_image(original, action, format)
19
36
 
20
- # This is retarded.
37
+ http = EM::HttpRequest.new "#{doc}?rev=#{rev}"
38
+ http.aput(
39
+ :head => {'Content-Type' => image.mime_type},
40
+ :body => image.to_blob,
41
+ :params => {:rev => rev}
42
+ )
43
+ content_type image.mime_type
44
+ body image.to_blob
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def append_query_string uri
21
51
  if !request.query_string.empty?
22
52
  uri += "?#{request.query_string}"
23
53
  end
24
- uri = URI.encode(uri)
25
-
26
- doc_id = encode_uri_for_couchdb(uri)
27
- doc_uri = settings.couchdb + "/#{doc_id}"
28
- doc_http = EventMachine::HttpRequest.new(doc_uri + "/" + format)
29
-
30
- request = doc_http.get(:timeout => 5)
31
- request.callback {
32
- expires 31_536_000 # 1 year
33
- if request.response_header.status == 200
34
- puts "Serving straight from cache.."
35
- content_type request.response_header["CONTENT_TYPE"]
36
- body request.response
37
- else
38
- download_original(uri, doc_uri) {|blob|
39
- resize_image(blob, format) {|img|
40
- doc_http.put(
41
- :head => {'Content-Type' => img.mime_type},
42
- :body => img.to_blob
43
- )
44
- content_type img.mime_type
45
- body img.to_blob
46
- }
47
- }
48
- end
49
- }
54
+ uri
50
55
  end
51
56
 
52
- def encode_uri_for_couchdb uri
57
+ def doc_id uri
53
58
  uri = URI.encode(uri)
54
59
  uri.gsub! "/", "%2F"
55
60
  uri
56
61
  end
57
62
 
58
- def download_original uri, doc_uri
59
- cache = EventMachine::HttpRequest.new(doc_uri + "/full")
63
+ def doc_uri uri, format=nil, action=nil
64
+ format = "#{action}/#{format}" if action
65
+ [settings.couchdb, doc_id(uri), format].compact.join("/")
66
+ end
67
+
68
+ def download_original uri
69
+ cache = EM::HttpRequest.new doc_uri(uri, "full")
60
70
  request = cache.get
61
- request.callback {
62
- if request.response_header.status == 200
63
- puts "Serving original from cache.."
64
- yield request.response if block_given?
65
- else
66
- puts "Downloading original.."
67
- original = EventMachine::HttpRequest.new(uri).get
68
- original.callback {
69
- req = cache.put(
70
- :head => {'Content-Type' => original.response_header["CONTENT_TYPE"]},
71
- :body => original.response
72
- )
73
- req.callback { yield original.response if block_given? }
74
- }
75
- end
76
- }
71
+
72
+ if request.response_header.status == 200
73
+ puts "Serving original from cache.."
74
+ blob = request.response
75
+ rev = request.response_header["ETAG"][1..-2]
76
+ else
77
+ puts "Downloading original.."
78
+ original = EM::HttpRequest.new(uri).get
79
+ request = cache.put(
80
+ :head => {'Content-Type' => original.response_header["CONTENT_TYPE"]},
81
+ :body => original.response
82
+ )
83
+ blob = original.response
84
+ rev = JSON.parse(request.response)["rev"]
85
+ end
86
+
87
+ [blob, rev]
77
88
  end
78
89
 
79
- def resize_image blob, format, &block
80
- puts "Resizing image.."
81
- img = Magick::Image.from_blob(blob).first
82
- img.change_geometry!(format) {|width, height|
83
- img.resize! width, height
84
- }
85
- block.call(img) if block
90
+ def format_response request
91
+ rev = etag[1..-2]
92
+ [blob, rev]
93
+ end
94
+
95
+ def transform_image blob, action, format
96
+ puts "#{action} image.."
97
+ image = Magick::Image.from_blob(blob).first
98
+ case action
99
+ when "resize" then
100
+ image.change_geometry!(format) {|width, height|
101
+ image.resize! width, height
102
+ }
103
+ when "crop" then
104
+ image.resize_to_fill! format.to_i
105
+ end
106
+ image
86
107
  end
87
108
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 3
8
- - 1
9
- version: 0.3.1
8
+ - 2
9
+ version: 0.3.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Harry Vangberg
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-18 00:00:00 +02:00
17
+ date: 2010-06-24 00:00:00 +02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -39,9 +39,9 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  segments:
41
41
  - 0
42
+ - 2
42
43
  - 1
43
- - 5
44
- version: 0.1.5
44
+ version: 0.2.1
45
45
  type: :runtime
46
46
  version_requirements: *id002
47
47
  - !ruby/object:Gem::Dependency
@@ -59,9 +59,35 @@ dependencies:
59
59
  type: :runtime
60
60
  version_requirements: *id003
61
61
  - !ruby/object:Gem::Dependency
62
- name: rmagick
62
+ name: em-synchrony
63
63
  prerelease: false
64
64
  requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ - 1
71
+ - 5
72
+ version: 0.1.5
73
+ type: :runtime
74
+ version_requirements: *id004
75
+ - !ruby/object:Gem::Dependency
76
+ name: json
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ type: :runtime
86
+ version_requirements: *id005
87
+ - !ruby/object:Gem::Dependency
88
+ name: rmagick
89
+ prerelease: false
90
+ requirement: &id006 !ruby/object:Gem::Requirement
65
91
  requirements:
66
92
  - - ">="
67
93
  - !ruby/object:Gem::Version
@@ -71,7 +97,7 @@ dependencies:
71
97
  - 1
72
98
  version: 2.13.1
73
99
  type: :runtime
74
- version_requirements: *id004
100
+ version_requirements: *id006
75
101
  description: dynamic image resizing.
76
102
  email: harry@vangberg.name
77
103
  executables: []