rack-cache 1.5.1 → 1.6.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b362a8d1a083164b460b2b6b02c2f8b4d6e5ff6
4
- data.tar.gz: bafe3e19182d804665595bf7e08456cf6c1d390a
3
+ metadata.gz: ad5318e23250e33645116d216dc29c802474689c
4
+ data.tar.gz: 80b52176a3aa9229f4fc4178e3123e973e10001e
5
5
  SHA512:
6
- metadata.gz: 85cf8ff84523a991068679016c81100f681dfeb17df159ba5cc0f2a0d63097dd1045e5de7d457faf91c62dcad6d4f1fdb616020bd1de4c6b31463e4fd8d57c88
7
- data.tar.gz: 433e8a34a0c78241a6e4dc32bd404bb8b7e4323318a2929688d129d06276b3b1f5d01ae44b1e2ad388b6101e9123ef1d377483ac84446f97ed0356ccd923a85b
6
+ metadata.gz: 58e6d9f8cd0cae110dc4fa923d0383973f085fa4e33f416318c7b48783a2d746278ec0e50b98a20dda55d669ef4016c10fe36693d49733f457fa630461cedea8
7
+ data.tar.gz: f30d08c7334ea19d00550d389e98940f62353fd93d15a65c3fd431c93a6c3b0ea23fc7e748bc51bc7646fa33f47c33061a55e03878368367ca743da762eea0a8
data/CHANGES CHANGED
@@ -1,3 +1,13 @@
1
+ ## 1.6.0
2
+
3
+ * Noop backend
4
+ * No longer read responses from cache when we already have them
5
+ * renamed files from entitystore -> entity_store (metastore/cachecontrol/appengine) and added warns for old ones
6
+
7
+ ## 1.5.1
8
+
9
+ * fix key generation for query strings that include encoded equals
10
+
1
11
  ## 1.5.0
2
12
 
3
13
  * only catch StandardError and not Exception
data/README.md CHANGED
@@ -41,9 +41,9 @@ and use as follows:
41
41
  require 'rack/cache'
42
42
 
43
43
  use Rack::Cache,
44
- :metastore => 'file:/var/cache/rack/meta',
45
- :entitystore => 'file:/var/cache/rack/body',
46
- :verbose => true
44
+ metastore: 'file:/var/cache/rack/meta',
45
+ entitystore: 'file:/var/cache/rack/body',
46
+ verbose: true
47
47
 
48
48
  run app
49
49
  ```
@@ -59,9 +59,9 @@ Add this to your `config/environment.rb`:
59
59
 
60
60
  ```Ruby
61
61
  config.middleware.use Rack::Cache,
62
- :verbose => true,
63
- :metastore => 'file:/var/cache/rack/meta',
64
- :entitystore => 'file:/var/cache/rack/body'
62
+ verbose: true,
63
+ metastore: 'file:/var/cache/rack/meta',
64
+ entitystore: 'file:/var/cache/rack/body'
65
65
  ```
66
66
 
67
67
  You should now see `Rack::Cache` listed in the middleware pipeline:
@@ -83,9 +83,28 @@ require 'dalli'
83
83
  require 'rack/cache'
84
84
 
85
85
  use Rack::Cache,
86
- :verbose => true,
87
- :metastore => "memcached://localhost:11211/meta",
88
- :entitystore => "memcached://localhost:11211/body"
86
+ verbose: true,
87
+ metastore: "memcached://localhost:11211/meta",
88
+ entitystore: "memcached://localhost:11211/body"
89
+
90
+ run app
91
+ ```
92
+
93
+ Noop entity store
94
+ -----------------
95
+
96
+ Does not persist response bodies (no disk/memory used).<br/>
97
+ Responses from the cache will have an empty body.<br/>
98
+ Clients must ignore these empty cached response (check for X-Rack-Cache response header).<br/>
99
+ Atm cannot handle streamed responses, patch needed.
100
+
101
+ ```Ruby
102
+ require 'rack/cache'
103
+
104
+ use Rack::Cache,
105
+ verbose: true,
106
+ metastore: <any backend>
107
+ entitystore: "noop:/"
89
108
 
90
109
  run app
91
110
  ```
@@ -31,7 +31,7 @@ module Rack::Cache
31
31
  autoload :Response, 'rack/cache/response'
32
32
  autoload :Context, 'rack/cache/context'
33
33
  autoload :Storage, 'rack/cache/storage'
34
- autoload :CacheControl, 'rack/cache/cachecontrol'
34
+ autoload :CacheControl, 'rack/cache/cache_control'
35
35
 
36
36
  # Create a new Rack::Cache middleware component that fetches resources from
37
37
  # the specified backend application. The +options+ Hash can be used to
@@ -0,0 +1,48 @@
1
+ require 'base64'
2
+
3
+ module Rack::Cache::AppEngine
4
+ module MC
5
+ require 'java'
6
+
7
+ import com.google.appengine.api.memcache.Expiration;
8
+ import com.google.appengine.api.memcache.MemcacheService;
9
+ import com.google.appengine.api.memcache.MemcacheServiceFactory;
10
+ import com.google.appengine.api.memcache.Stats;
11
+
12
+ Service = MemcacheServiceFactory.getMemcacheService
13
+ end unless defined?(Rack::Cache::AppEngine::MC)
14
+
15
+ class MemCache
16
+ def initialize(options = {})
17
+ @cache = MC::Service
18
+ @cache.namespace = options[:namespace] if options[:namespace]
19
+ end
20
+
21
+ def contains?(key)
22
+ MC::Service.contains(key)
23
+ end
24
+
25
+ def get(key)
26
+ value = MC::Service.get(key)
27
+ Marshal.load(Base64.decode64(value)) if value
28
+ end
29
+
30
+ def put(key, value, ttl = nil)
31
+ expiration = ttl ? MC::Expiration.byDeltaSeconds(ttl) : nil
32
+ value = Base64.encode64(Marshal.dump(value)).gsub(/\n/, '')
33
+ MC::Service.put(key, value, expiration)
34
+ end
35
+
36
+ def namespace
37
+ MC::Service.getNamespace
38
+ end
39
+
40
+ def namespace=(value)
41
+ MC::Service.setNamespace(value.to_s)
42
+ end
43
+
44
+ def delete(key)
45
+ MC::Service.delete(key)
46
+ end
47
+ end
48
+ end
@@ -1,52 +1,2 @@
1
- require 'base64'
2
-
3
- module Rack::Cache::AppEngine
4
-
5
- module MC
6
- require 'java'
7
-
8
- import com.google.appengine.api.memcache.Expiration;
9
- import com.google.appengine.api.memcache.MemcacheService;
10
- import com.google.appengine.api.memcache.MemcacheServiceFactory;
11
- import com.google.appengine.api.memcache.Stats;
12
-
13
- Service = MemcacheServiceFactory.getMemcacheService
14
- end unless defined?(Rack::Cache::AppEngine::MC)
15
-
16
- class MemCache
17
-
18
- def initialize(options = {})
19
- @cache = MC::Service
20
- @cache.namespace = options[:namespace] if options[:namespace]
21
- end
22
-
23
- def contains?(key)
24
- MC::Service.contains(key)
25
- end
26
-
27
- def get(key)
28
- value = MC::Service.get(key)
29
- Marshal.load(Base64.decode64(value)) if value
30
- end
31
-
32
- def put(key, value, ttl = nil)
33
- expiration = ttl ? MC::Expiration.byDeltaSeconds(ttl) : nil
34
- value = Base64.encode64(Marshal.dump(value)).gsub(/\n/, '')
35
- MC::Service.put(key, value, expiration)
36
- end
37
-
38
- def namespace
39
- MC::Service.getNamespace
40
- end
41
-
42
- def namespace=(value)
43
- MC::Service.setNamespace(value.to_s)
44
- end
45
-
46
- def delete(key)
47
- MC::Service.delete(key)
48
- end
49
-
50
- end
51
-
52
- end
1
+ warn "use require 'rack/cache/app_engine'"
2
+ require 'rack/cache/app_engine'
@@ -0,0 +1,209 @@
1
+ module Rack
2
+ module Cache
3
+
4
+ # Parses a Cache-Control header and exposes the directives as a Hash.
5
+ # Directives that do not have values are set to +true+.
6
+ class CacheControl < Hash
7
+ def initialize(value=nil)
8
+ parse(value)
9
+ end
10
+
11
+ # Indicates that the response MAY be cached by any cache, even if it
12
+ # would normally be non-cacheable or cacheable only within a non-
13
+ # shared cache.
14
+ #
15
+ # A response may be considered public without this directive if the
16
+ # private directive is not set and the request does not include an
17
+ # Authorization header.
18
+ def public?
19
+ self['public']
20
+ end
21
+
22
+ # Indicates that all or part of the response message is intended for
23
+ # a single user and MUST NOT be cached by a shared cache. This
24
+ # allows an origin server to state that the specified parts of the
25
+ # response are intended for only one user and are not a valid
26
+ # response for requests by other users. A private (non-shared) cache
27
+ # MAY cache the response.
28
+ #
29
+ # Note: This usage of the word private only controls where the
30
+ # response may be cached, and cannot ensure the privacy of the
31
+ # message content.
32
+ def private?
33
+ self['private']
34
+ end
35
+
36
+ # When set in a response, a cache MUST NOT use the response to satisfy a
37
+ # subsequent request without successful revalidation with the origin
38
+ # server. This allows an origin server to prevent caching even by caches
39
+ # that have been configured to return stale responses to client requests.
40
+ #
41
+ # Note that this does not necessary imply that the response may not be
42
+ # stored by the cache, only that the cache cannot serve it without first
43
+ # making a conditional GET request with the origin server.
44
+ #
45
+ # When set in a request, the server MUST NOT use a cached copy for its
46
+ # response. This has quite different semantics compared to the no-cache
47
+ # directive on responses. When the client specifies no-cache, it causes
48
+ # an end-to-end reload, forcing each cache to update their cached copies.
49
+ def no_cache?
50
+ self['no-cache']
51
+ end
52
+
53
+ # Indicates that the response MUST NOT be stored under any circumstances.
54
+ #
55
+ # The purpose of the no-store directive is to prevent the
56
+ # inadvertent release or retention of sensitive information (for
57
+ # example, on backup tapes). The no-store directive applies to the
58
+ # entire message, and MAY be sent either in a response or in a
59
+ # request. If sent in a request, a cache MUST NOT store any part of
60
+ # either this request or any response to it. If sent in a response,
61
+ # a cache MUST NOT store any part of either this response or the
62
+ # request that elicited it. This directive applies to both non-
63
+ # shared and shared caches. "MUST NOT store" in this context means
64
+ # that the cache MUST NOT intentionally store the information in
65
+ # non-volatile storage, and MUST make a best-effort attempt to
66
+ # remove the information from volatile storage as promptly as
67
+ # possible after forwarding it.
68
+ #
69
+ # The purpose of this directive is to meet the stated requirements
70
+ # of certain users and service authors who are concerned about
71
+ # accidental releases of information via unanticipated accesses to
72
+ # cache data structures. While the use of this directive might
73
+ # improve privacy in some cases, we caution that it is NOT in any
74
+ # way a reliable or sufficient mechanism for ensuring privacy. In
75
+ # particular, malicious or compromised caches might not recognize or
76
+ # obey this directive, and communications networks might be
77
+ # vulnerable to eavesdropping.
78
+ def no_store?
79
+ self['no-store']
80
+ end
81
+
82
+ # The expiration time of an entity MAY be specified by the origin
83
+ # server using the Expires header (see section 14.21). Alternatively,
84
+ # it MAY be specified using the max-age directive in a response. When
85
+ # the max-age cache-control directive is present in a cached response,
86
+ # the response is stale if its current age is greater than the age
87
+ # value given (in seconds) at the time of a new request for that
88
+ # resource. The max-age directive on a response implies that the
89
+ # response is cacheable (i.e., "public") unless some other, more
90
+ # restrictive cache directive is also present.
91
+ #
92
+ # If a response includes both an Expires header and a max-age
93
+ # directive, the max-age directive overrides the Expires header, even
94
+ # if the Expires header is more restrictive. This rule allows an origin
95
+ # server to provide, for a given response, a longer expiration time to
96
+ # an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. This might be
97
+ # useful if certain HTTP/1.0 caches improperly calculate ages or
98
+ # expiration times, perhaps due to desynchronized clocks.
99
+ #
100
+ # Many HTTP/1.0 cache implementations will treat an Expires value that
101
+ # is less than or equal to the response Date value as being equivalent
102
+ # to the Cache-Control response directive "no-cache". If an HTTP/1.1
103
+ # cache receives such a response, and the response does not include a
104
+ # Cache-Control header field, it SHOULD consider the response to be
105
+ # non-cacheable in order to retain compatibility with HTTP/1.0 servers.
106
+ #
107
+ # When the max-age directive is included in the request, it indicates
108
+ # that the client is willing to accept a response whose age is no
109
+ # greater than the specified time in seconds.
110
+ def max_age
111
+ self['max-age'].to_i if key?('max-age')
112
+ end
113
+
114
+ # If a response includes an s-maxage directive, then for a shared
115
+ # cache (but not for a private cache), the maximum age specified by
116
+ # this directive overrides the maximum age specified by either the
117
+ # max-age directive or the Expires header. The s-maxage directive
118
+ # also implies the semantics of the proxy-revalidate directive. i.e.,
119
+ # that the shared cache must not use the entry after it becomes stale
120
+ # to respond to a subsequent request without first revalidating it with
121
+ # the origin server. The s-maxage directive is always ignored by a
122
+ # private cache.
123
+ def shared_max_age
124
+ self['s-maxage'].to_i if key?('s-maxage')
125
+ end
126
+ alias_method :s_maxage, :shared_max_age
127
+
128
+ # If a response includes a r-maxage directive, then for a reverse cache
129
+ # (but not for a private or proxy cache), the maximum age specified by
130
+ # this directive overrides the maximum age specified by either the max-age
131
+ # directive, the s-maxage directive, or the Expires header. The r-maxage
132
+ # directive also implies the semantics of the proxy-revalidate directive.
133
+ # i.e., that the reverse cache must not use the entry after it becomes
134
+ # stale to respond to a subsequent request without first revalidating it
135
+ # with the origin server. The r-maxage directive is always ignored by
136
+ # private and proxy caches.
137
+ def reverse_max_age
138
+ self['r-maxage'].to_i if key?('r-maxage')
139
+ end
140
+ alias_method :r_maxage, :reverse_max_age
141
+
142
+ # Because a cache MAY be configured to ignore a server's specified
143
+ # expiration time, and because a client request MAY include a max-
144
+ # stale directive (which has a similar effect), the protocol also
145
+ # includes a mechanism for the origin server to require revalidation
146
+ # of a cache entry on any subsequent use. When the must-revalidate
147
+ # directive is present in a response received by a cache, that cache
148
+ # MUST NOT use the entry after it becomes stale to respond to a
149
+ # subsequent request without first revalidating it with the origin
150
+ # server. (I.e., the cache MUST do an end-to-end revalidation every
151
+ # time, if, based solely on the origin server's Expires or max-age
152
+ # value, the cached response is stale.)
153
+ #
154
+ # The must-revalidate directive is necessary to support reliable
155
+ # operation for certain protocol features. In all circumstances an
156
+ # HTTP/1.1 cache MUST obey the must-revalidate directive; in
157
+ # particular, if the cache cannot reach the origin server for any
158
+ # reason, it MUST generate a 504 (Gateway Timeout) response.
159
+ #
160
+ # Servers SHOULD send the must-revalidate directive if and only if
161
+ # failure to revalidate a request on the entity could result in
162
+ # incorrect operation, such as a silently unexecuted financial
163
+ # transaction. Recipients MUST NOT take any automated action that
164
+ # violates this directive, and MUST NOT automatically provide an
165
+ # unvalidated copy of the entity if revalidation fails.
166
+ def must_revalidate?
167
+ self['must-revalidate']
168
+ end
169
+
170
+ # The proxy-revalidate directive has the same meaning as the must-
171
+ # revalidate directive, except that it does not apply to non-shared
172
+ # user agent caches. It can be used on a response to an
173
+ # authenticated request to permit the user's cache to store and
174
+ # later return the response without needing to revalidate it (since
175
+ # it has already been authenticated once by that user), while still
176
+ # requiring proxies that service many users to revalidate each time
177
+ # (in order to make sure that each user has been authenticated).
178
+ # Note that such authenticated responses also need the public cache
179
+ # control directive in order to allow them to be cached at all.
180
+ def proxy_revalidate?
181
+ self['proxy-revalidate']
182
+ end
183
+
184
+ def to_s
185
+ bools, vals = [], []
186
+ each do |key,value|
187
+ if value == true
188
+ bools << key
189
+ elsif value
190
+ vals << "#{key}=#{value}"
191
+ end
192
+ end
193
+ (bools.sort + vals.sort).join(', ')
194
+ end
195
+
196
+ private
197
+
198
+ def parse(value)
199
+ return if value.nil? || value.empty?
200
+ value.delete(' ').split(',').each do |part|
201
+ next if part.empty?
202
+ name, value = part.split('=', 2)
203
+ self[name.downcase] = (value || true) unless name.empty?
204
+ end
205
+ self
206
+ end
207
+ end
208
+ end
209
+ end
@@ -1,208 +1,2 @@
1
- module Rack
2
- module Cache
3
-
4
- # Parses a Cache-Control header and exposes the directives as a Hash.
5
- # Directives that do not have values are set to +true+.
6
- class CacheControl < Hash
7
- def initialize(value=nil)
8
- parse(value)
9
- end
10
-
11
- # Indicates that the response MAY be cached by any cache, even if it
12
- # would normally be non-cacheable or cacheable only within a non-
13
- # shared cache.
14
- #
15
- # A response may be considered public without this directive if the
16
- # private directive is not set and the request does not include an
17
- # Authorization header.
18
- def public?
19
- self['public']
20
- end
21
-
22
- # Indicates that all or part of the response message is intended for
23
- # a single user and MUST NOT be cached by a shared cache. This
24
- # allows an origin server to state that the specified parts of the
25
- # response are intended for only one user and are not a valid
26
- # response for requests by other users. A private (non-shared) cache
27
- # MAY cache the response.
28
- #
29
- # Note: This usage of the word private only controls where the
30
- # response may be cached, and cannot ensure the privacy of the
31
- # message content.
32
- def private?
33
- self['private']
34
- end
35
-
36
- # When set in a response, a cache MUST NOT use the response to satisfy a
37
- # subsequent request without successful revalidation with the origin
38
- # server. This allows an origin server to prevent caching even by caches
39
- # that have been configured to return stale responses to client requests.
40
- #
41
- # Note that this does not necessary imply that the response may not be
42
- # stored by the cache, only that the cache cannot serve it without first
43
- # making a conditional GET request with the origin server.
44
- #
45
- # When set in a request, the server MUST NOT use a cached copy for its
46
- # response. This has quite different semantics compared to the no-cache
47
- # directive on responses. When the client specifies no-cache, it causes
48
- # an end-to-end reload, forcing each cache to update their cached copies.
49
- def no_cache?
50
- self['no-cache']
51
- end
52
-
53
- # Indicates that the response MUST NOT be stored under any circumstances.
54
- #
55
- # The purpose of the no-store directive is to prevent the
56
- # inadvertent release or retention of sensitive information (for
57
- # example, on backup tapes). The no-store directive applies to the
58
- # entire message, and MAY be sent either in a response or in a
59
- # request. If sent in a request, a cache MUST NOT store any part of
60
- # either this request or any response to it. If sent in a response,
61
- # a cache MUST NOT store any part of either this response or the
62
- # request that elicited it. This directive applies to both non-
63
- # shared and shared caches. "MUST NOT store" in this context means
64
- # that the cache MUST NOT intentionally store the information in
65
- # non-volatile storage, and MUST make a best-effort attempt to
66
- # remove the information from volatile storage as promptly as
67
- # possible after forwarding it.
68
- #
69
- # The purpose of this directive is to meet the stated requirements
70
- # of certain users and service authors who are concerned about
71
- # accidental releases of information via unanticipated accesses to
72
- # cache data structures. While the use of this directive might
73
- # improve privacy in some cases, we caution that it is NOT in any
74
- # way a reliable or sufficient mechanism for ensuring privacy. In
75
- # particular, malicious or compromised caches might not recognize or
76
- # obey this directive, and communications networks might be
77
- # vulnerable to eavesdropping.
78
- def no_store?
79
- self['no-store']
80
- end
81
-
82
- # The expiration time of an entity MAY be specified by the origin
83
- # server using the Expires header (see section 14.21). Alternatively,
84
- # it MAY be specified using the max-age directive in a response. When
85
- # the max-age cache-control directive is present in a cached response,
86
- # the response is stale if its current age is greater than the age
87
- # value given (in seconds) at the time of a new request for that
88
- # resource. The max-age directive on a response implies that the
89
- # response is cacheable (i.e., "public") unless some other, more
90
- # restrictive cache directive is also present.
91
- #
92
- # If a response includes both an Expires header and a max-age
93
- # directive, the max-age directive overrides the Expires header, even
94
- # if the Expires header is more restrictive. This rule allows an origin
95
- # server to provide, for a given response, a longer expiration time to
96
- # an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. This might be
97
- # useful if certain HTTP/1.0 caches improperly calculate ages or
98
- # expiration times, perhaps due to desynchronized clocks.
99
- #
100
- # Many HTTP/1.0 cache implementations will treat an Expires value that
101
- # is less than or equal to the response Date value as being equivalent
102
- # to the Cache-Control response directive "no-cache". If an HTTP/1.1
103
- # cache receives such a response, and the response does not include a
104
- # Cache-Control header field, it SHOULD consider the response to be
105
- # non-cacheable in order to retain compatibility with HTTP/1.0 servers.
106
- #
107
- # When the max-age directive is included in the request, it indicates
108
- # that the client is willing to accept a response whose age is no
109
- # greater than the specified time in seconds.
110
- def max_age
111
- self['max-age'].to_i if key?('max-age')
112
- end
113
-
114
- # If a response includes an s-maxage directive, then for a shared
115
- # cache (but not for a private cache), the maximum age specified by
116
- # this directive overrides the maximum age specified by either the
117
- # max-age directive or the Expires header. The s-maxage directive
118
- # also implies the semantics of the proxy-revalidate directive. i.e.,
119
- # that the shared cache must not use the entry after it becomes stale
120
- # to respond to a subsequent request without first revalidating it with
121
- # the origin server. The s-maxage directive is always ignored by a
122
- # private cache.
123
- def shared_max_age
124
- self['s-maxage'].to_i if key?('s-maxage')
125
- end
126
- alias_method :s_maxage, :shared_max_age
127
-
128
- # If a response includes a r-maxage directive, then for a reverse cache
129
- # (but not for a private or proxy cache), the maximum age specified by
130
- # this directive overrides the maximum age specified by either the max-age
131
- # directive, the s-maxage directive, or the Expires header. The r-maxage
132
- # directive also implies the semantics of the proxy-revalidate directive.
133
- # i.e., that the reverse cache must not use the entry after it becomes
134
- # stale to respond to a subsequent request without first revalidating it
135
- # with the origin server. The r-maxage directive is always ignored by
136
- # private and proxy caches.
137
- def reverse_max_age
138
- self['r-maxage'].to_i if key?('r-maxage')
139
- end
140
- alias_method :r_maxage, :reverse_max_age
141
-
142
- # Because a cache MAY be configured to ignore a server's specified
143
- # expiration time, and because a client request MAY include a max-
144
- # stale directive (which has a similar effect), the protocol also
145
- # includes a mechanism for the origin server to require revalidation
146
- # of a cache entry on any subsequent use. When the must-revalidate
147
- # directive is present in a response received by a cache, that cache
148
- # MUST NOT use the entry after it becomes stale to respond to a
149
- # subsequent request without first revalidating it with the origin
150
- # server. (I.e., the cache MUST do an end-to-end revalidation every
151
- # time, if, based solely on the origin server's Expires or max-age
152
- # value, the cached response is stale.)
153
- #
154
- # The must-revalidate directive is necessary to support reliable
155
- # operation for certain protocol features. In all circumstances an
156
- # HTTP/1.1 cache MUST obey the must-revalidate directive; in
157
- # particular, if the cache cannot reach the origin server for any
158
- # reason, it MUST generate a 504 (Gateway Timeout) response.
159
- #
160
- # Servers SHOULD send the must-revalidate directive if and only if
161
- # failure to revalidate a request on the entity could result in
162
- # incorrect operation, such as a silently unexecuted financial
163
- # transaction. Recipients MUST NOT take any automated action that
164
- # violates this directive, and MUST NOT automatically provide an
165
- # unvalidated copy of the entity if revalidation fails.
166
- def must_revalidate?
167
- self['must-revalidate']
168
- end
169
-
170
- # The proxy-revalidate directive has the same meaning as the must-
171
- # revalidate directive, except that it does not apply to non-shared
172
- # user agent caches. It can be used on a response to an
173
- # authenticated request to permit the user's cache to store and
174
- # later return the response without needing to revalidate it (since
175
- # it has already been authenticated once by that user), while still
176
- # requiring proxies that service many users to revalidate each time
177
- # (in order to make sure that each user has been authenticated).
178
- # Note that such authenticated responses also need the public cache
179
- # control directive in order to allow them to be cached at all.
180
- def proxy_revalidate?
181
- self['proxy-revalidate']
182
- end
183
-
184
- def to_s
185
- bools, vals = [], []
186
- each do |key,value|
187
- if value == true
188
- bools << key
189
- elsif value
190
- vals << "#{key}=#{value}"
191
- end
192
- end
193
- (bools.sort + vals.sort).join(', ')
194
- end
195
-
196
- private
197
- def parse(value)
198
- return if value.nil? || value.empty?
199
- value.delete(' ').split(',').each do |part|
200
- next if part.empty?
201
- name, value = part.split('=', 2)
202
- self[name.downcase] = (value || true) unless name.empty?
203
- end
204
- self
205
- end
206
- end
207
- end
208
- end
1
+ warn "use require 'rack/cache/cache_control'"
2
+ require 'rack/cache/cache_control'