rack-cache 1.12.1 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +11 -11
- 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
|
-
[![
|
126
|
+
[![Development](https://github.com/rack/rack-cache/actions/workflows/development.yml/badge.svg)](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
|
@@ -90,13 +90,13 @@ module Rack::Cache
|
|
90
90
|
# the list
|
91
91
|
vary = response.vary
|
92
92
|
entries =
|
93
|
-
read(key).reject do |env,res|
|
94
|
-
(vary == res['
|
93
|
+
read(key).reject do |env, 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
|
99
|
+
headers.delete('age')
|
100
100
|
|
101
101
|
entries.unshift [stored_env, headers]
|
102
102
|
if request.env['rack-cache.use_native_ttl'] && response.fresh?
|
@@ -145,13 +145,13 @@ module Rack::Cache
|
|
145
145
|
# Converts a stored response hash into a Response object. The caller
|
146
146
|
# is responsible for loading and passing the body if needed.
|
147
147
|
def restore_response(hash, body=[])
|
148
|
-
status = hash.delete('
|
148
|
+
status = hash.delete('x-status').to_i
|
149
149
|
Rack::Cache::Response.new(status, hash, body)
|
150
150
|
end
|
151
151
|
|
152
152
|
def persist_response(response)
|
153
|
-
hash = response.headers.
|
154
|
-
hash['
|
153
|
+
hash = response.headers.dup
|
154
|
+
hash['x-status'] = response.status.to_s
|
155
155
|
hash
|
156
156
|
end
|
157
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: []
|