rack-cache 1.2 → 1.3.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/doc/rack-cache.css DELETED
@@ -1,362 +0,0 @@
1
- /* rack-cache.css
2
- *---------------------------------------------------------------------------
3
- * Copyright (C) 2005-08 Ryan Tomayko <r@tomayko.com>
4
- */
5
-
6
-
7
- /* 18px base font size / 25px baseline */
8
- body {
9
- font-size:112.5%; /* 18px (probably) */
10
- line-height:1.3888; /* 25px */
11
- letter-spacing:-0.02em;
12
- margin:0 10px;
13
- font-family: 'lucida sans unicode', 'lucida grande',
14
- helvetica, 'bitstream vera sans', sans-serif;
15
- color:#556;
16
- background-color:#fff;
17
- }
18
-
19
- #container {
20
- max-width:45em;
21
- margin:0 auto;
22
- }
23
-
24
- h1, h2, h3 {
25
- font-family:georgia, 'bitstream vera sans serif', 'lucida grande',
26
- helvetica, verdana, sans-serif;
27
- font-weight:normal;
28
- letter-spacing:-0.05em;
29
- color:#000;
30
- }
31
- i, em {
32
- font-style:italic;
33
- }
34
- b, strong {
35
- font-weight:normal;
36
- color:#000;
37
- }
38
- blockquote {
39
- color:#555;
40
- }
41
- blockquote em {
42
- color:#333;
43
- font-style:italic;
44
- }
45
- blockquote strong {
46
- color:#333;
47
- font-weight: normal;
48
- }
49
- dt {
50
- font-weight:bold;
51
- color:#000;
52
- }
53
- tt, pre, code, samp, kbd {
54
- font-family: consolas, 'lucida console', 'bitstream vera sans mono',
55
- 'courier new', monospace;
56
- color: #000;
57
- }
58
- pre {
59
- color:#333;
60
- background-color:#f9f9f9;
61
- }
62
- code {
63
- color:#007A00;
64
- }
65
- pre code {
66
- color:#333;
67
- }
68
- pre.license {
69
- border:0;
70
- background:#fff;
71
- padding:0;
72
- font-size:1.1em;
73
- }
74
- a, a:link {
75
- color:#023;
76
- background:#eef;
77
- }
78
- a:visited {
79
- color:#345;
80
- background:#fff;
81
- }
82
- a:hover {
83
- background:#ccf;
84
- color:#000;
85
- text-decoration:none;
86
- }
87
-
88
-
89
- /* TYPOGRAPHY */
90
-
91
- p, ul, ol, dl, pre, blockquote, table, form {
92
- margin:1em 0;
93
- }
94
- dl {
95
- margin-left:2em;
96
- }
97
- hr {
98
- color:#eee;
99
- background-color:#ccc;
100
- border:0;
101
- height:1px;
102
- margin:1.5em 0;
103
- }
104
- blockquote {
105
- font-size:0.83333em; /* 15px */
106
- line-height:1.66666; /* 25px */
107
- margin:1.2em 3em;
108
- padding:0;
109
- }
110
- tt, pre, code, samp, kbd {
111
- font-size: 16px;
112
- line-height:1.1;
113
- }
114
- pre {
115
- margin:1.5em 0;
116
- padding:6px 4px 4px 6px;
117
- border:1px solid #eee;
118
- border-left-width:20px;
119
- overflow:auto;
120
- }
121
- h1 {
122
- font-size:2.3333em; /* 42px */
123
- line-height:1.1904; /* 50px */
124
- margin:0.5952em 0; /* 25px */
125
- }
126
- h2 {
127
- font-size:1.66666667em; /* 30px */
128
- line-height:1.2; /* 36px */
129
- margin:1em 0;
130
- }
131
- h3 {
132
- font-size:1.33333333em; /* 22px */
133
- line-height:1.13636363; /* 25px */
134
- margin:1em 0;
135
- }
136
- h3 code{
137
- font-size:0.95em;
138
- color:#000;
139
- }
140
- h4 {
141
- font-size:1em;
142
- font-weight:bold;
143
- line-height:1.5;
144
- margin:1em 0;
145
- }
146
- p small {
147
- font-size:0.8333; /* 15px */
148
- line-height:1.2;
149
- }
150
-
151
- /* Tables
152
- --------------------------------------------------------------------------- */
153
-
154
- table {
155
- width:100%;
156
- border-style:none;
157
- border-color:#ddd;
158
- padding:0;
159
- }
160
-
161
- th, td {
162
- padding: 4px 10px 4px 5px;
163
- border-style:solid;
164
- border-color:#fff;
165
- }
166
-
167
- th {
168
- font-weight: bold;
169
- background: #eef;
170
- }
171
-
172
- td {
173
- background: #f9f9f9;
174
- }
175
-
176
- tfoot {
177
- font-style: italic;
178
- }
179
-
180
- caption {
181
- background: #eee;
182
- }
183
-
184
- /* Header / Titling
185
- --------------------------------------------------------------------------- */
186
-
187
- #header {
188
- text-align:left;
189
- margin:1.5em auto 2em;
190
- float:left;
191
- width:100%;
192
- padding-bottom:1.5em;
193
- border-bottom:1px solid #777;
194
- }
195
- #header h1 {
196
- font-family: 'lucida sans unicode', 'lucida grande',
197
- helvetica, 'bitstream vera sans', sans-serif;
198
- font-size:5em;
199
- font-weight:bold;
200
- line-height:1;
201
- margin:0;
202
- float:left;
203
- color:#000;
204
- letter-spacing:-0.08em;
205
- }
206
- #header h1 a, #header h1 a:link, #header h1 a:visited, #header h1 a:hover {
207
- color:#000;
208
- text-decoration:none;
209
- background:transparent;
210
- }
211
- #header p {
212
- margin: 0;
213
- line-height:1.8;
214
- color: #777;
215
- text-transform:capitalize;
216
- font-variant:small-caps;
217
- float:right;
218
- }
219
- #header a, #header a:link, #header a:visited {
220
- color:#445;
221
- background:#fff;
222
- }
223
- #header a:hover {
224
- background:#ccf;
225
- color:#000;
226
- text-decoration:none;
227
- }
228
- #content {
229
- clear:both;
230
- }
231
-
232
- /* FOOTER */
233
-
234
- #footer {
235
- clear:both;
236
- color:#555;
237
- font-size:0.88888888em;
238
- line-height:1.5625;
239
- border-top:1px solid #ddd;
240
- padding:19px 0 0 0;
241
- margin:40px 0 20px 0;
242
- text-align:center;
243
- }
244
- #footer p {
245
- margin:0;
246
- }
247
- #footer form {
248
- float:right;
249
- }
250
- #footer input{
251
- font-size:10px;
252
- }
253
-
254
- /* MISC HELPER STYLES */
255
-
256
- ul.clean, ol.clean {
257
- list-style-type: none;
258
- padding-left: 0;
259
- }
260
- .caps {
261
- font-variant:small-caps;
262
- }
263
- .clear {
264
- clear:both;
265
- }
266
- .left{
267
- float:left;
268
- }
269
- .right{
270
- float:right;
271
- }
272
- .center{
273
- text-align:center;
274
- }
275
- .intro {
276
- font-size:0.833333em; /* 15px */
277
- line-height:1.666667; /* 25px */
278
- border:1px solid #ccc;
279
- padding:0.5em;
280
- font-style:italic;
281
- color:#555;
282
- }
283
- a.hash,
284
- a.hash:link,
285
- a.hash:visited {
286
- display:block;
287
- float:right;
288
- background:#fff;
289
- font-size:0.8em;
290
- text-decoration:none;
291
- line-height:2;
292
- color:#999;
293
- }
294
- a.hash:hover {
295
- color:MediumOrchid;
296
- }
297
-
298
- /* PRINT */
299
-
300
- @media print {
301
- html, body, #container {
302
- margin:0;
303
- }
304
- #container {
305
- width:100%;
306
- max-width:100%;
307
- }
308
- #header {
309
- margin-top:0;
310
- }
311
- #header p {
312
- display:none;
313
- }
314
- #footer {
315
- display:none;
316
- }
317
- a, a:link, a:visited {
318
- color:#000;
319
- background:#fff;
320
- text-decoration:none;
321
- }
322
- pre.license {
323
- font-size:0.95em;
324
- }
325
- @page {
326
- size:8.5in 11in;
327
- }
328
- }
329
-
330
- /* PRETTIFICATION OF SOURCE CODE */
331
-
332
- .str { color: #181; font-style:italic; }
333
- .kwd { color: #369; }
334
- .com { color: #666; }
335
- .typ { color: #c40; }
336
- .lit { color: #900; }
337
- .pun { color: #000; font-weight: bold; }
338
- .pln { color: #333; }
339
- .tag { color: #369; font-weight: bold; }
340
- .atn { color: #939; font-weight: bold }
341
- .atv { color: #181; }
342
- .dec { color: #606; }
343
-
344
- @media print {
345
- .str { color: #060; }
346
- .kwd { color: #006; font-weight: bold; }
347
- .com { color: #600; font-style: italic; }
348
- .typ { color: #404; font-weight: bold; }
349
- .lit { color: #044; }
350
- .pun { color: #440; }
351
- .pln { color: #000; }
352
- .tag { color: #006; font-weight: bold; }
353
- .atn { color: #404; }
354
- .atv { color: #060; }
355
- }
356
-
357
- /* FUCKING IE */
358
-
359
- * html body{width:40em}
360
- * html div.index{width:34.5em}
361
-
362
- /* vim: set ft=css ts=4 sw=4 noexpandtab: */
data/doc/server.ru DELETED
@@ -1,34 +0,0 @@
1
- # Rackup config that serves the contents of Rack::Cache's
2
- # doc directory. The documentation is rebuilt on each request.
3
-
4
- # Rewrites URLs like conventional web server configs.
5
- class Rewriter < Struct.new(:app)
6
- def call(env)
7
- if env['PATH_INFO'] =~ /\/$/
8
- env['PATH_INFO'] += 'index.html'
9
- elsif env['PATH_INFO'] !~ /\.\w+$/
10
- env['PATH_INFO'] += '.html'
11
- end
12
- app.call(env)
13
- end
14
- end
15
-
16
- # Rebuilds documentation on each request.
17
- class DocBuilder < Struct.new(:app)
18
- def call(env)
19
- if env['PATH_INFO'] !~ /\.(css|js|gif|jpg|png|ico)$/
20
- env['rack.errors'] << "*** rebuilding documentation (rake -s doc)\n"
21
- system "rake -s doc"
22
- end
23
- app.call(env)
24
- end
25
- end
26
-
27
- use Rack::CommonLogger
28
- use DocBuilder
29
- use Rewriter
30
- use Rack::Static, :root => File.dirname(__FILE__), :urls => ["/"]
31
-
32
- run(lambda{|env| [404,{},'<h1>Not Found</h1>']})
33
-
34
- # vim: ft=ruby
data/doc/storage.markdown DELETED
@@ -1,164 +0,0 @@
1
- Storage
2
- =======
3
-
4
- __Rack::Cache__ runs within each of your backend application processes and does not
5
- rely on a single intermediary process like most types of proxy cache
6
- implementations. Because of this, the storage subsystem has implications on not
7
- only where cache data is stored but whether the cache is properly distributed
8
- between multiple backend processes. It is highly recommended that you read and
9
- understand the following before choosing a storage implementation.
10
-
11
- Storage Areas
12
- -------------
13
-
14
- __Rack::Cache__ stores cache entries in two separate configurable storage
15
- areas: a _MetaStore_ and an _EntityStore_.
16
-
17
- The _MetaStore_ keeps high level information about each cache entry, including
18
- the request/response headers and other status information. When a request is
19
- received, the core caching logic uses this meta information to determine whether
20
- a fresh cache entry exists that can satisfy the request.
21
-
22
- The _EntityStore_ is where the actual response body content is stored. When a
23
- response is entered into the cache, a SHA1 digest of the response body content
24
- is calculated and used as a key. The entries stored in the MetaStore reference
25
- their response bodies using this SHA1 key.
26
-
27
- Separating request/response meta-data from response content has a few important
28
- advantages:
29
-
30
- * Different storage types can be used for meta and entity storage. For
31
- example, it may be desirable to use memcached to store meta information
32
- while using the filesystem for entity storage.
33
-
34
- * Cache entry meta-data may be retrieved quickly without also retrieving
35
- response bodies. This avoids significant overhead when the cache misses
36
- or only requires validation.
37
-
38
- * Multiple different responses may include the same exact response body. In
39
- these cases, the actual body content is stored once and referenced from
40
- each of the meta store entries.
41
-
42
- You should consider how the meta and entity stores differ when choosing a storage
43
- implementation. The MetaStore does not require nearly as much memory as the
44
- EntityStore and is accessed much more frequently. The EntityStore can grow quite
45
- large and raw performance is less of a concern. Using a memory based storage
46
- implementation (`heap` or `memcached`) for the MetaStore is strongly advised,
47
- while a disk based storage implementation (`file`) is often satisfactory for
48
- the EntityStore and uses much less memory.
49
-
50
- Storage Configuration
51
- ---------------------
52
-
53
- The MetaStore and EntityStore used for a particular request is determined by
54
- inspecting the `rack-cache.metastore` and `rack-cache.entitystore` Rack env
55
- variables. The value of these variables is a URI that identifies the storage
56
- type and location (URI formats are documented in the following section).
57
-
58
- The `heap:/` storage is assumed if either storage type is not explicitly
59
- provided. This storage type has significant drawbacks for most types of
60
- deployments so explicit configuration is advised.
61
-
62
- The default metastore and entitystore values can be specified when the
63
- __Rack::Cache__ object is added to the Rack middleware pipeline as follows:
64
-
65
- use Rack::Cache,
66
- :metastore => 'file:/var/cache/rack/meta',
67
- :entitystore => 'file:/var/cache/rack/body'
68
-
69
- Alternatively, the `rack-cache.metastore` and `rack-cache.entitystore`
70
- variables may be set in the Rack environment by an upstream component.
71
-
72
- Storage Implementations
73
- -----------------------
74
-
75
- __Rack::Cache__ includes meta and entity storage implementations backed by local
76
- process memory ("heap storage"), the file system ("disk storage"), and
77
- memcached. This section includes information on configuring __Rack::Cache__ to
78
- use a specific storage implementation as well as pros and cons of each.
79
-
80
- ### Heap Storage
81
-
82
- Uses local process memory to store cached entries.
83
-
84
- use Rack::Cache,
85
- :metastore => 'heap:/',
86
- :entitystore => 'heap:/'
87
-
88
- The heap storage backend is simple, fast, and mostly useless. All cache
89
- information is stored in each backend application's local process memory (using
90
- a normal Hash, in fact), which means that data cached under one backend is
91
- invisible to all other backends. This leads to low cache hit rates and excessive
92
- memory use, the magnitude of which is a function of the number of backends in
93
- use. Further, the heap storage provides no mechanism for purging unused entries
94
- so memory use is guaranteed to exceed that available, given enough time and
95
- utilization.
96
-
97
- Use of heap storage is recommended only for testing purposes or for very
98
- simple/single-backend deployment scenarios where the number of resources served
99
- is small and well understood.
100
-
101
- ### Disk Storage
102
-
103
- Stores cached entries on the filesystem.
104
-
105
- use Rack::Cache,
106
- :metastore => 'file:/var/cache/rack/meta',
107
- :entitystore => 'file:/var/cache/rack/body'
108
-
109
- The URI may specify an absolute, relative, or home-rooted path:
110
-
111
- * `file:/storage/path` - absolute path to storage directory.
112
- * `file:storage/path` - relative path to storage directory, rooted at the
113
- process's current working directory (`Dir.pwd`).
114
- * `file:~user/storage/path` - path to storage directory, rooted at the
115
- specified user's home directory.
116
- * `file:~/storage/path` - path to storage directory, rooted at the current
117
- user's home directory.
118
-
119
- File system storage is simple, requires no special daemons or libraries, has a
120
- tiny memory footprint, and allows multiple backends to share a single cache; it
121
- is one of the slower storage implementations, however. Its use is recommended in
122
- cases where memory is limited or in environments where more complex storage
123
- backends (i.e., memcached) are not available. In many cases, it may be
124
- acceptable (and even optimal) to use file system storage for the entitystore and
125
- a more performant storage implementation (i.e. memcached) for the metastore.
126
-
127
- __NOTE:__ When both the metastore and entitystore are configured to use file
128
- system storage, they should be set to different paths to prevent any chance of
129
- collision.
130
-
131
- ### Memcached Storage
132
-
133
- Stores cached entries in a remote [memcached](http://www.danga.com/memcached/)
134
- instance.
135
-
136
- use Rack::Cache,
137
- :metastore => 'memcached://localhost:11211/meta',
138
- :entitystore => 'memcached://localhost:11211/body'
139
-
140
- The URI must specify the host and port of a remote memcached daemon. The path
141
- portion is an optional (but recommended) namespace that is prepended to each
142
- cache key.
143
-
144
- The memcached storage backend requires either the `dalli` or `memcached`
145
- libraries. By default, the `dalli` library is used; require the `memcached`
146
- library explicitly to use it instead.
147
-
148
- gem install dalli
149
-
150
- Memcached storage is reasonably fast and allows multiple backends to share a
151
- single cache. It is also the only storage implementation that allows the cache
152
- to reside somewhere other than the local machine. The memcached daemon stores
153
- all data in local process memory so using it for the entitystore can result in
154
- heavy memory usage. It is by far the best option for the metastore in
155
- deployments with multiple backend application processes since it allows the
156
- cache to be properly distributed and provides fast access to the
157
- meta-information required to perform cache logic. Memcached is considerably more
158
- complex than the other storage implementations, requiring a separate daemon
159
- process and extra libraries. Still, its use is recommended in all cases where
160
- you can get away with it.
161
-
162
- [e]: http://blog.evanweaver.com/files/doc/fauna/memcached/files/README.html
163
- [f]: http://blog.evanweaver.com/articles/2008/01/21/b-the-fastest-u-can-b-memcached/
164
- [l]: http://tangent.org/552/libmemcached.html
@@ -1,21 +0,0 @@
1
- require 'sinatra'
2
- require 'rack/cache'
3
-
4
- use Rack::Cache do
5
- set :verbose, true
6
- set :metastore, 'heap:/'
7
- set :entitystore, 'heap:/'
8
- end
9
-
10
- before do
11
- last_modified $updated_at ||= Time.now
12
- end
13
-
14
- get '/' do
15
- erb :index
16
- end
17
-
18
- put '/' do
19
- $updated_at = nil
20
- redirect '/'
21
- end
@@ -1,44 +0,0 @@
1
- <html>
2
- <head>
3
- <title>Sample Rack::Cache Sinatra app</title>
4
- <style type="text/css" media="screen">
5
- body {
6
- font-family: Georgia;
7
- font-size: 24px;
8
- text-align: center;
9
- }
10
-
11
- #headers {
12
- font-size: 16px;
13
- }
14
-
15
- input {
16
- font-size: 24px;
17
- cursor: pointer;
18
- }
19
- </style>
20
- </head>
21
- <body>
22
- <h1>Last updated at: <%= $updated_at.strftime('%l:%m:%S%P') %></h1>
23
-
24
- <p>
25
- <form action="/" method="post">
26
- <input type="hidden" name="_method" value="PUT">
27
- <input type="submit" value="Expire the cache.">
28
- </form>
29
- </p>
30
-
31
- <div id="headers">
32
- <h3>Headers:</h3>
33
-
34
- <% response.headers.each do |key, value| %>
35
- <p><%= key %>: <%= value %></p>
36
- <% end %>
37
-
38
- <h3>Params:</h3>
39
- <% params.each do |key, value| %>
40
- <p><%= key %>: <%= value || '(blank)' %></p>
41
- <% end %>
42
- </div>
43
- </body>
44
- </html>
data/rack-cache.gemspec DELETED
@@ -1,75 +0,0 @@
1
- Gem::Specification.new do |s|
2
- s.specification_version = 2 if s.respond_to? :specification_version=
3
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
4
-
5
- s.name = 'rack-cache'
6
- s.version = '1.2'
7
- s.date = '2012-03-05'
8
-
9
- s.summary = "HTTP Caching for Rack"
10
- s.description = "Rack::Cache is suitable as a quick drop-in component to enable HTTP caching for Rack-based applications that produce freshness (Expires, Cache-Control) and/or validation (Last-Modified, ETag) information."
11
-
12
- s.authors = ["Ryan Tomayko"]
13
- s.email = "r@tomayko.com"
14
-
15
- # = MANIFEST =
16
- s.files = %w[
17
- CHANGES
18
- COPYING
19
- Gemfile
20
- README
21
- Rakefile
22
- TODO
23
- doc/configuration.markdown
24
- doc/faq.markdown
25
- doc/index.markdown
26
- doc/layout.html.erb
27
- doc/license.markdown
28
- doc/rack-cache.css
29
- doc/server.ru
30
- doc/storage.markdown
31
- example/sinatra/app.rb
32
- example/sinatra/views/index.erb
33
- lib/rack-cache.rb
34
- lib/rack/cache.rb
35
- lib/rack/cache/appengine.rb
36
- lib/rack/cache/cachecontrol.rb
37
- lib/rack/cache/context.rb
38
- lib/rack/cache/entitystore.rb
39
- lib/rack/cache/key.rb
40
- lib/rack/cache/metastore.rb
41
- lib/rack/cache/options.rb
42
- lib/rack/cache/request.rb
43
- lib/rack/cache/response.rb
44
- lib/rack/cache/storage.rb
45
- rack-cache.gemspec
46
- test/cache_test.rb
47
- test/cachecontrol_test.rb
48
- test/context_test.rb
49
- test/entitystore_test.rb
50
- test/key_test.rb
51
- test/metastore_test.rb
52
- test/options_test.rb
53
- test/pony.jpg
54
- test/request_test.rb
55
- test/response_test.rb
56
- test/spec_setup.rb
57
- test/storage_test.rb
58
- ]
59
- # = MANIFEST =
60
-
61
- s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
62
-
63
- s.extra_rdoc_files = %w[README COPYING TODO CHANGES]
64
- s.add_dependency 'rack', '>= 0.4'
65
-
66
- s.add_development_dependency 'bacon'
67
- s.add_development_dependency 'memcached'
68
- s.add_development_dependency 'dalli'
69
-
70
- s.has_rdoc = true
71
- s.homepage = "http://tomayko.com/src/rack-cache/"
72
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rack::Cache", "--main", "Rack::Cache"]
73
- s.require_paths = %w[lib]
74
- s.rubygems_version = '1.1.1'
75
- end