image8 0.3.1 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +4 -2
- data/image8.gemspec +5 -3
- data/lib/image8.rb +81 -60
- metadata +33 -7
data/Gemfile
CHANGED
data/image8.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "image8"
|
3
|
-
s.version = "0.3.
|
4
|
-
s.date = "2010-06-
|
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
|
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
|
|
data/lib/image8.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require "uri"
|
2
2
|
require "sinatra/async"
|
3
|
-
require "em-
|
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
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
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
|
59
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
-
-
|
9
|
-
version: 0.3.
|
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-
|
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
|
-
|
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:
|
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: *
|
100
|
+
version_requirements: *id006
|
75
101
|
description: dynamic image resizing.
|
76
102
|
email: harry@vangberg.name
|
77
103
|
executables: []
|