rack-cache 1.5.1 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
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'