Skip to content
This repository was archived by the owner on Dec 3, 2019. It is now read-only.

Commit 37dd911

Browse files
committed
Ensure the 'Cache-Control: max-age' is validated
1 parent e002c27 commit 37dd911

6 files changed

Lines changed: 48 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
# 0.1.18 (2015-05-01)
4+
5+
* Ensure the 'Cache-Control: max-age' is validated
6+
* Add regression tests
7+
* Update documentation
8+
39
## 0.1.17 (2015-04-30)
410

511
* Return the proper 'Age' header and ignore the 'public' control directive

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ HTTP Caching request.
4949
| :------------------------| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
5050
| **Are the headers cached?** | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
5151
| **Must revalidate?** | - | - | - | - | 0 | 0 | 0 | 1 | - |
52-
| **No-cache or max-age 0?** | - | - | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
52+
| **No-cache or max-age reached?** | - | - | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
5353
| **Do Etags/If-None-Match match?** | - || 0 | 1 | 0 | 1 | - | - ||
5454
| **Is the cached data expired?** | - | - | 0 | 0 | 1 | 1 | 1 | 1 | - |
5555
| **Is there an if-only-cached header?** | 0 | 1 | - | - | - | - ||| - |
@@ -125,6 +125,7 @@ To run the tests, type:
125125

126126
## TODO
127127

128+
* Validation of `s-maxage` [response header](https://tools.ietf.org/html/rfc7234#section-5.2.2.9)
128129
* Handling `Vary` header and different representations for the same resource
129130
* Handling `206 (Partial)` and `Range` headers for resuming downloads
130131
* Handling `Cache-Control: private` headers

cache_rules.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ require 'date'
66

77
Gem::Specification.new do |s|
88
s.name = 'cache_rules'
9-
s.version = '0.1.17'
9+
s.version = '0.1.18'
1010

1111
s.date = Date.today.to_s
1212

lib/validations.rb

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,11 @@ def validate_expired?(headers)
4747

4848
response_is_fresh = freshness_lifetime.to_i > current_age
4949

50-
to_bit { response_is_fresh != true }
50+
return 1 if headers[:cached]['Cache-Control'] &&
51+
headers[:cached]['Cache-Control']['max-age'] &&
52+
current_age > headers[:cached]['Cache-Control']['max-age']['token'].to_i
53+
54+
to_bit { (response_is_fresh != true) }
5155
end
5256

5357
def validate_only_if_cached?(headers)
@@ -85,8 +89,16 @@ def validate_no_cache?(headers)
8589

8690
# Must revalidate if this request header exists
8791
# source: https://tools.ietf.org/html/rfc7234#section-5.2.1.4
88-
return 1 if (( request = request_headers['Cache-Control'] )) &&
89-
request_headers['Cache-Control']['no-cache']
92+
if request_headers['Cache-Control']
93+
_, current_age = helper_freshness_lifetime.call cached_headers
94+
95+
# If max-age is 0 or if the current age is above the max-age and max-stale isn't set
96+
# source: https://tools.ietf.org/html/rfc7234#section-5.2.1.1
97+
return 1 if (( request = request_headers['Cache-Control'] )) &&
98+
request['no-cache'] ||
99+
(!request['max-stale'] && request['max-age'] &&
100+
(request['max-age']['token'].to_s == "0" || current_age > request['max-age']['token'].to_i))
101+
end
90102

91103
# source: https://tools.ietf.org/html/rfc7234#section-5.2.2.2
92104
# source: https://tools.ietf.org/html/rfc7234#section-3.2

test/test_regressions.rb

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ class TestRegressions < MiniTest::Test
88
def setup
99
@cached_headers = {
1010
:cached => {
11+
"Age" => "99999",
1112
"Date" => {"httpdate"=>"Thu, 01 Jan 2015 07:03:45 GMT", "timestamp"=>1420095825},
1213
"Cache-Control" => {
13-
"public" => {"token"=>nil, "quoted_string"=>nil}
14+
"public" => {"token"=>nil, "quoted_string"=>nil},
15+
"max-age" => {"token"=>"10", "quoted_string"=>nil}
1416
},
1517
"X-Cache-Req-Date" => {"httpdate"=>"Sat, 03 Jan 2015 07:03:45 GMT", "timestamp"=>1420268625},
1618
"X-Cache-Res-Date" => {"httpdate"=>"Sat, 03 Jan 2015 07:03:45 GMT", "timestamp"=>1420268625}
@@ -44,4 +46,24 @@ def test_bugfix_8_errors_caused_by_empty_http_headers
4446
assert_equal isnil, []
4547
assert_equal isempty, []
4648
end
49+
50+
# https://github.com/aw/CacheRules/issues/10
51+
def test_bugfix_10_request_header_max_age_is_checked
52+
request_maxage = CacheRules.validate_no_cache?({
53+
:cached => @cached_headers[:cached],
54+
:request => {"Cache-Control" => {"max-age" => {"token"=>0, "quoted_string"=>nil} } }
55+
})
56+
current = CacheRules.validate_no_cache?({
57+
:cached => @cached_headers[:cached],
58+
:request => {"Cache-Control" => {"max-age" => {"token"=>1000, "quoted_string"=>nil} } }
59+
})
60+
cached_max_age = CacheRules.validate_expired?({
61+
:cached => @cached_headers[:cached],
62+
:request => {}
63+
})
64+
65+
assert_equal 1, request_maxage
66+
assert_equal 1, current
67+
assert_equal 1, cached_max_age
68+
end
4769
end

test/test_validations.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def test_must_revalidate
164164
def test_no_cache
165165
headers1 = {
166166
:request => {'Cache-Control' => {'no-cache'=>{'token'=>nil}}},
167-
:cached => {'Cache-Control' => {}}
167+
:cached => {}
168168
}
169169
headers2 = {
170170
:request => {},

0 commit comments

Comments
 (0)