rack-cache 1.13.0 → 1.14.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.
- checksums.yaml +4 -4
- data/CHANGES +4 -0
- data/README.md +9 -9
- data/lib/rack/cache/cache_control.rb +12 -12
- data/lib/rack/cache/context.rb +9 -9
- data/lib/rack/cache/entity_store.rb +1 -1
- data/lib/rack/cache/meta_store.rb +9 -10
- data/lib/rack/cache/options.rb +6 -6
- data/lib/rack/cache/request.rb +2 -2
- data/lib/rack/cache/response.rb +49 -41
- data/lib/rack/cache/version.rb +5 -0
- data/lib/rack/cache.rb +2 -2
- metadata +38 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b0736c08c25e902a2bd7a9348343f9c85a75a0463fea40f62939c6d8119e76e8
|
|
4
|
+
data.tar.gz: 28d088e61248351bf733db042795fdcd6aef588e6b31f1ab618d6cb76f56c3b4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9be0a8a33da6bd4ac271e06bee21616c902bd484da18d21a809cdb75c27f876bb64166edcc084ef387f45b5307a91814b9595384763bbcebd55bfbdc8582f96d
|
|
7
|
+
data.tar.gz: e9bb795f263903be398a9e2b9ee7ea3e44352bb0a2786a90bd699f2078da237add5fa76a1ec3ca79140b776aa87f969ffe126b95664b974279b6c4089ff28200
|
data/CHANGES
CHANGED
data/README.md
CHANGED
|
@@ -2,21 +2,21 @@ Rack::Cache
|
|
|
2
2
|
===========
|
|
3
3
|
|
|
4
4
|
Rack::Cache is suitable as a quick drop-in component to enable HTTP caching for
|
|
5
|
-
Rack-based applications that produce freshness (
|
|
6
|
-
validation (
|
|
5
|
+
Rack-based applications that produce freshness (`expires`, `cache-control`)
|
|
6
|
+
and/or validation (`last-modified`, `etag`) information:
|
|
7
7
|
|
|
8
8
|
* Standards-based (RFC 2616)
|
|
9
9
|
* Freshness/expiration based caching
|
|
10
|
-
* Validation (
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
and proxy-revalidate
|
|
10
|
+
* Validation (`if-modified-since` / `if-none-match`)
|
|
11
|
+
* `vary` support
|
|
12
|
+
* `cache-control` `public`, `private`, `max-age`, `s-maxage`, `must-revalidate`,
|
|
13
|
+
and `proxy-revalidate`.
|
|
14
14
|
* Portable: 100% Ruby / works with any Rack-enabled framework
|
|
15
15
|
* Disk, memcached, and heap memory storage backends
|
|
16
16
|
|
|
17
17
|
For more information about Rack::Cache features and usage, see:
|
|
18
18
|
|
|
19
|
-
https://
|
|
19
|
+
https://rack.github.io/rack-cache/
|
|
20
20
|
|
|
21
21
|
Rack::Cache is not overly optimized for performance. The main goal of the
|
|
22
22
|
project is to provide a portable, easy-to-configure, and standards-based
|
|
@@ -95,7 +95,7 @@ Noop entity store
|
|
|
95
95
|
|
|
96
96
|
Does not persist response bodies (no disk/memory used).<br/>
|
|
97
97
|
Responses from the cache will have an empty body.<br/>
|
|
98
|
-
Clients must ignore these empty cached response (check for
|
|
98
|
+
Clients must ignore these empty cached response (check for `x-rack-cache` response header).<br/>
|
|
99
99
|
Atm cannot handle streamed responses, patch needed.
|
|
100
100
|
|
|
101
101
|
```Ruby
|
|
@@ -123,4 +123,4 @@ Rack::Cache::Key.query_string_ignore = proc { |k, v| k =~ /^(trk|utm)_/ }
|
|
|
123
123
|
```
|
|
124
124
|
|
|
125
125
|
License: MIT<br/>
|
|
126
|
-
[](https://github.com/rack/rack-cache/actions/workflows/development.yml)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Rack
|
|
2
2
|
module Cache
|
|
3
3
|
|
|
4
|
-
# Parses a
|
|
4
|
+
# Parses a cache-control header and exposes the directives as a Hash.
|
|
5
5
|
# Directives that do not have values are set to +true+.
|
|
6
6
|
class CacheControl < Hash
|
|
7
7
|
def initialize(value=nil)
|
|
@@ -80,7 +80,7 @@ module Rack
|
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
# The expiration time of an entity MAY be specified by the origin
|
|
83
|
-
# server using the
|
|
83
|
+
# server using the expires header (see section 14.21). Alternatively,
|
|
84
84
|
# it MAY be specified using the max-age directive in a response. When
|
|
85
85
|
# the max-age cache-control directive is present in a cached response,
|
|
86
86
|
# the response is stale if its current age is greater than the age
|
|
@@ -89,19 +89,19 @@ module Rack
|
|
|
89
89
|
# response is cacheable (i.e., "public") unless some other, more
|
|
90
90
|
# restrictive cache directive is also present.
|
|
91
91
|
#
|
|
92
|
-
# If a response includes both an
|
|
93
|
-
# directive, the max-age directive overrides the
|
|
94
|
-
# if the
|
|
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
95
|
# server to provide, for a given response, a longer expiration time to
|
|
96
96
|
# an HTTP/1.1 (or later) cache than to an HTTP/1.0 cache. This might be
|
|
97
97
|
# useful if certain HTTP/1.0 caches improperly calculate ages or
|
|
98
98
|
# expiration times, perhaps due to desynchronized clocks.
|
|
99
99
|
#
|
|
100
|
-
# Many HTTP/1.0 cache implementations will treat an
|
|
100
|
+
# Many HTTP/1.0 cache implementations will treat an expires value that
|
|
101
101
|
# is less than or equal to the response Date value as being equivalent
|
|
102
|
-
# to the
|
|
102
|
+
# to the cache-control response directive "no-cache". If an HTTP/1.1
|
|
103
103
|
# cache receives such a response, and the response does not include a
|
|
104
|
-
#
|
|
104
|
+
# cache-control header field, it SHOULD consider the response to be
|
|
105
105
|
# non-cacheable in order to retain compatibility with HTTP/1.0 servers.
|
|
106
106
|
#
|
|
107
107
|
# When the max-age directive is included in the request, it indicates
|
|
@@ -114,7 +114,7 @@ module Rack
|
|
|
114
114
|
# If a response includes an s-maxage directive, then for a shared
|
|
115
115
|
# cache (but not for a private cache), the maximum age specified by
|
|
116
116
|
# this directive overrides the maximum age specified by either the
|
|
117
|
-
# max-age directive or the
|
|
117
|
+
# max-age directive or the expires header. The s-maxage directive
|
|
118
118
|
# also implies the semantics of the proxy-revalidate directive. i.e.,
|
|
119
119
|
# that the shared cache must not use the entry after it becomes stale
|
|
120
120
|
# to respond to a subsequent request without first revalidating it with
|
|
@@ -128,7 +128,7 @@ module Rack
|
|
|
128
128
|
# If a response includes a r-maxage directive, then for a reverse cache
|
|
129
129
|
# (but not for a private or proxy cache), the maximum age specified by
|
|
130
130
|
# this directive overrides the maximum age specified by either the max-age
|
|
131
|
-
# directive, the s-maxage directive, or the
|
|
131
|
+
# directive, the s-maxage directive, or the expires header. The r-maxage
|
|
132
132
|
# directive also implies the semantics of the proxy-revalidate directive.
|
|
133
133
|
# i.e., that the reverse cache must not use the entry after it becomes
|
|
134
134
|
# stale to respond to a subsequent request without first revalidating it
|
|
@@ -148,7 +148,7 @@ module Rack
|
|
|
148
148
|
# MUST NOT use the entry after it becomes stale to respond to a
|
|
149
149
|
# subsequent request without first revalidating it with the origin
|
|
150
150
|
# server. (I.e., the cache MUST do an end-to-end revalidation every
|
|
151
|
-
# time, if, based solely on the origin server's
|
|
151
|
+
# time, if, based solely on the origin server's expires or max-age
|
|
152
152
|
# value, the cached response is stale.)
|
|
153
153
|
#
|
|
154
154
|
# The must-revalidate directive is necessary to support reliable
|
|
@@ -196,7 +196,7 @@ module Rack
|
|
|
196
196
|
private
|
|
197
197
|
|
|
198
198
|
def parse(value)
|
|
199
|
-
return
|
|
199
|
+
return if value.nil? || value.empty?
|
|
200
200
|
value.delete(' ').split(',').each do |part|
|
|
201
201
|
next if part.empty?
|
|
202
202
|
name, value = part.split('=', 2)
|
data/lib/rack/cache/context.rb
CHANGED
|
@@ -76,9 +76,9 @@ module Rack::Cache
|
|
|
76
76
|
end
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
# log trace and set
|
|
79
|
+
# log trace and set x-rack-cache tracing header
|
|
80
80
|
trace = @trace.join(', ')
|
|
81
|
-
response.headers['
|
|
81
|
+
response.headers['x-rack-cache'] = trace
|
|
82
82
|
|
|
83
83
|
# write log message to rack.errors
|
|
84
84
|
if verbose?
|
|
@@ -113,7 +113,7 @@ module Rack::Cache
|
|
|
113
113
|
@private_header_keys.any? { |key| @env.key?(key) }
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
-
# Determine if the #response validators (
|
|
116
|
+
# Determine if the #response validators (etag, last-modified) matches
|
|
117
117
|
# a conditional value specified in #request.
|
|
118
118
|
def not_modified?(response)
|
|
119
119
|
last_modified = @request.env['HTTP_IF_MODIFIED_SINCE']
|
|
@@ -181,7 +181,7 @@ module Rack::Cache
|
|
|
181
181
|
if entry
|
|
182
182
|
if fresh_enough?(entry)
|
|
183
183
|
record :fresh
|
|
184
|
-
entry.headers['
|
|
184
|
+
entry.headers['age'] = entry.age.to_s
|
|
185
185
|
entry
|
|
186
186
|
else
|
|
187
187
|
record :stale
|
|
@@ -204,7 +204,7 @@ module Rack::Cache
|
|
|
204
204
|
rescue => e
|
|
205
205
|
record :connnection_failed
|
|
206
206
|
age = entry.age.to_s
|
|
207
|
-
entry.headers['
|
|
207
|
+
entry.headers['age'] = age
|
|
208
208
|
record "Fail-over to stale cache data with age #{age} due to #{e.class.name}: #{e}"
|
|
209
209
|
entry
|
|
210
210
|
end
|
|
@@ -232,12 +232,12 @@ module Rack::Cache
|
|
|
232
232
|
record :valid
|
|
233
233
|
|
|
234
234
|
# Check if the response validated which is not cached here
|
|
235
|
-
etag = response.headers['
|
|
235
|
+
etag = response.headers['etag']
|
|
236
236
|
return response if etag && request_etags.include?(etag) && !cached_etags.include?(etag)
|
|
237
237
|
|
|
238
238
|
entry = entry.dup
|
|
239
|
-
entry.headers.delete('
|
|
240
|
-
%w[Date
|
|
239
|
+
entry.headers.delete('date')
|
|
240
|
+
%w[Date expires cache-control etag last-modified].each do |name|
|
|
241
241
|
next unless value = response.headers[name]
|
|
242
242
|
entry.headers[name] = value
|
|
243
243
|
end
|
|
@@ -287,7 +287,7 @@ module Rack::Cache
|
|
|
287
287
|
def store(response)
|
|
288
288
|
strip_ignore_headers(response)
|
|
289
289
|
metastore.store(@request, response, entitystore)
|
|
290
|
-
response.headers['
|
|
290
|
+
response.headers['age'] = response.age.to_s
|
|
291
291
|
rescue => e
|
|
292
292
|
log_error(e)
|
|
293
293
|
nil
|
|
@@ -341,7 +341,7 @@ module Rack::Cache
|
|
|
341
341
|
# Set `entitystore` to 'noop:/'.
|
|
342
342
|
# Does not persist response bodies (no disk/memory used).
|
|
343
343
|
# Responses from the cache will have an empty body.
|
|
344
|
-
# Clients must ignore these empty cached response (check for
|
|
344
|
+
# Clients must ignore these empty cached response (check for x-rack-cache response header).
|
|
345
345
|
# Atm cannot handle streamed responses, patch needed.
|
|
346
346
|
#
|
|
347
347
|
class Noop < EntityStore
|
|
@@ -34,11 +34,11 @@ module Rack::Cache
|
|
|
34
34
|
|
|
35
35
|
# find a cached entry that matches the request.
|
|
36
36
|
env = request.env
|
|
37
|
-
match = entries.detect{ |req,res| requests_match?((res['
|
|
37
|
+
match = entries.detect{ |req,res| requests_match?((res['vary'] || res['vary']), env, req) }
|
|
38
38
|
return nil if match.nil?
|
|
39
39
|
|
|
40
40
|
_, res = match
|
|
41
|
-
if body = entity_store.open(res['
|
|
41
|
+
if body = entity_store.open(res['x-content-digest'])
|
|
42
42
|
restore_response(res, body)
|
|
43
43
|
else
|
|
44
44
|
# the metastore referenced an entity that doesn't exist in
|
|
@@ -64,14 +64,14 @@ module Rack::Cache
|
|
|
64
64
|
|
|
65
65
|
# write the response body to the entity store if this is the
|
|
66
66
|
# original response.
|
|
67
|
-
if response.headers['
|
|
67
|
+
if response.headers['x-content-digest'].nil?
|
|
68
68
|
if request.env['rack-cache.use_native_ttl'] && response.fresh?
|
|
69
69
|
digest, size = entity_store.write(response.body, response.ttl)
|
|
70
70
|
else
|
|
71
71
|
digest, size = entity_store.write(response.body)
|
|
72
72
|
end
|
|
73
|
-
response.headers['
|
|
74
|
-
response.headers['
|
|
73
|
+
response.headers['x-content-digest'] = digest
|
|
74
|
+
response.headers['content-length'] = size.to_s unless response.headers['Transfer-Encoding']
|
|
75
75
|
|
|
76
76
|
# If the entitystore backend is a Noop, do not try to read the body from the backend, it always returns an empty array
|
|
77
77
|
unless entity_store.is_a? Rack::Cache::EntityStore::Noop
|
|
@@ -91,12 +91,11 @@ module Rack::Cache
|
|
|
91
91
|
vary = response.vary
|
|
92
92
|
entries =
|
|
93
93
|
read(key).reject do |env, res|
|
|
94
|
-
(vary == (res['
|
|
94
|
+
(vary == (res['vary'])) &&
|
|
95
95
|
requests_match?(vary, env, stored_env)
|
|
96
96
|
end
|
|
97
97
|
|
|
98
98
|
headers = persist_response(response)
|
|
99
|
-
headers.delete('Age')
|
|
100
99
|
headers.delete('age')
|
|
101
100
|
|
|
102
101
|
entries.unshift [stored_env, headers]
|
|
@@ -146,13 +145,13 @@ module Rack::Cache
|
|
|
146
145
|
# Converts a stored response hash into a Response object. The caller
|
|
147
146
|
# is responsible for loading and passing the body if needed.
|
|
148
147
|
def restore_response(hash, body=[])
|
|
149
|
-
status = hash.delete('
|
|
148
|
+
status = hash.delete('x-status').to_i
|
|
150
149
|
Rack::Cache::Response.new(status, hash, body)
|
|
151
150
|
end
|
|
152
151
|
|
|
153
152
|
def persist_response(response)
|
|
154
|
-
hash = response.headers.
|
|
155
|
-
hash['
|
|
153
|
+
hash = response.headers.dup
|
|
154
|
+
hash['x-status'] = response.status.to_s
|
|
156
155
|
hash
|
|
157
156
|
end
|
|
158
157
|
|
data/lib/rack/cache/options.rb
CHANGED
|
@@ -72,7 +72,7 @@ module Rack::Cache
|
|
|
72
72
|
|
|
73
73
|
# The number of seconds that a cache entry should be considered
|
|
74
74
|
# "fresh" when no explicit freshness information is provided in
|
|
75
|
-
# a response. Explicit
|
|
75
|
+
# a response. Explicit cache-control or expires headers
|
|
76
76
|
# override this value.
|
|
77
77
|
#
|
|
78
78
|
# Default: 0
|
|
@@ -83,12 +83,12 @@ module Rack::Cache
|
|
|
83
83
|
# example, in most cases, it makes sense to prevent cookies from being
|
|
84
84
|
# stored in the cache.
|
|
85
85
|
#
|
|
86
|
-
# Default: ['
|
|
86
|
+
# Default: ['set-cookie']
|
|
87
87
|
option_accessor :ignore_headers
|
|
88
88
|
|
|
89
89
|
# Set of request headers that trigger "private" cache-control behavior
|
|
90
90
|
# on responses that don't explicitly state whether the response is
|
|
91
|
-
# public or private via a
|
|
91
|
+
# public or private via a cache-control directive. Applications that use
|
|
92
92
|
# cookies for authorization may need to add the 'Cookie' header to this
|
|
93
93
|
# list.
|
|
94
94
|
#
|
|
@@ -96,11 +96,11 @@ module Rack::Cache
|
|
|
96
96
|
option_accessor :private_headers
|
|
97
97
|
|
|
98
98
|
# Specifies whether a client can force cache reload by including a
|
|
99
|
-
#
|
|
99
|
+
# cache-control "no-cache" directive in the request. Disabled by default.
|
|
100
100
|
option_accessor :allow_reload
|
|
101
101
|
|
|
102
102
|
# Specifies whether a client can force cache revalidate by including a
|
|
103
|
-
#
|
|
103
|
+
# cache-control "max-age=0" directive in the request. Disabled by default.
|
|
104
104
|
option_accessor :allow_revalidate
|
|
105
105
|
|
|
106
106
|
# Specifies whether the underlying entity store's native expiration should
|
|
@@ -148,7 +148,7 @@ module Rack::Cache
|
|
|
148
148
|
'rack-cache.metastore' => 'heap:/',
|
|
149
149
|
'rack-cache.entitystore' => 'heap:/',
|
|
150
150
|
'rack-cache.default_ttl' => 0,
|
|
151
|
-
'rack-cache.ignore_headers' => ['
|
|
151
|
+
'rack-cache.ignore_headers' => ['set-cookie'],
|
|
152
152
|
'rack-cache.private_headers' => ['Authorization', 'Cookie'],
|
|
153
153
|
'rack-cache.allow_reload' => false,
|
|
154
154
|
'rack-cache.allow_revalidate' => false,
|
data/lib/rack/cache/request.rb
CHANGED
|
@@ -18,12 +18,12 @@ module Rack::Cache
|
|
|
18
18
|
@env['REQUEST_METHOD']
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
# A CacheControl instance based on the request's
|
|
21
|
+
# A CacheControl instance based on the request's cache-control header.
|
|
22
22
|
def cache_control
|
|
23
23
|
@cache_control ||= CacheControl.new(env['HTTP_CACHE_CONTROL'])
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
# True when the
|
|
26
|
+
# True when the cache-control/no-cache directive is present or the
|
|
27
27
|
# Pragma header is set to no-cache.
|
|
28
28
|
def no_cache?
|
|
29
29
|
cache_control['no-cache'] ||
|
data/lib/rack/cache/response.rb
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
require 'time'
|
|
2
2
|
require 'set'
|
|
3
3
|
require 'rack/response'
|
|
4
|
-
require 'rack/utils'
|
|
5
4
|
require 'rack/cache/cache_control'
|
|
6
5
|
|
|
7
6
|
module Rack::Cache
|
|
7
|
+
begin
|
|
8
|
+
# For `Rack::Headers` (Rack 3+):
|
|
9
|
+
require "rack/headers"
|
|
10
|
+
Headers = ::Rack::Headers
|
|
11
|
+
rescue LoadError
|
|
12
|
+
# For `Rack::Utils::HeaderHash`:
|
|
13
|
+
require "rack/utils"
|
|
14
|
+
Headers = ::Rack::Utils::HeaderHash
|
|
15
|
+
end
|
|
8
16
|
|
|
9
17
|
# Provides access to the response generated by the downstream application. The
|
|
10
18
|
# +response+, +original_response+, and +entry+ objects exposed by the Core
|
|
@@ -31,10 +39,10 @@ module Rack::Cache
|
|
|
31
39
|
# and body.
|
|
32
40
|
def initialize(status, headers, body)
|
|
33
41
|
@status = status.to_i
|
|
34
|
-
@headers =
|
|
42
|
+
@headers = Headers[headers]
|
|
35
43
|
@body = body
|
|
36
44
|
@now = Time.now
|
|
37
|
-
@headers['
|
|
45
|
+
@headers['date'] ||= @now.httpdate
|
|
38
46
|
end
|
|
39
47
|
|
|
40
48
|
def initialize_copy(other)
|
|
@@ -62,15 +70,15 @@ module Rack::Cache
|
|
|
62
70
|
410 # Gone
|
|
63
71
|
].to_set
|
|
64
72
|
|
|
65
|
-
# A Hash of name=value pairs that correspond to the
|
|
73
|
+
# A Hash of name=value pairs that correspond to the cache-control header.
|
|
66
74
|
# Valueless parameters (e.g., must-revalidate, no-store) have a Hash value
|
|
67
|
-
# of true. This method always returns a Hash, empty if no
|
|
75
|
+
# of true. This method always returns a Hash, empty if no cache-control
|
|
68
76
|
# header is present.
|
|
69
77
|
def cache_control
|
|
70
|
-
@cache_control ||= CacheControl.new(headers['
|
|
78
|
+
@cache_control ||= CacheControl.new(headers['cache-control'])
|
|
71
79
|
end
|
|
72
80
|
|
|
73
|
-
# Set the
|
|
81
|
+
# Set the cache-control header to the values specified by the Hash. See
|
|
74
82
|
# the #cache_control method for information on expected Hash structure.
|
|
75
83
|
def cache_control=(value)
|
|
76
84
|
if value.respond_to? :to_hash
|
|
@@ -80,26 +88,26 @@ module Rack::Cache
|
|
|
80
88
|
end
|
|
81
89
|
|
|
82
90
|
if value.nil? || value.empty?
|
|
83
|
-
headers.delete('
|
|
91
|
+
headers.delete('cache-control')
|
|
84
92
|
else
|
|
85
|
-
headers['
|
|
93
|
+
headers['cache-control'] = value
|
|
86
94
|
end
|
|
87
95
|
end
|
|
88
96
|
|
|
89
97
|
# Determine if the response is "fresh". Fresh responses may be served from
|
|
90
98
|
# cache without any interaction with the origin. A response is considered
|
|
91
|
-
# fresh when it includes a
|
|
99
|
+
# fresh when it includes a cache-control/max-age indicator or Expiration
|
|
92
100
|
# header and the calculated age is less than the freshness lifetime.
|
|
93
101
|
def fresh?
|
|
94
102
|
ttl && ttl > 0
|
|
95
103
|
end
|
|
96
104
|
|
|
97
105
|
# Determine if the response is worth caching under any circumstance. Responses
|
|
98
|
-
# marked "private" with an explicit
|
|
106
|
+
# marked "private" with an explicit cache-control directive are considered
|
|
99
107
|
# uncacheable
|
|
100
108
|
#
|
|
101
|
-
# Responses with neither a freshness lifetime (
|
|
102
|
-
# validator (
|
|
109
|
+
# Responses with neither a freshness lifetime (expires, max-age) nor cache
|
|
110
|
+
# validator (last-modified, etag) are considered uncacheable.
|
|
103
111
|
def cacheable?
|
|
104
112
|
return false unless CACHEABLE_RESPONSE_CODES.include?(status)
|
|
105
113
|
return false if cache_control.no_store? || cache_control.private?
|
|
@@ -109,7 +117,7 @@ module Rack::Cache
|
|
|
109
117
|
# Determine if the response includes headers that can be used to validate
|
|
110
118
|
# the response with the origin using a conditional GET request.
|
|
111
119
|
def validateable?
|
|
112
|
-
headers.key?('
|
|
120
|
+
headers.key?('last-modified') || headers.key?('etag')
|
|
113
121
|
end
|
|
114
122
|
|
|
115
123
|
# Mark the response "private", making it ineligible for serving other
|
|
@@ -131,26 +139,26 @@ module Rack::Cache
|
|
|
131
139
|
# Mark the response stale by setting the Age header to be equal to the
|
|
132
140
|
# maximum age of the response.
|
|
133
141
|
def expire!
|
|
134
|
-
headers['
|
|
142
|
+
headers['age'] = max_age.to_s if fresh?
|
|
135
143
|
end
|
|
136
144
|
|
|
137
145
|
# The date, as specified by the Date header. When no Date header is present
|
|
138
146
|
# or is unparseable, set the Date header to Time.now and return.
|
|
139
147
|
def date
|
|
140
|
-
if date = headers['
|
|
148
|
+
if date = headers['date']
|
|
141
149
|
Time.httpdate(date)
|
|
142
150
|
else
|
|
143
|
-
headers['
|
|
151
|
+
headers['date'] = now.httpdate unless headers.frozen?
|
|
144
152
|
now
|
|
145
153
|
end
|
|
146
154
|
rescue ArgumentError
|
|
147
|
-
headers['
|
|
155
|
+
headers['date'] = now.httpdate unless headers.frozen?
|
|
148
156
|
now
|
|
149
157
|
end
|
|
150
158
|
|
|
151
159
|
# The age of the response.
|
|
152
160
|
def age
|
|
153
|
-
(headers['
|
|
161
|
+
(headers['age'] || [(now - date).to_i, 0].max).to_i
|
|
154
162
|
end
|
|
155
163
|
|
|
156
164
|
# The number of seconds after the time specified in the response's Date
|
|
@@ -165,15 +173,15 @@ module Rack::Cache
|
|
|
165
173
|
(expires && (expires - date))
|
|
166
174
|
end
|
|
167
175
|
|
|
168
|
-
# The value of the
|
|
176
|
+
# The value of the expires header as a Time object.
|
|
169
177
|
def expires
|
|
170
|
-
headers['
|
|
178
|
+
headers['expires'] && Time.httpdate(headers['expires'])
|
|
171
179
|
rescue ArgumentError
|
|
172
180
|
nil
|
|
173
181
|
end
|
|
174
182
|
|
|
175
183
|
# The number of seconds after which the response should no longer
|
|
176
|
-
# be considered fresh. Sets the
|
|
184
|
+
# be considered fresh. Sets the cache-control max-age directive.
|
|
177
185
|
def max_age=(value)
|
|
178
186
|
self.cache_control = cache_control.merge('max-age' => value.to_s)
|
|
179
187
|
end
|
|
@@ -199,39 +207,39 @@ module Rack::Cache
|
|
|
199
207
|
end
|
|
200
208
|
|
|
201
209
|
# Set the response's time-to-live for shared caches to the specified number
|
|
202
|
-
# of seconds. This adjusts the
|
|
210
|
+
# of seconds. This adjusts the cache-control/s-maxage directive.
|
|
203
211
|
def ttl=(seconds)
|
|
204
212
|
self.shared_max_age = age + seconds
|
|
205
213
|
end
|
|
206
214
|
|
|
207
215
|
# Set the response's time-to-live for private/client caches. This adjusts
|
|
208
|
-
# the
|
|
216
|
+
# the cache-control/max-age directive.
|
|
209
217
|
def client_ttl=(seconds)
|
|
210
218
|
self.max_age = age + seconds
|
|
211
219
|
end
|
|
212
220
|
|
|
213
|
-
# The String value of the
|
|
221
|
+
# The String value of the last-modified header exactly as it appears
|
|
214
222
|
# in the response (i.e., no date parsing / conversion is performed).
|
|
215
223
|
def last_modified
|
|
216
|
-
headers['
|
|
224
|
+
headers['last-modified']
|
|
217
225
|
end
|
|
218
226
|
|
|
219
|
-
# The literal value of
|
|
227
|
+
# The literal value of etag HTTP header or nil if no etag is specified.
|
|
220
228
|
def etag
|
|
221
|
-
headers['
|
|
229
|
+
headers['etag']
|
|
222
230
|
end
|
|
223
231
|
|
|
224
232
|
# Headers that MUST NOT be included with 304 Not Modified responses.
|
|
225
233
|
#
|
|
226
234
|
# http://tools.ietf.org/html/rfc2616#section-10.3.5
|
|
227
235
|
NOT_MODIFIED_OMIT_HEADERS = %w[
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
236
|
+
allow
|
|
237
|
+
content-encoding
|
|
238
|
+
content-language
|
|
239
|
+
content-length
|
|
240
|
+
content-md5
|
|
241
|
+
content-type
|
|
242
|
+
last-modified
|
|
235
243
|
].to_set
|
|
236
244
|
|
|
237
245
|
# Modify the response so that it conforms to the rules defined for
|
|
@@ -247,20 +255,20 @@ module Rack::Cache
|
|
|
247
255
|
nil
|
|
248
256
|
end
|
|
249
257
|
|
|
250
|
-
# The literal value of the
|
|
258
|
+
# The literal value of the vary header, or nil when no header is present.
|
|
251
259
|
def vary
|
|
252
|
-
headers['
|
|
260
|
+
headers['vary']
|
|
253
261
|
end
|
|
254
262
|
|
|
255
|
-
# Does the response include a
|
|
263
|
+
# Does the response include a vary header?
|
|
256
264
|
def vary?
|
|
257
265
|
! vary.nil?
|
|
258
266
|
end
|
|
259
267
|
|
|
260
|
-
# An array of header names given in the
|
|
261
|
-
# array when no
|
|
268
|
+
# An array of header names given in the vary header or an empty
|
|
269
|
+
# array when no vary header is present.
|
|
262
270
|
def vary_header_names
|
|
263
|
-
return [] unless vary = headers['
|
|
271
|
+
return [] unless vary = headers['vary']
|
|
264
272
|
vary.split(/[\s,]+/)
|
|
265
273
|
end
|
|
266
274
|
|
data/lib/rack/cache.rb
CHANGED
|
@@ -3,8 +3,8 @@ require 'rack'
|
|
|
3
3
|
# = HTTP Caching For Rack
|
|
4
4
|
#
|
|
5
5
|
# Rack::Cache is suitable as a quick, drop-in component to enable HTTP caching
|
|
6
|
-
# for Rack-enabled applications that produce freshness (+
|
|
7
|
-
# and/or validation (+
|
|
6
|
+
# for Rack-enabled applications that produce freshness (+expires+, +cache-control+)
|
|
7
|
+
# and/or validation (+last-modified+, +etag+) information.
|
|
8
8
|
#
|
|
9
9
|
# * Standards-based (RFC 2616 compliance)
|
|
10
10
|
# * Freshness/expiration based caching and validation
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rack-cache
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.14.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Tomayko
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-07-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -108,9 +108,37 @@ dependencies:
|
|
|
108
108
|
- - ">="
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: rdiscount
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - ">="
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '0'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
name: hanna-nouveau
|
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
|
128
|
+
requirements:
|
|
129
|
+
- - ">="
|
|
130
|
+
- !ruby/object:Gem::Version
|
|
131
|
+
version: '0'
|
|
132
|
+
type: :development
|
|
133
|
+
prerelease: false
|
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
+
requirements:
|
|
136
|
+
- - ">="
|
|
137
|
+
- !ruby/object:Gem::Version
|
|
138
|
+
version: '0'
|
|
111
139
|
description: Rack::Cache is suitable as a quick drop-in component to enable HTTP caching
|
|
112
|
-
for Rack-based applications that produce freshness (
|
|
113
|
-
validation (
|
|
140
|
+
for Rack-based applications that produce freshness (expires, cache-control) and/or
|
|
141
|
+
validation (last-modified, etag) information.
|
|
114
142
|
email: r@tomayko.com
|
|
115
143
|
executables: []
|
|
116
144
|
extensions: []
|
|
@@ -138,11 +166,12 @@ files:
|
|
|
138
166
|
- lib/rack/cache/request.rb
|
|
139
167
|
- lib/rack/cache/response.rb
|
|
140
168
|
- lib/rack/cache/storage.rb
|
|
141
|
-
|
|
169
|
+
- lib/rack/cache/version.rb
|
|
170
|
+
homepage: https://github.com/rack/rack-cache
|
|
142
171
|
licenses:
|
|
143
172
|
- MIT
|
|
144
173
|
metadata: {}
|
|
145
|
-
post_install_message:
|
|
174
|
+
post_install_message:
|
|
146
175
|
rdoc_options:
|
|
147
176
|
- "--line-numbers"
|
|
148
177
|
- "--inline-source"
|
|
@@ -163,8 +192,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
163
192
|
- !ruby/object:Gem::Version
|
|
164
193
|
version: '0'
|
|
165
194
|
requirements: []
|
|
166
|
-
rubygems_version: 3.
|
|
167
|
-
signing_key:
|
|
195
|
+
rubygems_version: 3.4.10
|
|
196
|
+
signing_key:
|
|
168
197
|
specification_version: 4
|
|
169
198
|
summary: HTTP Caching for Rack
|
|
170
199
|
test_files: []
|