thumbnail 0.2.0
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/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>
|