rack-cache 1.13.0 → 1.15.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/headers.rb +21 -0
- 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 +42 -42
- data/lib/rack/cache/version.rb +5 -0
- data/lib/rack/cache.rb +2 -2
- metadata +39 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e551d4e48499cda1a41809df4010eaf84bb5cf75edb113543a803cf4b7a5f2a6
|
4
|
+
data.tar.gz: 33d4f98db1ba1c858bbf0337e249c7d121e0f14f3705e00934f2adb29ddccddc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d068832ba4eb458626148d0ccd9d4485f82305934fa97201b8b4d2ffad975a50e2c8152129c2a0f95971ed172184246e9dcd12de308324dbdb7b04f4792d9537
|
7
|
+
data.tar.gz: 035b6979668d9315fb9a29f081df044c64f34380f54dd4c16b0b3a13534fe205fae9d2d30bcd8fe682f2747b5aa8ab40e736fea1774841364165da80065d0b66
|
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
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Rack::Cache
|
2
|
+
begin
|
3
|
+
# For `Rack::Headers` (Rack 3+):
|
4
|
+
require "rack/headers"
|
5
|
+
Headers = ::Rack::Headers
|
6
|
+
def self.Headers(headers)
|
7
|
+
Headers[headers]
|
8
|
+
end
|
9
|
+
rescue LoadError
|
10
|
+
# For `Rack::Utils::HeaderHash`:
|
11
|
+
require "rack/utils"
|
12
|
+
Headers = ::Rack::Utils::HeaderHash
|
13
|
+
def self.Headers(headers)
|
14
|
+
if headers.is_a?(Headers) && !headers.frozen?
|
15
|
+
return headers
|
16
|
+
else
|
17
|
+
return Headers.new(headers)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -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,11 +1,11 @@
|
|
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
|
+
require_relative 'headers'
|
8
7
|
|
8
|
+
module Rack::Cache
|
9
9
|
# Provides access to the response generated by the downstream application. The
|
10
10
|
# +response+, +original_response+, and +entry+ objects exposed by the Core
|
11
11
|
# caching engine are instances of this class.
|
@@ -31,10 +31,10 @@ module Rack::Cache
|
|
31
31
|
# and body.
|
32
32
|
def initialize(status, headers, body)
|
33
33
|
@status = status.to_i
|
34
|
-
@headers = Rack::
|
34
|
+
@headers = Rack::Cache::Headers(headers)
|
35
35
|
@body = body
|
36
36
|
@now = Time.now
|
37
|
-
@headers['
|
37
|
+
@headers['date'] ||= @now.httpdate
|
38
38
|
end
|
39
39
|
|
40
40
|
def initialize_copy(other)
|
@@ -62,15 +62,15 @@ module Rack::Cache
|
|
62
62
|
410 # Gone
|
63
63
|
].to_set
|
64
64
|
|
65
|
-
# A Hash of name=value pairs that correspond to the
|
65
|
+
# A Hash of name=value pairs that correspond to the cache-control header.
|
66
66
|
# Valueless parameters (e.g., must-revalidate, no-store) have a Hash value
|
67
|
-
# of true. This method always returns a Hash, empty if no
|
67
|
+
# of true. This method always returns a Hash, empty if no cache-control
|
68
68
|
# header is present.
|
69
69
|
def cache_control
|
70
|
-
@cache_control ||= CacheControl.new(headers['
|
70
|
+
@cache_control ||= CacheControl.new(headers['cache-control'])
|
71
71
|
end
|
72
72
|
|
73
|
-
# Set the
|
73
|
+
# Set the cache-control header to the values specified by the Hash. See
|
74
74
|
# the #cache_control method for information on expected Hash structure.
|
75
75
|
def cache_control=(value)
|
76
76
|
if value.respond_to? :to_hash
|
@@ -80,26 +80,26 @@ module Rack::Cache
|
|
80
80
|
end
|
81
81
|
|
82
82
|
if value.nil? || value.empty?
|
83
|
-
headers.delete('
|
83
|
+
headers.delete('cache-control')
|
84
84
|
else
|
85
|
-
headers['
|
85
|
+
headers['cache-control'] = value
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
89
|
# Determine if the response is "fresh". Fresh responses may be served from
|
90
90
|
# cache without any interaction with the origin. A response is considered
|
91
|
-
# fresh when it includes a
|
91
|
+
# fresh when it includes a cache-control/max-age indicator or Expiration
|
92
92
|
# header and the calculated age is less than the freshness lifetime.
|
93
93
|
def fresh?
|
94
94
|
ttl && ttl > 0
|
95
95
|
end
|
96
96
|
|
97
97
|
# Determine if the response is worth caching under any circumstance. Responses
|
98
|
-
# marked "private" with an explicit
|
98
|
+
# marked "private" with an explicit cache-control directive are considered
|
99
99
|
# uncacheable
|
100
100
|
#
|
101
|
-
# Responses with neither a freshness lifetime (
|
102
|
-
# validator (
|
101
|
+
# Responses with neither a freshness lifetime (expires, max-age) nor cache
|
102
|
+
# validator (last-modified, etag) are considered uncacheable.
|
103
103
|
def cacheable?
|
104
104
|
return false unless CACHEABLE_RESPONSE_CODES.include?(status)
|
105
105
|
return false if cache_control.no_store? || cache_control.private?
|
@@ -109,7 +109,7 @@ module Rack::Cache
|
|
109
109
|
# Determine if the response includes headers that can be used to validate
|
110
110
|
# the response with the origin using a conditional GET request.
|
111
111
|
def validateable?
|
112
|
-
headers.key?('
|
112
|
+
headers.key?('last-modified') || headers.key?('etag')
|
113
113
|
end
|
114
114
|
|
115
115
|
# Mark the response "private", making it ineligible for serving other
|
@@ -131,26 +131,26 @@ module Rack::Cache
|
|
131
131
|
# Mark the response stale by setting the Age header to be equal to the
|
132
132
|
# maximum age of the response.
|
133
133
|
def expire!
|
134
|
-
headers['
|
134
|
+
headers['age'] = max_age.to_s if fresh?
|
135
135
|
end
|
136
136
|
|
137
137
|
# The date, as specified by the Date header. When no Date header is present
|
138
138
|
# or is unparseable, set the Date header to Time.now and return.
|
139
139
|
def date
|
140
|
-
if date = headers['
|
140
|
+
if date = headers['date']
|
141
141
|
Time.httpdate(date)
|
142
142
|
else
|
143
|
-
headers['
|
143
|
+
headers['date'] = now.httpdate unless headers.frozen?
|
144
144
|
now
|
145
145
|
end
|
146
146
|
rescue ArgumentError
|
147
|
-
headers['
|
147
|
+
headers['date'] = now.httpdate unless headers.frozen?
|
148
148
|
now
|
149
149
|
end
|
150
150
|
|
151
151
|
# The age of the response.
|
152
152
|
def age
|
153
|
-
(headers['
|
153
|
+
(headers['age'] || [(now - date).to_i, 0].max).to_i
|
154
154
|
end
|
155
155
|
|
156
156
|
# The number of seconds after the time specified in the response's Date
|
@@ -165,15 +165,15 @@ module Rack::Cache
|
|
165
165
|
(expires && (expires - date))
|
166
166
|
end
|
167
167
|
|
168
|
-
# The value of the
|
168
|
+
# The value of the expires header as a Time object.
|
169
169
|
def expires
|
170
|
-
headers['
|
170
|
+
headers['expires'] && Time.httpdate(headers['expires'])
|
171
171
|
rescue ArgumentError
|
172
172
|
nil
|
173
173
|
end
|
174
174
|
|
175
175
|
# The number of seconds after which the response should no longer
|
176
|
-
# be considered fresh. Sets the
|
176
|
+
# be considered fresh. Sets the cache-control max-age directive.
|
177
177
|
def max_age=(value)
|
178
178
|
self.cache_control = cache_control.merge('max-age' => value.to_s)
|
179
179
|
end
|
@@ -199,39 +199,39 @@ module Rack::Cache
|
|
199
199
|
end
|
200
200
|
|
201
201
|
# Set the response's time-to-live for shared caches to the specified number
|
202
|
-
# of seconds. This adjusts the
|
202
|
+
# of seconds. This adjusts the cache-control/s-maxage directive.
|
203
203
|
def ttl=(seconds)
|
204
204
|
self.shared_max_age = age + seconds
|
205
205
|
end
|
206
206
|
|
207
207
|
# Set the response's time-to-live for private/client caches. This adjusts
|
208
|
-
# the
|
208
|
+
# the cache-control/max-age directive.
|
209
209
|
def client_ttl=(seconds)
|
210
210
|
self.max_age = age + seconds
|
211
211
|
end
|
212
212
|
|
213
|
-
# The String value of the
|
213
|
+
# The String value of the last-modified header exactly as it appears
|
214
214
|
# in the response (i.e., no date parsing / conversion is performed).
|
215
215
|
def last_modified
|
216
|
-
headers['
|
216
|
+
headers['last-modified']
|
217
217
|
end
|
218
218
|
|
219
|
-
# The literal value of
|
219
|
+
# The literal value of etag HTTP header or nil if no etag is specified.
|
220
220
|
def etag
|
221
|
-
headers['
|
221
|
+
headers['etag']
|
222
222
|
end
|
223
223
|
|
224
224
|
# Headers that MUST NOT be included with 304 Not Modified responses.
|
225
225
|
#
|
226
226
|
# http://tools.ietf.org/html/rfc2616#section-10.3.5
|
227
227
|
NOT_MODIFIED_OMIT_HEADERS = %w[
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
228
|
+
allow
|
229
|
+
content-encoding
|
230
|
+
content-language
|
231
|
+
content-length
|
232
|
+
content-md5
|
233
|
+
content-type
|
234
|
+
last-modified
|
235
235
|
].to_set
|
236
236
|
|
237
237
|
# Modify the response so that it conforms to the rules defined for
|
@@ -247,20 +247,20 @@ module Rack::Cache
|
|
247
247
|
nil
|
248
248
|
end
|
249
249
|
|
250
|
-
# The literal value of the
|
250
|
+
# The literal value of the vary header, or nil when no header is present.
|
251
251
|
def vary
|
252
|
-
headers['
|
252
|
+
headers['vary']
|
253
253
|
end
|
254
254
|
|
255
|
-
# Does the response include a
|
255
|
+
# Does the response include a vary header?
|
256
256
|
def vary?
|
257
257
|
! vary.nil?
|
258
258
|
end
|
259
259
|
|
260
|
-
# An array of header names given in the
|
261
|
-
# array when no
|
260
|
+
# An array of header names given in the vary header or an empty
|
261
|
+
# array when no vary header is present.
|
262
262
|
def vary_header_names
|
263
|
-
return [] unless vary = headers['
|
263
|
+
return [] unless vary = headers['vary']
|
264
264
|
vary.split(/[\s,]+/)
|
265
265
|
end
|
266
266
|
|
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.15.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-12-09 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: []
|
@@ -131,6 +159,7 @@ files:
|
|
131
159
|
- lib/rack/cache/context.rb
|
132
160
|
- lib/rack/cache/entity_store.rb
|
133
161
|
- lib/rack/cache/entitystore.rb
|
162
|
+
- lib/rack/cache/headers.rb
|
134
163
|
- lib/rack/cache/key.rb
|
135
164
|
- lib/rack/cache/meta_store.rb
|
136
165
|
- lib/rack/cache/metastore.rb
|
@@ -138,11 +167,12 @@ files:
|
|
138
167
|
- lib/rack/cache/request.rb
|
139
168
|
- lib/rack/cache/response.rb
|
140
169
|
- lib/rack/cache/storage.rb
|
141
|
-
|
170
|
+
- lib/rack/cache/version.rb
|
171
|
+
homepage: https://github.com/rack/rack-cache
|
142
172
|
licenses:
|
143
173
|
- MIT
|
144
174
|
metadata: {}
|
145
|
-
post_install_message:
|
175
|
+
post_install_message:
|
146
176
|
rdoc_options:
|
147
177
|
- "--line-numbers"
|
148
178
|
- "--inline-source"
|
@@ -163,8 +193,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
163
193
|
- !ruby/object:Gem::Version
|
164
194
|
version: '0'
|
165
195
|
requirements: []
|
166
|
-
rubygems_version: 3.
|
167
|
-
signing_key:
|
196
|
+
rubygems_version: 3.4.22
|
197
|
+
signing_key:
|
168
198
|
specification_version: 4
|
169
199
|
summary: HTTP Caching for Rack
|
170
200
|
test_files: []
|