rack-cache 0.3.0 → 0.4

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.

Potentially problematic release.


This version of rack-cache might be problematic. Click here for more details.

Files changed (44) hide show
  1. data/CHANGES +43 -0
  2. data/README +18 -9
  3. data/Rakefile +1 -14
  4. data/TODO +13 -14
  5. data/doc/configuration.markdown +7 -153
  6. data/doc/faq.markdown +8 -0
  7. data/doc/index.markdown +7 -9
  8. data/example/sinatra/app.rb +25 -0
  9. data/example/sinatra/views/index.erb +44 -0
  10. data/lib/rack/cache.rb +5 -11
  11. data/lib/rack/cache/cachecontrol.rb +193 -0
  12. data/lib/rack/cache/context.rb +190 -52
  13. data/lib/rack/cache/entitystore.rb +10 -4
  14. data/lib/rack/cache/key.rb +52 -0
  15. data/lib/rack/cache/metastore.rb +52 -16
  16. data/lib/rack/cache/options.rb +60 -39
  17. data/lib/rack/cache/request.rb +11 -15
  18. data/lib/rack/cache/response.rb +221 -30
  19. data/lib/rack/cache/storage.rb +1 -2
  20. data/rack-cache.gemspec +9 -15
  21. data/test/cache_test.rb +9 -6
  22. data/test/cachecontrol_test.rb +139 -0
  23. data/test/context_test.rb +251 -169
  24. data/test/entitystore_test.rb +12 -11
  25. data/test/key_test.rb +50 -0
  26. data/test/metastore_test.rb +57 -14
  27. data/test/options_test.rb +11 -0
  28. data/test/request_test.rb +19 -0
  29. data/test/response_test.rb +164 -23
  30. data/test/spec_setup.rb +7 -0
  31. metadata +12 -20
  32. data/doc/events.dot +0 -27
  33. data/lib/rack/cache/config.rb +0 -65
  34. data/lib/rack/cache/config/busters.rb +0 -16
  35. data/lib/rack/cache/config/default.rb +0 -133
  36. data/lib/rack/cache/config/no-cache.rb +0 -13
  37. data/lib/rack/cache/core.rb +0 -299
  38. data/lib/rack/cache/headers.rb +0 -325
  39. data/lib/rack/utils/environment_headers.rb +0 -78
  40. data/test/config_test.rb +0 -66
  41. data/test/core_test.rb +0 -84
  42. data/test/environment_headers_test.rb +0 -69
  43. data/test/headers_test.rb +0 -298
  44. data/test/logging_test.rb +0 -45
data/CHANGES CHANGED
@@ -1,3 +1,46 @@
1
+ ## 0.4.0 / March 2009
2
+
3
+ * Ruby 1.9.1 / Rack 1.0 compatible.
4
+
5
+ * Invalidate cache entries that match the request URL on non-GET/HEAD
6
+ requests. i.e., POST, PUT, DELETE cause matching cache entries to
7
+ be invalidated. The cache entry is validated with the backend using
8
+ a conditional GET the next time it's requested.
9
+
10
+ * Implement "Cache-Control: max-age=N" request directive by forcing
11
+ validation when the max-age provided exceeds the age of the cache
12
+ entry. This can be disabled by setting the "allow_revalidate" option to
13
+ false.
14
+
15
+ * Properly implement "Cache-Control: no-cache" request directive by
16
+ performing a full reload. RFC 2616 states that when "no-cache" is
17
+ present in the request, the cache MUST NOT serve a stored response even
18
+ after successful validation. This is slightly different from the
19
+ "no-cache" directive in responses, which indicates that the cache must
20
+ first validate its entry with the origin. Previously, we implemented
21
+ "no-cache" on requests by passing so no new cache entry would be stored
22
+ based on the response. Now we treat it as a forced miss and enter the
23
+ response into the cache if it's cacheable. This can be disabled by
24
+ setting the "allow_reload" option to false.
25
+
26
+ * Assume identical semantics for the "Pragma: no-cache" request header
27
+ as the "Cache-Control: no-cache" directive described above.
28
+
29
+ * Less crazy logging. When the verbose option is set, a single log entry
30
+ is written with a comma separated list of trace events. For example, if
31
+ the cache was stale but validated, the following log entry would be
32
+ written: "cache: stale, valid, store". When the verbose option is false,
33
+ no logging occurs.
34
+
35
+ * Added "X-Rack-Cache" response header with the same comma separated trace
36
+ value as described above. This gives some visibility into how the cache
37
+ processed the request.
38
+
39
+ * Add support for canonicalized cache keys, as well as custom cache key
40
+ generators, which are specified in the options as :cache_key as either
41
+ any object that has a call() or as a block. Cache key generators get
42
+ passed a request object and return a cache key string.
43
+
1
44
  ## 0.3.0 / December 2008
2
45
 
3
46
  * Add support for public and private cache control directives. Responses
data/README CHANGED
@@ -12,7 +12,6 @@ validation (Last-Modified, ETag) information:
12
12
  * Cache-Control: public, private, max-age, s-maxage, must-revalidate,
13
13
  and proxy-revalidate.
14
14
  * Portable: 100% Ruby / works with any Rack-enabled framework
15
- * Configuration language for advanced caching policies
16
15
  * Disk, memcached, and heap memory storage backends
17
16
 
18
17
  For more information about Rack::Cache features and usage, see:
@@ -25,14 +24,6 @@ caching solution for small to medium sized deployments. More sophisticated /
25
24
  high-performance caching systems (e.g., Varnish, Squid, httpd/mod-cache) may be
26
25
  more appropriate for large deployments with significant throughput requirements.
27
26
 
28
- Status
29
- ------
30
-
31
- Rack::Cache is a young and experimental project that is likely to change
32
- substantially and may not be wholly functional, consistent, fast, or correct.
33
- The current focus is on reaching basic compliance with RFC 2616 and providing
34
- good documentation.
35
-
36
27
  Installation
37
28
  ------------
38
29
 
@@ -66,6 +57,24 @@ Assuming you've designed your backend application to take advantage of HTTP's
66
57
  caching features, no further code or configuration is required for basic
67
58
  caching.
68
59
 
60
+ Using with Rails
61
+ ----------------
62
+
63
+ Add this to your `config/environment.rb`:
64
+
65
+ config.middleware.use Rack::Cache,
66
+ :verbose => true,
67
+ :metastore => 'file:/var/cache/rack/meta',
68
+ :entitystore => 'file:/var/cache/rack/body'
69
+
70
+ You should now see `Rack::Cache` listed in the middleware pipeline:
71
+
72
+ rake middleware
73
+
74
+ See the following for more information:
75
+
76
+ http://snippets.aktagon.com/snippets/302
77
+
69
78
  Links
70
79
  -----
71
80
 
data/Rakefile CHANGED
@@ -31,7 +31,7 @@ end
31
31
 
32
32
  # DOC =======================================================================
33
33
  desc 'Build all documentation'
34
- task :doc => %w[doc:api doc:graphs doc:markdown]
34
+ task :doc => %w[doc:api doc:markdown]
35
35
 
36
36
  # requires the hanna gem:
37
37
  # gem install mislav-hanna --source=http://gems.github.com
@@ -55,19 +55,6 @@ file 'doc/api/index.html' => FileList['lib/**/*.rb'] do |f|
55
55
  end
56
56
  CLEAN.include 'doc/api'
57
57
 
58
- desc 'Build graphviz graphs'
59
- task 'doc:graphs'
60
- %w[pdf png svg].each do |filetype|
61
- FileList["doc/*.dot"].each do |source|
62
- dest = source.sub(/dot$/, filetype)
63
- file dest => source do |f|
64
- sh "dot -T#{filetype} #{source} -o #{f.name}"
65
- end
66
- task 'doc:graphs' => dest
67
- CLEAN.include dest
68
- end
69
- end
70
-
71
58
  desc 'Build markdown documentation files'
72
59
  task 'doc:markdown'
73
60
  FileList['doc/*.markdown'].each do |source|
data/TODO CHANGED
@@ -1,21 +1,20 @@
1
- ## 0.4
2
-
3
- - liberal, conservative, sane caching configs
4
- - Sample apps: Rack, Rails, Sinatra, Merb, etc.
5
- - busters.rb and no-cache.rb doc and tests
6
- - Canonicalized URL for cache key:
7
- - sorts params by key, then value
8
- - urlencodes /[^ A-Za-z0-9_.-]/ host, path, and param key/value
9
- - Custom cache keys
10
- - Cache invalidation on PUT, POST, DELETE.
11
- - Invalidate at the request URI; or, anything that's "near" the request URI.
12
- - Invalidate at the URI of the Location or Content-Location response header.
13
-
14
1
  ## Backlog
15
2
 
3
+ - Move breakers.rb configuration file into rack-contrib as a middleware
4
+ component.
5
+ - Sample apps: Rack, Rails, Sinatra, Merb, etc.
6
+ - Use Bacon instead of test/spec
7
+ - Work with both memcache and memcached gems (memcached hasn't built on MacOS
8
+ for some time now).
9
+ - Fast path pass processing. We do a lot more than necessary just to determine
10
+ that the response should be passed through untouched.
11
+ - Don't purge/remove cache entries when invalidating. The entries should be
12
+ marked as stale and be forced revalidated on the next request instead of
13
+ being removed entirely.
16
14
  - Add missing Expires header if we have a max-age.
17
- - Purge/invalidate specific cache entries
18
15
  - Purge/invalidate everything
16
+ - Invalidate at the URI of the Location or Content-Location response header
17
+ on POST, PUT, or DELETE that results in a redirect.
19
18
  - Maximum size of cached entity
20
19
  - Last-Modified factor: requests that have a Last-Modified header but no Expires
21
20
  header have a TTL assigned based on the last modified age of the response:
@@ -1,51 +1,17 @@
1
- Configuration Language
2
- ======================
1
+ Configuration
2
+ =============
3
3
 
4
4
  __Rack::Cache__ includes a configuration system that can be used to specify
5
5
  fairly sophisticated cache policy on a global or per-request basis.
6
6
 
7
- - [Synopsis](#synopsis)
8
- - [Setting Cache Options](#setopt)
9
- - [Cache Option Reference](#options)
10
- - [Configuration Machinery - Events and Transitions](#machinery)
11
- - [Importing Configuration](#import)
12
- - [Default Configuration Machinery](#default)
13
- - [Notes](#notes)
14
-
15
- <a id='synopsis'></a>
16
-
17
- Synopsis
18
- --------
19
-
20
- use Rack::Cache do
21
- # set cache related options
22
- set :verbose, true
23
- set :metastore, 'memcached://localhost:11211'
24
- set :entitystore, 'file:/var/cache/rack/body'
25
-
26
- # override events / transitions
27
- on :receive do
28
- pass! if request.url =~ %r|/dontcache/|
29
- error! 402 if request.referrer =~ /digg.com/
30
- end
31
-
32
- on :miss do
33
- trace 'missed: %s', request.url
34
- end
35
-
36
- # bring in other configuration machinery
37
- import 'rack/cache/config/breakers'
38
- import 'mycacheconfig'
39
- end
40
-
41
7
  <a id='setopt'></a>
42
8
 
43
9
  Setting Cache Options
44
10
  ---------------------
45
11
 
46
- Cache options can be set when the __Rack::Cache__ object is created; or by using
47
- the `set` method within a configuration block; or by setting a
48
- `rack-cache.<option>` variable in __Rack__'s __Environment__.
12
+ Cache options can be set when the __Rack::Cache__ object is created,
13
+ or by setting a `rack-cache.<option>` variable in __Rack__'s
14
+ __Environment__.
49
15
 
50
16
  When the __Rack::Cache__ object is instantiated:
51
17
 
@@ -54,14 +20,6 @@ When the __Rack::Cache__ object is instantiated:
54
20
  :metastore => 'memcached://localhost:11211/',
55
21
  :entitystore => 'file:/var/cache/rack'
56
22
 
57
- Using the `set` method within __Rack::Cache__'s configuration context:
58
-
59
- use Rack::Cache do
60
- set :verbose, true
61
- set :metastore, 'memcached://localhost:11211/'
62
- set :entitystore, 'file:/var/cache/rack'
63
- end
64
-
65
23
  Using __Rack__'s __Environment__:
66
24
 
67
25
  env.merge!(
@@ -123,110 +81,6 @@ If any of these headers are present in the request, the response is considered
123
81
  private and will not be cached _unless_ the response is explicitly marked public
124
82
  (e.g., `Cache-Control: public`).
125
83
 
126
- <a id='machinery'></a>
127
-
128
- Configuration Machinery - Events and Transitions
129
- ------------------------------------------------
130
-
131
- The configuration machinery is built around a series of interceptable events and
132
- transitions controlled by a simple configuration language. The following diagram
133
- shows each state (interceptable event) along with their possible transitions:
134
-
135
- <p class='center'>
136
- <img src='events.png' alt='Events and Transitions Diagram' />
137
- </p>
138
-
139
- Custom logic can be layered onto the `receive`, `hit`, `miss`, `fetch`, `store`,
140
- `deliver`, and `pass` events by passing a block to the `on` method:
141
-
142
- on :fetch do
143
- trace 'fetched %p from backend application', request.url
144
- end
145
-
146
- Here, the `trace` method writes a message to the `rack.errors` stream when a
147
- response is fetched from the backend application. The `request` object is a
148
- [__Rack::Cache::Request__](./api/classes/Rack/Cache/Request) that can be
149
- inspected (and modified) to determine what action should be taken next.
150
-
151
- Event blocks are capable of performing more interesting operations:
152
-
153
- * Transition to a different event or override default caching logic.
154
- * Modify the request, response, cache entry, or Rack environment options.
155
- * Set the `metastore` or `entitystore` options to select a different storage
156
- mechanism / location dynamically.
157
- * Collect statistics or log request/response/cache information.
158
-
159
- When an event is triggered, the blocks associated with the event are executed in
160
- reverse/FILO order (i.e., the block declared last runs first) until a
161
- _transitioning statement_ is encountered. Transitioning statements are suffixed
162
- with a bang character (e.g, `pass!`, `store!`, `error!`) and cause the current
163
- event to halt and the machine to transition to the subsequent event; control is
164
- not returned to the original event. The [default configuration](#default)
165
- includes documentation on available transitions for each event.
166
-
167
- The `next` statement can be used to exit an event block without transitioning
168
- to another event. Subsequent event blocks are executed until a transitioning
169
- statement is encountered:
170
-
171
- on :fetch do
172
- next if response.freshness_information?
173
-
174
- if request.url =~ /\/feed$/
175
- trace 'feed will expire in fifteen minutes'
176
- response.ttl = 15 * 60
177
- end
178
- end
179
-
180
- <a id='import'></a>
181
-
182
- Importing Configuration
183
- -----------------------
184
-
185
- Since caching logic can be layered, it's possible to separate various bits of
186
- cache policy into files for organization and reuse.
187
-
188
- use Rack::Cache do
189
- import 'rack/cache/config/busters'
190
- import 'mycacheconfig'
191
-
192
- # more stuff here
193
- end
194
-
195
- The `busters` and `mycacheconfig` configuration files are normal Ruby source
196
- files (i.e., they have a `.rb` extension) situated on the `$LOAD_PATH` - the
197
- `import` statement works like Ruby's `require` statement but the contents of the
198
- files are evaluated in the context of the configuration machinery, as if
199
- specified directly in the configuration block.
200
-
201
- The `rack/cache/config/busters.rb` file makes a good example. It hooks into the
202
- `fetch` event and adds an impractically long expiration lifetime to any response
203
- that includes a cache busting query string:
204
-
205
- <%= File.read('lib/rack/cache/config/busters.rb').gsub(/^/, ' ') %>
206
-
207
-
208
- <a id='default'></a>
209
-
210
- Default Configuration Machinery
211
- -------------------------------
212
-
213
- The `rack/cache/config/default.rb` file is imported when the __Rack::Cache__
214
- object is instantiated and before any custom configuration code is executed.
215
- It's useful to understand this configuration because it drives the default
216
- transitioning logic.
217
-
218
- <%= File.read('lib/rack/cache/config/default.rb').gsub(/^/, ' ') %>
219
-
220
- <a id='notes'></a>
221
-
222
- Notes
223
- -----
224
-
225
- The configuration language was inspired by [Varnish][var]'s
226
- [VCL configuration language][vcl].
227
-
228
- [var]: http://varnish.projects.linpro.no/
229
- "Varnish HTTP accelerator"
84
+ ### `cache_key`
230
85
 
231
- [vcl]: http://tomayko.com/man/vcl
232
- "VCL(7) -- Varnish Configuration Language Manual Page"
86
+ TODO: Document custom cache keys
data/doc/faq.markdown CHANGED
@@ -10,6 +10,14 @@ General
10
10
  -------
11
11
 
12
12
 
13
+ <a class='hash' id='rails' href='#rails'>#</a>
14
+
15
+ ### Q: Can I use Rack::Cache with Rails?
16
+
17
+ Rack::Cache can be used with Rails 2.3 or above. Documentation and a
18
+ sample application is forthcoming; in the mean time, see
19
+ [this example of using Rack::Cache with Rails 2.3](http://snippets.aktagon.com/snippets/302-How-to-setup-and-use-Rack-Cache-with-Rails-2-3-0-RC-1).
20
+
13
21
  <a class='hash' id='why-not-squid' href='#why-not-squid'>#</a>
14
22
 
15
23
  ### Q: Why Rack::Cache? Why not Squid, Varnish, Perlbol, etc.?
data/doc/index.markdown CHANGED
@@ -7,16 +7,15 @@ for [Rack][]-based applications that produce freshness (`Expires`,
7
7
  * Validation
8
8
  * Vary support
9
9
  * Portable: 100% Ruby / works with any [Rack][]-enabled framework.
10
- * [Configuration language][config] for advanced caching policies.
11
10
  * Disk, memcached, and heap memory [storage backends][storage].
12
11
 
13
- Status
14
- ------
12
+ News
13
+ ----
15
14
 
16
- __Rack::Cache__ is a young and experimental project that is likely to
17
- change substantially and may not be wholly functional, consistent,
18
- fast, or correct. The current focus is on reaching basic compliance
19
- with RFC 2616 and providing good documentation.
15
+ * [How to use Rack::Cache with Rails 2.3](http://snippets.aktagon.com/snippets/302-How-to-setup-and-use-Rack-Cache-with-Rails-2-3-0-RC-1) - it's really easy.
16
+ * [RailsLab's Advanced HTTP Caching Screencast](http://railslab.newrelic.com/2009/02/26/episode-11-advanced-http-caching)
17
+ is a really great review of HTTP caching concepts and shows how to
18
+ use Rack::Cache with Rails.
20
19
 
21
20
  Installation
22
21
  ------------
@@ -52,8 +51,7 @@ caching.
52
51
  More
53
52
  ----
54
53
 
55
- * [Configuration Language Documentation][config] - how to customize cache
56
- policy using the simple event-based configuration system.
54
+ * [Configuration Options][config] - how to set cache options.
57
55
 
58
56
  * [Cache Storage Documentation][storage] - detailed information on the various
59
57
  storage implementations available in __Rack::Cache__ and how to choose the one
@@ -0,0 +1,25 @@
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
+
9
+ on :receive do
10
+ pass! if request.url =~ /favicon/
11
+ end
12
+ end
13
+
14
+ before do
15
+ last_modified $updated_at ||= Time.now
16
+ end
17
+
18
+ get '/' do
19
+ erb :index
20
+ end
21
+
22
+ put '/' do
23
+ $updated_at = nil
24
+ redirect '/'
25
+ end
@@ -0,0 +1,44 @@
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>