1NAME
2 Image::Delivery - Efficient transformation and delivery of web images
3
4INTRODUCTION
5 Many web applications generate or otherwise deliver graphics as part of
6 their interface. Getting the delivery of these images right is tricky,
7 and developers usually need to make trade-offs in order to get a usable
8 mechanism.
9
10 Image::Delivery is an extremely sophisticated module for delivering
11 these generated images. It is designed to be powerful, flexible,
12 extensible, scalable, secure, stable and correct, and use a minimum of
13 resources.
14
15DESIGN
16 Because it can take a little bit of work to set up Image::Delivery, we
17 will start with a quick once-over of the design of the API, and the
18 reasons and use cases that drove it.
19
20 Preventing Multiple Server Calls
21 Use Case 1: CVS Monitor
22 The initial idea for Image::Delivery was due to some problems with
23 the design of CVS Monitor (L<http://ali.as/devel/cvsmonitor/), an advanced
24 but extremely resource-hungry MVC CGI application. Many of the CVS Monitor
25 views have a single large graph on them, which involves a second call to the
26 server that starts just before the previous call ends. Generating the graph
27 took minimal extra effort, but the overhead of starting another process and
28 loading another 100meg of data creates a double whammy hit to the server.
29
30 What would be ideal would be to generate both at once and have the browser
31 get the image without a CGI hit.
32
33 The solution to this problem, and the primary mechanism that
34 Image::Delivery implements could be called "Static Delivery via Cached
35 Disk", but is best demonstrated with the diagram outlined in General
36 Structure below.
37
38 Use Case 2: Thumbnails
39 One problem with thumbnailing is the vast number that need to be generated.
40 When done on demand, if generated by the image request, you will have large
41 numbers of processes working. The normal solution is to pre-generate the
42 thumbnails, potentially polluting image directories.
43
44 Image::Delivery stores all images in one central cache, so that the
45 original images are unaffected.
46
47 General Structure
48 Image Provider
49 |
50 |BLOB + TransformPath
51 |
52 \1/
53 Image::Delivery
54 | \
55 | |
56 | |
57 \2/ |
58 Hard Disk |
59 /5\ | |URI
60 | | |
61 | | |
62 | \6/ |
63 Web Server |
64 /4\ | /
65 | |gzip /
66 \ | /
67 \ \7/ \3/
68 Web Browser
69
70 1) Image Data pulled from Object/Provider
71 An Object, or a Provider that accesses the data from outside the API,
72 generates or obtains the image data and various metadata that describes
73 the image data.
74
75 2) Image Written to File-System
76 Image::Delivery writes the image to the filesystem with a specific file
77 name
78
79 3) URI sent to Browser in HTML
80 Image::Delivery determines the matching URI that points to the location
81 of the written file, and provides it to be used in an "img" tag in the
82 generated HTML page.
83
84 4) Web Browser Requests Image
85 Having received the HTML, the browser requests the image from the web
86 server.
87
88 5) Web Server Finds Image File
89 The web server receives the image request and finds the file that was
90 written at step 2)
91
92 6) Web Server Retrieves Image File
93 Web server reads the file like any other plain file
94
95 7) Web Server Sends File to Browser
96 Web server sends the file off to the browser
97
98 Digest::TransformPath
99 Image::Delivery works around source objects. Each source object may want
100 to work with more than one image, and each image may need to come in
101 several different versions. In short, there can be lots of variations of
102 images.
103
104 To handle this, we utilise (or SHOULD utilise) Digest::TransformPath to
105 help identify the images, with a 10 digit digest built into the
106 filename.
107
108 Might as Well Cache Them
109 Since we went to all that effort to write the file, its relatively easy
110 to add caching. But the most important thing if we are going to cache is
111 to have a good file naming scheme.
112
113 Image::Delivery Naming Scheme
114 In order to make this all work, the naming scheme is critical.
115
116 The basic path format is:
117
118 $ROOT/Object.id/checksum.type
119
120 Object.id
121 When an object is updated, it may have any number of Image fields, which
122 may each have any number of scaled/rotated/morphed/derived images. When
123 a source object is updated, some or all of these need to be cleared.
124
125 checksum
126 The checksum calculated from the TransformPath does not describe any of
127 the data, only the data source and modifications to it. This means that
128 it is possible to cheaply test if the image for a particular transform
129 has already been created, without having to access any of the data in
130 the actual images.
131
132 type
133 Because we accept image data in a variety of formats, its not possible
134 to know what image type any given image should be. So when testing we
135 simply check the lot until we find one.
136
137 Generally, rather than test 10-15 types, the Provider will inform us of
138 the types to expect. :)
139
140 Operation Profile
141 All of this junk gives the module the following properties
142
143 - Intrinsicaly supports all major image types
144
145 - No pre-generation of images, generates everything on-the-fly
146
147 - Image names are secure and can't be predicted
148
149 - All images for any page are processed in one process hit
150
151 - Cache checking is extremely quick
152
153 - Never touches image source data when not filling the cache
154
155 - Handles many images. Storage extendable to support thousands to
156 millions of individual images
157
158 - Multiple hosts can work with the same Image cache
159
160 - Images can be delivered by a different web server to the application
161
162DESCRIPTION
163 Image::Delivery is very powerful, but setting it up may take a little
164 bit of work.
165
166 Setting up the URI <-> path mapping
167 First, you need to become aquainted with HTML::Location. This is used as
168 the basis for the mapping between the disc and a URI.
169
170 You should also make sure that whatever process will be running will
171 have write permissions to the appropriate directory.
172
173 For starters, we would suggest creating the cache directory just under
174 the root of a website, at "$ROOT/cache", which will be linked to
175 "http://yourwebsite.com/cache/".
176
177 This will let you create your HTML::Location.
178
179 # Set up the location of the cache
180 my $Location = HTML::Location->new(
181 "$ROOT/cache",
182 "http://yourwebsite.com/cache"
183 );
184
185 This gives you the absolute minimum Image::Delivery itself needs to get
186 rolling. With a location to manage, you can then start to fire images at
187 it, and it will store them and hand you back a HTML::Location for the
188 actual file.
189
190 # Create the Image::Delivery object
191 my $Delivery = Image::Delivery->new(
192 Location => $Location,
193 );
194
195 However, the tricky bit is probably setting up your Provider class.
196 Although the abstract class implements much of the details and defaults
197 for you, you are probably still going to need to do some work to tie the
198 two together.
199
200STATUS
201 While the concept and design are fairly well understood and unlikely to
202 change, there is an unfortunate situation with regards to the Cache::
203 family of modules.
204
205 Although originally written to live at Cache::Web and to be a little
206 more general, it was felt by the maintainer that Cache::Web would
207 represent the module as being a full member of the Cache:: family, which
208 it is not.
209
210 However, during the first few releases I hope to at least try to move
211 the API of Image::Delivery as close to Cache:: as possible, possibly
212 under a common Cache::Interface class, to gain some potential benefits
213 from code written on top of it.
214
215 Until these comments are updated, you should assume that the API may
216 undergo some changes.
217
218METHODS
219 new %params
220 The "new" constructor creates a new Image::Delivery object. It takes a
221 number of required and optional parameters, provided as a set of
222 key/value pairs.
223
224 Location
225 The required Location parameter
226
227 Location
228 The "Location" method returns the HTML::Location that was used when
229 creating the Image::Delivery.
230
231 filename $TransformPath | $Provider
232 The "filename" method determines, for a given $TransformPath or
233 $Provider, the file name that the Image should be written to, excluding
234 the file type.
235
236 This is the method most likely to be overloaded, so enable a different
237 naming scheme.
238
239 exists $TransformPath | $Provider
240 For a given Digest::TransformPath, or a ::Provider which contains one,
241 check to see the a file exists for it in the cache already.
242
243 Returns the HTML::Location of the image if it exists, false if it does
244 not exist, or "undef" on error.
245
246 get $TransformPath | $Provider
247 The "get" methods gets the contents of a cached file from the cache, if
248 it exists. You should generally check that the image "exists" first
249 before trying to get it.
250
251 Returns a reference to a SCALAR containing the image data if the image
252 exists. Returns "undef" if the image does not exist, or some other error
253 occurs.
254
255 set $Provider
256 The "set" method stores an image in the cache, shortcutting if the image
257 has already been stored.
258
259 Returns the HTML::Location of the stored image on success, or "undef" on
260 error.
261
262 clear $TransformPath
263 The "clear" method allows you to explicitly delete an image from the
264 cache. This would generally be done for security purposes, as the cache
265 cleaners will generally harvest files directly, rather than going via
266 TransformPaths.
267
268 Returns true if the image was removed, or did not exist. Returns "undef"
269 on error.
270
271TO DO
272 - Add ability to mask indexes with empty HTML files
273
274 - Add cache clearing capabilities
275
276 - Add file locking to prevent race conditions in the cache
277
278 - Add pluggable cache cleaners
279
280SUPPORT
281 All bugs should be filed via the bug tracker at
282
283 <http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Image-Delivery>
284
285 For other issues, contact the author
286
287AUTHORS
288 Adam Kennedy <adamk@cpan.org>
289
290COPYRIGHT
291 Copyright 2004 - 2007 Adam Kennedy.
292
293 This program is free software; you can redistribute it and/or modify it
294 under the same terms as Perl itself.
295
296 The full text of the license can be found in the LICENSE file included
297 with this module.
298
299