thumbnail 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/License.txt +20 -0
- data/Manifest.txt +28 -0
- data/README.txt +88 -0
- data/Rakefile +140 -0
- data/client_spec.txt +58 -0
- data/lib/thumbnail.rb +1 -0
- data/lib/thumbnail/client.rb +106 -0
- data/lib/thumbnail/response.rb +89 -0
- data/lib/thumbnail/version.rb +9 -0
- data/response_spec.txt +10 -0
- data/setup.rb +1585 -0
- data/spec/client_spec.rb +284 -0
- data/spec/fixtures/batch.xml +64 -0
- data/spec/fixtures/invalid_credentials.xml +10 -0
- data/spec/fixtures/single.xml +15 -0
- data/spec/fixtures/unexists.xml +2 -0
- data/spec/response_spec.rb +40 -0
- data/spec/spec.opts +1 -0
- data/website/amzn.jpg +0 -0
- data/website/craphound.jpg +0 -0
- data/website/index.html +147 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/logo.png +0 -0
- data/website/small_crap.jpg +0 -0
- data/website/soon.jpg +0 -0
- data/website/stylesheets/screen.css +147 -0
- metadata +78 -0
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,284 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/thumbnail.rb'
|
3
|
+
|
4
|
+
module SetupOpts
|
5
|
+
def auth_opts
|
6
|
+
{:access_key_id => "asdfsdfasdf", :secret_access_key => "asdfsadfasf"}
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
module NoGo
|
11
|
+
def stub_request
|
12
|
+
Net::HTTP.stub!(:get)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "Thumbnail::Client#new" do
|
17
|
+
include SetupOpts
|
18
|
+
|
19
|
+
it "should default to the thumbnail action" do
|
20
|
+
t = Thumbnail::Client.new(auth_opts)
|
21
|
+
t.action.should == :thumbnail
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set the action as redirect if specified" do
|
25
|
+
t = Thumbnail::Client.new( auth_opts.merge(:action => :redirect) )
|
26
|
+
t.action.should == :redirect
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should raise an error if the action is neither redirect nor thumbnail" do
|
30
|
+
lambda{ Thumbnail::Client.new(auth_opts.merge(:action => :dogs) ) }.should raise_error(ArgumentError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should raise an error if the access_key_id is not specified" do
|
34
|
+
lambda{ Thumbnail::Client.new(:secret_access_key => "asdfsadfasf")}.should raise_error(ArgumentError)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should raise an error if the secret_access_key is not specified" do
|
38
|
+
lambda{ Thumbnail::Client.new(:access_key_id => "asdfsadfasf")}.should raise_error(ArgumentError)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should default the size to large" do
|
42
|
+
t = Thumbnail::Client.new(auth_opts)
|
43
|
+
t.size.should == :large
|
44
|
+
end
|
45
|
+
it "should set the size to small if specified" do
|
46
|
+
t = Thumbnail::Client.new( auth_opts.merge(:size => :small) )
|
47
|
+
t.size.should == :small
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should raise an error if the size is neither large nor small" do
|
51
|
+
lambda{ Thumbnail::Client.new(auth_opts.merge(:size => :largest) ) }.should raise_error(ArgumentError)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should raise an error if a default_image is specified for a Thumbnail action" do
|
55
|
+
lambda{ Thumbnail::Client.new(auth_opts.merge(:default_image => "http://somewhere.com/my_pict.jpg")) }.should raise_error(ArgumentError)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "Thumbnail::Client#new for a redirect" do
|
60
|
+
include SetupOpts
|
61
|
+
|
62
|
+
it "should set the default_image if specified" do
|
63
|
+
t = Thumbnail::Client.new(auth_opts.merge(:action => :redirect, :default_image => "http://somewhere.com/my_pict.jpg"))
|
64
|
+
t.instance_variable_get("@default_image").should == "http://somewhere.com/my_pict.jpg"
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "Thumbnail#query" do
|
70
|
+
include SetupOpts
|
71
|
+
|
72
|
+
it "should calculate the signature and timestamp" do
|
73
|
+
t = Thumbnail::Client.new(auth_opts)
|
74
|
+
t.should_receive(:calculate_signature_and_timestamp)
|
75
|
+
t.send(:query)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "Thumbnail#calculate_signature_and_timestamp" do
|
80
|
+
include SetupOpts
|
81
|
+
|
82
|
+
before do
|
83
|
+
@t = Thumbnail::Client.new(auth_opts)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should calculate the signature" do
|
87
|
+
Base64.should_receive(:encode64).and_return("se5wwsefaw435rawef=")
|
88
|
+
@t.send(:calculate_signature_and_timestamp)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should set the (correctly formatted) timestamp" do
|
92
|
+
Time.stub!(:now).and_return(Time.mktime(2007,7,1,12))
|
93
|
+
@t.send(:calculate_signature_and_timestamp)
|
94
|
+
@t.instance_variable_get("@timestamp").should == "2007-07-01T19:00:00.000Z"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "Thumbnail#query with thumbnail action and a single url" do
|
99
|
+
include SetupOpts
|
100
|
+
|
101
|
+
before do
|
102
|
+
@t = Thumbnail::Client.new(auth_opts)
|
103
|
+
@t.instance_variable_set("@url", "www.boingboing.net")
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should compose a thumbnail single query" do
|
107
|
+
@t.should_receive(:thumbnail_query_single)
|
108
|
+
@t.send(:query)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "Thumbnail::Client#query with thumbnail action and an array of urls" do
|
113
|
+
include SetupOpts
|
114
|
+
|
115
|
+
before do
|
116
|
+
@t = Thumbnail::Client.new(auth_opts)
|
117
|
+
@t.instance_variable_set("@url", ["www.boingboing.net", "www.craphound.com"])
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should compose a thumbnail batch query" do
|
122
|
+
@t.should_receive(:thumbnail_query_batch)
|
123
|
+
@t.send(:query)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "Thumbnail::Client#query with redirect action" do
|
128
|
+
include SetupOpts
|
129
|
+
|
130
|
+
before do
|
131
|
+
@t = Thumbnail::Client.new( auth_opts.merge(:action => :redirect) )
|
132
|
+
@t.instance_variable_set("@url", "www.boingboing.net")
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should compose a redirect query" do
|
136
|
+
@t.should_receive(:redirect_query)
|
137
|
+
@t.send(:query)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "Thumbnail::Client#thumbnail_query_single" do
|
142
|
+
include SetupOpts
|
143
|
+
|
144
|
+
before do
|
145
|
+
Time.stub!(:now).and_return(Time.mktime(2007,7,1,15))
|
146
|
+
@t = Thumbnail::Client.new( auth_opts )
|
147
|
+
@t.send(:calculate_signature_and_timestamp)
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should compose the query url correctly" do
|
151
|
+
@t.instance_variable_set("@url", "www.boingboing.net")
|
152
|
+
@t.send(:thumbnail_query_single).should == "http://ast.amazonaws.com/?Action=Thumbnail&AWSAccessKeyId=#{auth_opts[:access_key_id]}&Signature=f2g%2BLOp8T1ZfWLEip7l4RXiPQkI%3D&Timestamp=2007-07-01T22:00:00.000Z&Url=www.boingboing.net&Size=Large"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe "Thumbnail::Client#thumbnail_query_batch" do
|
157
|
+
include SetupOpts
|
158
|
+
|
159
|
+
before do
|
160
|
+
Time.stub!(:now).and_return(Time.mktime(2007,7,1,15))
|
161
|
+
@t = Thumbnail::Client.new( auth_opts )
|
162
|
+
@t.send(:calculate_signature_and_timestamp)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should compose the query url correctly" do
|
166
|
+
@t.instance_variable_set("@url", ["www.boingboing.net", "www.craphound.com"])
|
167
|
+
@t.send(:thumbnail_query_batch).should ==
|
168
|
+
"http://ast.amazonaws.com/?Action=Thumbnail&AWSAccessKeyId=#{auth_opts[:access_key_id]}&Signature=f2g%2BLOp8T1ZfWLEip7l4RXiPQkI%3D&Timestamp=2007-07-01T22:00:00.000Z&Shared.Size=Large&Thumbnail.1.Url=www.boingboing.net&Thumbnail.2.Url=www.craphound.com"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "Thumbnail::Client#redirect_query with a default_image" do
|
173
|
+
include SetupOpts
|
174
|
+
|
175
|
+
before do
|
176
|
+
Time.stub!(:now).and_return(Time.mktime(2007,7,1,15))
|
177
|
+
@t = Thumbnail::Client.new( auth_opts.merge(:action => :redirect, :default_image => "http://somewhere.com/my_pict.jpg") )
|
178
|
+
@t.send(:calculate_signature_and_timestamp)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should compose the query url correctly" do
|
182
|
+
@t.instance_variable_set("@url", "www.boingboing.net")
|
183
|
+
|
184
|
+
@t.send(:redirect_query).should ==
|
185
|
+
"http://ast.amazonaws.com/?Action=Redirect&AWSAccessKeyId=#{auth_opts[:access_key_id]}&Signature=%2FceiRH2lULi0rTvaY0mmJhxIwa4%3D&Timestamp=2007-07-01T22:00:00.000Z&Url=www.boingboing.net&Size=Large&DefaultImage=http://somewhere.com/my_pict.jpg"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "Thumbnail::Client#redirect_query without a default_image" do
|
190
|
+
include SetupOpts
|
191
|
+
|
192
|
+
before do
|
193
|
+
Time.stub!(:now).and_return(Time.mktime(2007,7,1,15))
|
194
|
+
@t = Thumbnail::Client.new( auth_opts.merge(:action => :redirect) )
|
195
|
+
@t.send(:calculate_signature_and_timestamp)
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should compose the query url correctly" do
|
199
|
+
@t.instance_variable_set("@url", "www.boingboing.net")
|
200
|
+
@t.send(:redirect_query).should ==
|
201
|
+
"http://ast.amazonaws.com/?Action=Redirect&AWSAccessKeyId=#{auth_opts[:access_key_id]}&Signature=%2FceiRH2lULi0rTvaY0mmJhxIwa4%3D&Timestamp=2007-07-01T22:00:00.000Z&Url=www.boingboing.net&Size=Large"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "Thumbnail::Client#get with a thumbnail action" do
|
206
|
+
include SetupOpts
|
207
|
+
include NoGo
|
208
|
+
|
209
|
+
before do
|
210
|
+
stub_request
|
211
|
+
Thumbnail::Response.stub!(:build)
|
212
|
+
@t = Thumbnail::Client.new(auth_opts)
|
213
|
+
@t.stub!(:query).and_return(@q = "http://aws.com")
|
214
|
+
@pq = mock('URI::HTTP')
|
215
|
+
@pq.stub!(:host).and_return('aws.com')
|
216
|
+
URI.stub!(:parse).and_return(@pq)
|
217
|
+
Net::HTTP.stub!(:get).and_return(@xml = mock('xmldoc'))
|
218
|
+
end
|
219
|
+
|
220
|
+
it "should set the url string if given a single url" do
|
221
|
+
@t.get("www.boingboing.net")
|
222
|
+
@t.instance_variable_get("@url").should == "www.boingboing.net"
|
223
|
+
end
|
224
|
+
|
225
|
+
it "should set the url array if given an array of urls" do
|
226
|
+
@t.get(["www.boingboing.net", "www.craphound.com"])
|
227
|
+
@t.instance_variable_get("@url").should == ["www.boingboing.net", "www.craphound.com"]
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should parse the url before conducting the query" do
|
231
|
+
URI.should_receive(:parse).with(@q).and_return(@pq)
|
232
|
+
@t.get("www.craphound.com")
|
233
|
+
end
|
234
|
+
|
235
|
+
it "should use net/https to conduct the query" do
|
236
|
+
Net::HTTP.should_receive(:get).with(@pq)
|
237
|
+
@t.get("www.craphound.com")
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should build a response object from the xml" do
|
241
|
+
Thumbnail::Response.should_receive(:build).with(@xml)
|
242
|
+
@t.get("www.craphound.com")
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
describe "Thumbnail::Client#get with one or more invalid urls" do
|
247
|
+
include SetupOpts
|
248
|
+
|
249
|
+
before do
|
250
|
+
@t = Thumbnail::Client.new(auth_opts)
|
251
|
+
end
|
252
|
+
|
253
|
+
it "should raise an error with one url that is invalid" do
|
254
|
+
lambda{ @t.get("89u--=sdf-://as-df-") }.should raise_error(URI::InvalidURIError)
|
255
|
+
end
|
256
|
+
|
257
|
+
it "should raise an error if any of the urls in its give array are invalid" do
|
258
|
+
lambda{ @t.get(["89u--=s:?df-as-df-", "www.google.com"]) }.should raise_error(URI::InvalidURIError)
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
describe "Thumbnail::Client#get with a redirect action" do
|
264
|
+
include SetupOpts
|
265
|
+
include NoGo
|
266
|
+
|
267
|
+
before do
|
268
|
+
stub_request
|
269
|
+
@t = Thumbnail::Client.new(auth_opts.merge(:action => :redirect))
|
270
|
+
end
|
271
|
+
|
272
|
+
it "should raise an error if given an array of urls" do
|
273
|
+
lambda{ @t.get(["www.boingboing.net", "www.craphound.com"]) }.should raise_error(ArgumentError)
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should calculate the query url" do
|
277
|
+
@t.should_receive(:query)
|
278
|
+
@t.get("www.boingboing.net")
|
279
|
+
end
|
280
|
+
|
281
|
+
it "should return the redirect query" do
|
282
|
+
@t.get("www.boingboing.net").should == @t.send(:redirect_query)
|
283
|
+
end
|
284
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<aws:ThumbnailResponse
|
3
|
+
xmlns:aws="http://ast.amazonaws.com/doc/2005-10-05/">
|
4
|
+
<aws:Response>
|
5
|
+
<aws:OperationRequest>
|
6
|
+
<aws:RequestId>
|
7
|
+
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
8
|
+
</aws:RequestId>
|
9
|
+
</aws:OperationRequest>
|
10
|
+
<aws:ThumbnailResult>
|
11
|
+
<aws:Thumbnail Exists="true">
|
12
|
+
http://location_to_thumbnail_for_alexa.com
|
13
|
+
</aws:Thumbnail>
|
14
|
+
<aws:RequestUrl>
|
15
|
+
alexa.com
|
16
|
+
</aws:RequestUrl>
|
17
|
+
</aws:ThumbnailResult>
|
18
|
+
<aws:ResponseStatus>
|
19
|
+
<aws:StatusCode>
|
20
|
+
Success
|
21
|
+
</aws:StatusCode>
|
22
|
+
</aws:ResponseStatus>
|
23
|
+
</aws:Response>
|
24
|
+
<aws:Response>
|
25
|
+
<aws:OperationRequest>
|
26
|
+
<aws:RequestId>
|
27
|
+
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
28
|
+
</aws:RequestId>
|
29
|
+
</aws:OperationRequest>
|
30
|
+
<aws:ThumbnailResult>
|
31
|
+
<aws:Thumbnail Exists="true">
|
32
|
+
http://location_to_thumbnail_for_amazon.com
|
33
|
+
</aws:Thumbnail>
|
34
|
+
<aws:RequestUrl>
|
35
|
+
amazon.com
|
36
|
+
</aws:RequestUrl>
|
37
|
+
</aws:ThumbnailResult>
|
38
|
+
<aws:ResponseStatus>
|
39
|
+
<aws:StatusCode>
|
40
|
+
Success
|
41
|
+
</aws:StatusCode>
|
42
|
+
</aws:ResponseStatus>
|
43
|
+
</aws:Response>
|
44
|
+
<aws:Response>
|
45
|
+
<aws:OperationRequest>
|
46
|
+
<aws:RequestId>
|
47
|
+
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
|
48
|
+
</aws:RequestId>
|
49
|
+
</aws:OperationRequest>
|
50
|
+
<aws:ThumbnailResult>
|
51
|
+
<aws:Thumbnail Exists="true">
|
52
|
+
http://location_to_thumbnail_for_a9.com
|
53
|
+
</aws:Thumbnail>
|
54
|
+
<aws:RequestUrl>
|
55
|
+
a9.com
|
56
|
+
</aws:RequestUrl>
|
57
|
+
</aws:ThumbnailResult>
|
58
|
+
<aws:ResponseStatus>
|
59
|
+
<aws:StatusCode>
|
60
|
+
Success
|
61
|
+
</aws:StatusCode>
|
62
|
+
</aws:ResponseStatus>
|
63
|
+
</aws:Response>
|
64
|
+
</aws:ThumbnailResponse>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<Response>
|
3
|
+
<Errors>
|
4
|
+
<Error>
|
5
|
+
<Code>AuthFailure</Code>
|
6
|
+
<Message>AWS was not able to validate the provided access credentials</Message>
|
7
|
+
</Error>
|
8
|
+
</Errors>
|
9
|
+
<RequestID>5bb2ed01-8ff3-4622-a359-af9b9dcb80b2</RequestID>
|
10
|
+
</Response>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<aws:ThumbnailResponse xmlns:aws="http://ast.amazonaws.com/doc/2005-10-05/">
|
3
|
+
<aws:Response>
|
4
|
+
<aws:OperationRequest>
|
5
|
+
<aws:RequestId>429d5fa3-e7b3-43d7-98ee-35ec9b01750f</aws:RequestId>
|
6
|
+
</aws:OperationRequest>
|
7
|
+
<aws:ThumbnailResult>
|
8
|
+
<aws:Thumbnail Exists="true">http://s3-external-1.amazonaws.com/alexa-thumbnails/421922F1CA73EF1FB344425517D124FA5F84E8DDl?Signature=sL4Ldjh336C2KJ8RMaWoswMah9k%3D&Expires=1181512094&AWSAccessKeyId=1FVZ0JNEJDA5TK457CR2</aws:Thumbnail>
|
9
|
+
<aws:RequestUrl>www.boingboing.net</aws:RequestUrl>
|
10
|
+
</aws:ThumbnailResult>
|
11
|
+
<aws:ResponseStatus>
|
12
|
+
<aws:StatusCode>Success</aws:StatusCode>
|
13
|
+
</aws:ResponseStatus>
|
14
|
+
</aws:Response>
|
15
|
+
</aws:ThumbnailResponse>
|
@@ -0,0 +1,2 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<aws:ThumbnailResponse xmlns:aws="http://ast.amazonaws.com/doc/2005-10-05/"><aws:Response><aws:OperationRequest><aws:RequestId>c4ab78dc-77f1-4534-9458-45436f689c1b</aws:RequestId></aws:OperationRequest><aws:ThumbnailResult><aws:Thumbnail Exists="false">http://s3-external-1.amazonaws.com/alexa-thumbnails/noimagel?Signature=ZEDPUK7B%2FpLsNwufU%2FafuHPrIR0%3D&Expires=1181687213&AWSAccessKeyId=1FVZ0JNEJDA5TK457CR2</aws:Thumbnail><aws:RequestUrl>www.thenytimesexplainstheratings.com</aws:RequestUrl></aws:ThumbnailResult><aws:ResponseStatus><aws:StatusCode>Success</aws:StatusCode></aws:ResponseStatus></aws:Response></aws:ThumbnailResponse>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
require File.dirname(__FILE__) + '/../lib/thumbnail.rb'
|
3
|
+
|
4
|
+
describe "Thumbnail::Response#build with a successful single response" do
|
5
|
+
before do
|
6
|
+
@xml = parse_fixture("single")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should create a Thumbnail::Response::Success object" do
|
10
|
+
Thumbnail::Response::Success.should_receive(:new)
|
11
|
+
Thumbnail::Response.build(@xml)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "Thumbnail::Response#build with a successful batch response" do
|
16
|
+
before do
|
17
|
+
@xml = parse_fixture("batch")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should create a Thumbnail::Response::Success object" do
|
21
|
+
Thumbnail::Response::Success.should_receive(:new)
|
22
|
+
Thumbnail::Response.build(@xml)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "Thumbnail::Response#build with an invalid credentails response" do
|
27
|
+
before do
|
28
|
+
@xml = parse_fixture("invalid_credentials")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should create a Thumbnail::Response::Failure object" do
|
32
|
+
Thumbnail::Response::Failure.should_receive(:new)
|
33
|
+
Thumbnail::Response.build(@xml)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should correctly parse out and format the error message" do
|
37
|
+
r = Thumbnail::Response.build(@xml)
|
38
|
+
r.to_s.should == "AuthFailure: AWS was not able to validate the provided access credentials"
|
39
|
+
end
|
40
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/website/amzn.jpg
ADDED
Binary file
|
Binary file
|
data/website/index.html
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
|
6
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
7
|
+
<title>
|
8
|
+
THUMBNAIL: website pix courtesy of ruby, amazon, and alexa
|
9
|
+
</title>
|
10
|
+
<script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
|
11
|
+
<style>
|
12
|
+
|
13
|
+
</style>
|
14
|
+
<script type="text/javascript">
|
15
|
+
window.onload = function() {
|
16
|
+
settings = {
|
17
|
+
tl: { radius: 10 },
|
18
|
+
tr: { radius: 10 },
|
19
|
+
bl: { radius: 10 },
|
20
|
+
br: { radius: 10 },
|
21
|
+
antiAlias: true,
|
22
|
+
autoPad: true,
|
23
|
+
validTags: ["div"]
|
24
|
+
}
|
25
|
+
var versionBox = new curvyCorners(settings, document.getElementById("version"));
|
26
|
+
versionBox.applyCornersToAll();
|
27
|
+
}
|
28
|
+
</script>
|
29
|
+
</head>
|
30
|
+
<body>
|
31
|
+
<div id="main">
|
32
|
+
<img src="logo.png" id="logo">
|
33
|
+
<div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/thumbnail"; return false'>
|
34
|
+
<p>Get Version</p>
|
35
|
+
<a href="http://rubyforge.org/projects/thumbnail" class="numbers">0.2.0</a>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
|
39
|
+
<h2>What</h2>
|
40
|
+
<p>A Ruby wrapper for the <a href="http://www.amazon.com/b/ref=sc_fe_c_0_239513011_4/102-1130464-8229719?ie=UTF8&node=236156011&no=239513011&me=A36L942TSJ2AJA">Amazon Web Services Alexa Site Thumbnail Service</a> REST API, which provides website thumbnail images on demand for a small fee ($0.20/1000).</p>
|
41
|
+
|
42
|
+
<h2>Installing</h2>
|
43
|
+
|
44
|
+
|
45
|
+
<pre syntax="ruby">$ sudo gem install thumbnail</pre>
|
46
|
+
|
47
|
+
<p>Thumbnail depends on the terrific <a href="http://code.whytheluckystiff.net/hpricot/">Hpricot</a> XHTML parsing and manipulation library by <a href="whytheluckystiff.net">why the lucky stiff</a>; version 0.5 or better has the necessary powers.</p>
|
48
|
+
|
49
|
+
<h2>Registering with Amazon</h2>
|
50
|
+
<p>
|
51
|
+
In order to use the AWS-AST api, you must first complete the following series of bureaucratic tasks:
|
52
|
+
<ol>
|
53
|
+
<li><a href="http://aws.amazon.com">Signup for an Amazon Web Services account</a> (if you don't yet have one). You can use your existing Amazon user account for this or create a new one.</li>
|
54
|
+
<li><a href="http://www.amazon.com/b/ref=sc_fe_c_0_239513011_4/102-1130464-8229719?ie=UTF8&node=236156011&no=239513011&me=A36L942TSJ2AJA">Signup for the Alexa Site Thumbnail Service</a>.</li>
|
55
|
+
<li>Find and note your AWS Access Key Id and your Secret Access Key. You'll need to tell Thumbnail about these for authentication's sake; you should be given them at the end of the signup process.</li>
|
56
|
+
</ol>
|
57
|
+
</p>
|
58
|
+
<p>
|
59
|
+
Registering for both of these accounts is free, payment for the Site Thumbnail Service is based entirely on usage, with no charges for requests for unavailable thumbnails.
|
60
|
+
</p>
|
61
|
+
<h2>Demonstration of usage</h2>
|
62
|
+
<p>The API provides two actions for accessing site thumbnails: Thumbnail and Redirect and the Thumbnail::Client supports 'em both.
|
63
|
+
</p>
|
64
|
+
<h3>Thumbnail Action</h3>
|
65
|
+
When conducting a thumbnail action (the default), the Client will conduct an api call to fetch the image url(s) from Amazon for immediate download of your thumbnail(s) as follows:
|
66
|
+
|
67
|
+
<pre>
|
68
|
+
require 'thumbnail'
|
69
|
+
require 'open-uri'
|
70
|
+
|
71
|
+
t = Thumbnail::Client.new :access_key_id => YOUR_ACCESS_KEY_ID,
|
72
|
+
:secret_access_key => YOUR_SECRET_ACCESS_KEY
|
73
|
+
url = t.get("www.craphound.com")[:thumbnail][:url]
|
74
|
+
File.open("craphound.jpg", "w") { |f| f.write open(url).read }
|
75
|
+
</pre>
|
76
|
+
The result will look something like this:<br />
|
77
|
+
<img src="craphound.jpg">
|
78
|
+
</p>
|
79
|
+
<p>You can also request thumbnails for multiple images simultaneously by passing an array of urls to <code>get</code>. If you do that, you'll have to access the response object differently (see below).</p>
|
80
|
+
<p><em>Note: Once you make the <code>get</code> call, and the request to AST goes out, you only have fifteen seconds to use the resulting image url before it expires. This can play havoc with by-hand testing. I recommend that you run something very much like the final line in the example immediately.</em></p>
|
81
|
+
<h3>The Response Object</h3>
|
82
|
+
<p>
|
83
|
+
Thumbnail action requests will return either a Thumbnail::Response::Success or Thumbnail::Response::Failure object depending on their outcome. Each of these objects offer access to the raw xml response and the Hpricot::Doc object built from parsing it in addtion to the parsed results hash. Further, the <code>[]</code> method has been defined to provide easy access to the parsed results as seen in the example above. Calling <code>to_s</code> on a Failure object will provide a helpful concatenation of the error messages returned by Amazon.
|
84
|
+
</p>
|
85
|
+
<h3>Redirect Action</h3>
|
86
|
+
<p>
|
87
|
+
For a redirect action, the Thumbnail::Client will simply compose and return the image url like so:
|
88
|
+
<pre>
|
89
|
+
require 'thumbnail'
|
90
|
+
|
91
|
+
t = Thumbnail::Client.new :access_key_id => YOUR_ACCESS_KEY_ID,
|
92
|
+
:secret_access_key => YOUR_SECRET_ACCESS_KEY,
|
93
|
+
:action => :redirect
|
94
|
+
url = t.get("www.twitter.com")
|
95
|
+
|
96
|
+
#=> http://ast.amazonaws.com/?Action=Redirect&AWSAccessKeyId=YOUR_ACCESS_KEY_ID
|
97
|
+
&Signature=sdhfiawrkjw3h9bncoa8ue&Timestamp=2007-06-14T09:09:18.000Z&Url=www.tw
|
98
|
+
itter.com&Size=Large
|
99
|
+
</pre>
|
100
|
+
The resulting url will redirect to the thumbnail image hosted on s3. This action is perfect for dynamic inclusion of AWS-AST-generated thumbnails in live web pages. <em>Note: this usage of the Thumbnail::Client does not go out over the wire and will not count as a paid api call until you actually request the resulting url with a browser or other user agent.</em>
|
101
|
+
</p>
|
102
|
+
<h3>Default Images</h3>
|
103
|
+
<p>
|
104
|
+
In either action, if you request a thumbnail that is not available, it will be queued for creation within 24 hours and you will not be charged for the request. In the redirect action, you can indicate a Default Image to be returned in this eventuality by including <code>:default_image => 'http://me.com/path/to/my_image.jpg'</code> in the options hash when initializing your Thumbnail::Client. If you don't indicate a default image (or if you're doing a thumbnail action), you'll get the following Alexa "coming soon" default image:<br />
|
105
|
+
<img src="soon.jpg">
|
106
|
+
</p>
|
107
|
+
<h3>Image Size Options</h3>
|
108
|
+
|
109
|
+
<p>In both actions, you have a choice between large (201x147 pixels, ~8k) and small (111x82 pixels, ~3k) thumbnails. The Thumbnail::Client defaults to the large size, so if you want the smaller images, you should include <code>:size => :small</code> in your options hash when calling <code>Thumbnail::Client.new</code> (<em>note: there's also an attribute accessor for doing this after initialization</em>). Here are both sizes next to each other for comparison:<br />
|
110
|
+
<img src="craphound.jpg">
|
111
|
+
<img src="small_crap.jpg" />
|
112
|
+
</p>
|
113
|
+
|
114
|
+
<h2>Documentation</h2>
|
115
|
+
<p>
|
116
|
+
For more details about using Thumbnail, see <a href="http://thumbnail.rubyforge.org/rdoc">the RDoc documentation</a>. To learn more about AWS-AST, see <a href="http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=51">the Alexa Site Thumbnail Service Resource Center</a>.
|
117
|
+
</p>
|
118
|
+
|
119
|
+
<h2>How to submit patches</h2>
|
120
|
+
|
121
|
+
|
122
|
+
<p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people’s code</a> and then <a href="mailto:greg@mfdz.com">email me</a>.
|
123
|
+
|
124
|
+
|
125
|
+
<p>The trunk repository is <code>svn://rubyforge.org/var/svn/thumbnail/trunk</code> for anonymous access.</p>
|
126
|
+
|
127
|
+
|
128
|
+
<h2>License</h2>
|
129
|
+
|
130
|
+
|
131
|
+
<p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
|
132
|
+
|
133
|
+
|
134
|
+
<h2>Contact</h2>
|
135
|
+
|
136
|
+
|
137
|
+
<p>Comments are welcome. Send email to <a href="mailto:greg@mfdz.com">Greg Borenstein</a>. Visit my blog: <a href=http://www.urbanhonking.com/ideasfordozens>Ideas For Dozens</a>.</p>
|
138
|
+
<p class="coda">
|
139
|
+
This gem was packaged and released with the help of <a href="http://newgem.rubyforge.org/">newgem</a> by <a href="http://drnicwilliams.com/">Dr Nic</a>.<br />
|
140
|
+
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
141
|
+
</p>
|
142
|
+
</div>
|
143
|
+
|
144
|
+
<!-- insert site tracking codes here, like Google Urchin -->
|
145
|
+
|
146
|
+
</body>
|
147
|
+
</html>
|