rack-cache 0.3.0 → 0.4
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.
Potentially problematic release.
This version of rack-cache might be problematic. Click here for more details.
- data/CHANGES +43 -0
- data/README +18 -9
- data/Rakefile +1 -14
- data/TODO +13 -14
- data/doc/configuration.markdown +7 -153
- data/doc/faq.markdown +8 -0
- data/doc/index.markdown +7 -9
- data/example/sinatra/app.rb +25 -0
- data/example/sinatra/views/index.erb +44 -0
- data/lib/rack/cache.rb +5 -11
- data/lib/rack/cache/cachecontrol.rb +193 -0
- data/lib/rack/cache/context.rb +190 -52
- data/lib/rack/cache/entitystore.rb +10 -4
- data/lib/rack/cache/key.rb +52 -0
- data/lib/rack/cache/metastore.rb +52 -16
- data/lib/rack/cache/options.rb +60 -39
- data/lib/rack/cache/request.rb +11 -15
- data/lib/rack/cache/response.rb +221 -30
- data/lib/rack/cache/storage.rb +1 -2
- data/rack-cache.gemspec +9 -15
- data/test/cache_test.rb +9 -6
- data/test/cachecontrol_test.rb +139 -0
- data/test/context_test.rb +251 -169
- data/test/entitystore_test.rb +12 -11
- data/test/key_test.rb +50 -0
- data/test/metastore_test.rb +57 -14
- data/test/options_test.rb +11 -0
- data/test/request_test.rb +19 -0
- data/test/response_test.rb +164 -23
- data/test/spec_setup.rb +7 -0
- metadata +12 -20
- data/doc/events.dot +0 -27
- data/lib/rack/cache/config.rb +0 -65
- data/lib/rack/cache/config/busters.rb +0 -16
- data/lib/rack/cache/config/default.rb +0 -133
- data/lib/rack/cache/config/no-cache.rb +0 -13
- data/lib/rack/cache/core.rb +0 -299
- data/lib/rack/cache/headers.rb +0 -325
- data/lib/rack/utils/environment_headers.rb +0 -78
- data/test/config_test.rb +0 -66
- data/test/core_test.rb +0 -84
- data/test/environment_headers_test.rb +0 -69
- data/test/headers_test.rb +0 -298
- data/test/logging_test.rb +0 -45
data/test/core_test.rb
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/spec_setup"
|
2
|
-
require 'rack/cache/core'
|
3
|
-
|
4
|
-
class MockCore
|
5
|
-
include Rack::Cache::Core
|
6
|
-
alias_method :initialize, :initialize_core
|
7
|
-
public :transition, :trigger, :events
|
8
|
-
end
|
9
|
-
|
10
|
-
describe 'Rack::Cache::Core' do
|
11
|
-
before :each do
|
12
|
-
@core = MockCore.new
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'has events after instantiation' do
|
16
|
-
@core.events.should.respond_to :[]
|
17
|
-
end
|
18
|
-
it 'defines and triggers event handlers' do
|
19
|
-
executed = false
|
20
|
-
@core.on(:foo) { executed = true }
|
21
|
-
@core.trigger :foo
|
22
|
-
executed.should.be true
|
23
|
-
end
|
24
|
-
it 'executes multiple handlers in LIFO order' do
|
25
|
-
x = 'nothing executed'
|
26
|
-
@core.on :foo do
|
27
|
-
x.should.equal 'bottom executed'
|
28
|
-
x = 'top executed'
|
29
|
-
end
|
30
|
-
@core.on :foo do
|
31
|
-
x.should.equal 'nothing executed'
|
32
|
-
x = 'bottom executed'
|
33
|
-
end
|
34
|
-
@core.trigger :foo
|
35
|
-
x.should.equal 'top executed'
|
36
|
-
end
|
37
|
-
it 'records event execution history' do
|
38
|
-
@core.on(:foo) {}
|
39
|
-
@core.trigger :foo
|
40
|
-
@core.should.a.performed :foo
|
41
|
-
end
|
42
|
-
it 'raises an exception when asked to perform an unknown event' do
|
43
|
-
assert_raises NameError do
|
44
|
-
@core.trigger :foo
|
45
|
-
end
|
46
|
-
end
|
47
|
-
it 'raises an exception when asked to transition to an unknown event' do
|
48
|
-
@core.on(:bling) {}
|
49
|
-
@core.on(:foo) { throw(:transition, [:bling]) }
|
50
|
-
lambda { @core.transition(from=:foo, to=[:bar, :baz]) }.
|
51
|
-
should.raise Rack::Cache::IllegalTransition
|
52
|
-
end
|
53
|
-
it 'passes transition arguments to handlers' do
|
54
|
-
passed = nil
|
55
|
-
@core.meta_def(:perform_bar) do |*args|
|
56
|
-
passed = args
|
57
|
-
'hi'
|
58
|
-
end
|
59
|
-
@core.on(:bar) {}
|
60
|
-
@core.on(:foo) { throw(:transition, [:bar, 1, 2, 3]) }
|
61
|
-
result = @core.transition(from=:foo, to=[:bar])
|
62
|
-
passed.should.equal [1,2,3]
|
63
|
-
result.should.equal 'hi'
|
64
|
-
end
|
65
|
-
it 'fully transitions out of handlers when the next event is invoked' do
|
66
|
-
x = []
|
67
|
-
@core.on(:foo) {
|
68
|
-
x << 'in foo, before transitioning to bar'
|
69
|
-
throw(:transition, [:bar])
|
70
|
-
x << 'in foo, after transitioning to bar'
|
71
|
-
}
|
72
|
-
@core.on(:bar) { x << 'in bar' }
|
73
|
-
@core.trigger(:foo).should.equal [:bar]
|
74
|
-
@core.trigger(:bar).should.be.nil
|
75
|
-
x.should.equal [
|
76
|
-
'in foo, before transitioning to bar',
|
77
|
-
'in bar'
|
78
|
-
]
|
79
|
-
end
|
80
|
-
it 'returns the transition event name' do
|
81
|
-
@core.on(:foo) { throw(:transition, [:bar]) }
|
82
|
-
@core.trigger(:foo).should.equal [:bar]
|
83
|
-
end
|
84
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/spec_setup"
|
2
|
-
require 'rack/utils/environment_headers'
|
3
|
-
|
4
|
-
describe 'Rack::Utils::EnvironmentHeaders' do
|
5
|
-
|
6
|
-
before :each do
|
7
|
-
@now = Time.now.httpdate
|
8
|
-
@env = {
|
9
|
-
'CONTENT_TYPE' => 'text/plain',
|
10
|
-
'CONTENT_LENGTH' => '0x1A4',
|
11
|
-
'HTTP_X_FOO' => 'BAR',
|
12
|
-
'HTTP_IF_MODIFIED_SINCE' => @now,
|
13
|
-
'rack.run_once' => true
|
14
|
-
}
|
15
|
-
@h = Rack::Utils::EnvironmentHeaders.new(@env)
|
16
|
-
end
|
17
|
-
|
18
|
-
after(:each) {
|
19
|
-
@env, @h = nil, nil
|
20
|
-
}
|
21
|
-
|
22
|
-
it 'retrieves headers with #[]' do
|
23
|
-
@h.should.respond_to :[]
|
24
|
-
@h['X-Foo'].should.equal 'BAR'
|
25
|
-
@h['If-Modified-Since'].should.equal @now
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'sets headers with #[]=' do
|
29
|
-
@h.should.respond_to :[]=
|
30
|
-
@h['X-Foo'] = 'BAZZLE'
|
31
|
-
@h['X-Foo'].should.equal 'BAZZLE'
|
32
|
-
end
|
33
|
-
|
34
|
-
it 'sets values on the underlying environment hash' do
|
35
|
-
@h['X-Something-Else'] = 'FOO'
|
36
|
-
@env['HTTP_X_SOMETHING_ELSE'].should.equal 'FOO'
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'handles Content-Type special case' do
|
40
|
-
@h['Content-Type'].should.equal 'text/plain'
|
41
|
-
end
|
42
|
-
|
43
|
-
it 'handles Content-Length special case' do
|
44
|
-
@h['Content-Length'].should.equal '0x1A4'
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'implements #include? with RFC 2616 header name' do
|
48
|
-
@h.should.include 'If-Modified-Since'
|
49
|
-
end
|
50
|
-
|
51
|
-
it 'deletes underlying env entries' do
|
52
|
-
@h.delete('X-Foo')
|
53
|
-
@env.should.not.include? 'HTTP_X_FOO'
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'returns the underlying environment hash with #to_env' do
|
57
|
-
@h.to_env.should.be @env
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'iterates over all headers with #each' do
|
61
|
-
hash = {}
|
62
|
-
@h.each { |name,value| hash[name] = value }
|
63
|
-
hash.should.equal 'Content-Type' => 'text/plain',
|
64
|
-
'Content-Length' => '0x1A4',
|
65
|
-
'X-Foo' => 'BAR',
|
66
|
-
'If-Modified-Since' => @now
|
67
|
-
end
|
68
|
-
|
69
|
-
end
|
data/test/headers_test.rb
DELETED
@@ -1,298 +0,0 @@
|
|
1
|
-
require "#{File.dirname(__FILE__)}/spec_setup"
|
2
|
-
|
3
|
-
class MockResponse < Rack::MockResponse
|
4
|
-
include Rack::Cache::Headers
|
5
|
-
include Rack::Cache::ResponseHeaders
|
6
|
-
public :now
|
7
|
-
end
|
8
|
-
|
9
|
-
describe 'Rack::Cache::Headers' do
|
10
|
-
before :each do
|
11
|
-
@now = Time.httpdate(Time.now.httpdate)
|
12
|
-
@res = MockResponse.new(200, {'Date' => @now.httpdate}, '')
|
13
|
-
@one_hour_ago = Time.httpdate((Time.now - (60**2)).httpdate)
|
14
|
-
end
|
15
|
-
after :each do
|
16
|
-
@now, @res, @one_hour_ago = nil
|
17
|
-
end
|
18
|
-
|
19
|
-
describe '#cache_control' do
|
20
|
-
it 'handles single name=value pair' do
|
21
|
-
@res.headers['Cache-Control'] = 'max-age=600'
|
22
|
-
@res.cache_control['max-age'].should.equal '600'
|
23
|
-
end
|
24
|
-
it 'handles multiple name=value pairs' do
|
25
|
-
@res.headers['Cache-Control'] = 'max-age=600, max-stale=300, min-fresh=570'
|
26
|
-
@res.cache_control['max-age'].should.equal '600'
|
27
|
-
@res.cache_control['max-stale'].should.equal '300'
|
28
|
-
@res.cache_control['min-fresh'].should.equal '570'
|
29
|
-
end
|
30
|
-
it 'handles a single flag value' do
|
31
|
-
@res.headers['Cache-Control'] = 'no-cache'
|
32
|
-
@res.cache_control.should.include 'no-cache'
|
33
|
-
@res.cache_control['no-cache'].should.be true
|
34
|
-
end
|
35
|
-
it 'handles a bunch of all kinds of stuff' do
|
36
|
-
@res.headers['Cache-Control'] = 'max-age=600,must-revalidate,min-fresh=3000,foo=bar,baz'
|
37
|
-
@res.cache_control['max-age'].should.equal '600'
|
38
|
-
@res.cache_control['must-revalidate'].should.be true
|
39
|
-
@res.cache_control['min-fresh'].should.equal '3000'
|
40
|
-
@res.cache_control['foo'].should.equal 'bar'
|
41
|
-
@res.cache_control['baz'].should.be true
|
42
|
-
end
|
43
|
-
it 'removes the header when given an empty hash' do
|
44
|
-
@res.headers['Cache-Control'] = 'max-age=600, must-revalidate'
|
45
|
-
@res.cache_control['max-age'].should.equal '600'
|
46
|
-
@res.cache_control = {}
|
47
|
-
@res.headers.should.not.include 'Cache-Control'
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe 'Rack::Cache::ResponseHeaders' do
|
53
|
-
before :each do
|
54
|
-
@now = Time.httpdate(Time.now.httpdate)
|
55
|
-
@one_hour_ago = Time.httpdate((Time.now - (60**2)).httpdate)
|
56
|
-
@one_hour_later = Time.httpdate((Time.now + (60**2)).httpdate)
|
57
|
-
@res = MockResponse.new(200, {'Date' => @now.httpdate}, '')
|
58
|
-
end
|
59
|
-
after :each do
|
60
|
-
@now, @res, @one_hour_ago = nil
|
61
|
-
end
|
62
|
-
|
63
|
-
describe '#validateable?' do
|
64
|
-
it 'is true when Last-Modified header present' do
|
65
|
-
@res = MockResponse.new(200, { 'Last-Modified' => @one_hour_ago.httpdate }, '')
|
66
|
-
@res.extend Rack::Cache::ResponseHeaders
|
67
|
-
@res.should.be.validateable
|
68
|
-
end
|
69
|
-
it 'is true when Etag header present' do
|
70
|
-
@res = MockResponse.new(200, { 'Etag' => '"12345"' }, '')
|
71
|
-
@res.extend Rack::Cache::ResponseHeaders
|
72
|
-
@res.should.be.validateable
|
73
|
-
end
|
74
|
-
it 'is false when no validator is present' do
|
75
|
-
@res = MockResponse.new(200, {}, '')
|
76
|
-
@res.extend Rack::Cache::ResponseHeaders
|
77
|
-
@res.should.not.be.validateable
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
describe '#date' do
|
82
|
-
it 'uses the Date header if present' do
|
83
|
-
@res = MockResponse.new(200, { 'Date' => @one_hour_ago.httpdate }, '')
|
84
|
-
@res.extend Rack::Cache::ResponseHeaders
|
85
|
-
@res.date.should.equal @one_hour_ago
|
86
|
-
end
|
87
|
-
it 'uses the current time when no Date header present' do
|
88
|
-
@res = MockResponse.new(200, {}, '')
|
89
|
-
@res.extend Rack::Cache::ResponseHeaders
|
90
|
-
@res.date.should.be.close Time.now, 1
|
91
|
-
end
|
92
|
-
it 'returns the correct date when the header is modified directly' do
|
93
|
-
@res = MockResponse.new(200, { 'Date' => @one_hour_ago.httpdate }, '')
|
94
|
-
@res.extend Rack::Cache::ResponseHeaders
|
95
|
-
@res.date.should.equal @one_hour_ago
|
96
|
-
@res.headers['Date'] = @now.httpdate
|
97
|
-
@res.date.should.equal @now
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
describe '#expires_at' do
|
102
|
-
it 'returns #date + #max_age when Cache-Control/max-age is present' do
|
103
|
-
@res.headers['Cache-Control'] = 'max-age=500'
|
104
|
-
@res.expires_at.should.equal @res.date + 500
|
105
|
-
end
|
106
|
-
it 'uses the Expires header when present and no Cache-Control/max-age' do
|
107
|
-
@res.headers['Expires'] = @one_hour_ago.httpdate
|
108
|
-
@res.expires_at.should.equal @one_hour_ago
|
109
|
-
end
|
110
|
-
it 'returns nil when no Expires or Cache-Control provided' do
|
111
|
-
@res.expires_at.should.be nil
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
describe '#max_age' do
|
116
|
-
it 'uses s-maxage cache control directive when present' do
|
117
|
-
@res.headers['Cache-Control'] = 's-maxage=600, max-age=0'
|
118
|
-
@res.max_age.should.equal 600
|
119
|
-
end
|
120
|
-
it 'falls back to max-age when no s-maxage directive present' do
|
121
|
-
@res.headers['Cache-Control'] = 'max-age=600'
|
122
|
-
@res.max_age.should.equal 600
|
123
|
-
end
|
124
|
-
it 'falls back to Expires when no max-age or s-maxage directive present' do
|
125
|
-
@res.headers['Cache-Control'] = 'must-revalidate'
|
126
|
-
@res.headers['Expires'] = @one_hour_later.httpdate
|
127
|
-
@res.max_age.should.equal 60 ** 2
|
128
|
-
end
|
129
|
-
it 'gives a #max_age of nil when no freshness information available' do
|
130
|
-
@res.max_age.should.be.nil
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
describe '#freshness_information?' do
|
135
|
-
it 'is true when Expires header is present' do
|
136
|
-
@res.headers['Expires'] = Time.now.httpdate
|
137
|
-
@res.freshness_information?.should.be true
|
138
|
-
end
|
139
|
-
it 'is true when a Cache-Control max-age directive is present' do
|
140
|
-
@res.headers['Cache-Control'] = 'max-age=500'
|
141
|
-
@res.freshness_information?.should.be true
|
142
|
-
end
|
143
|
-
it 'is true when a Cache-Control s-maxage directive is present' do
|
144
|
-
@res.headers['Cache-Control'] = 's-maxage=500'
|
145
|
-
@res.freshness_information?.should.be true
|
146
|
-
end
|
147
|
-
it 'is not true otherwise' do
|
148
|
-
@res.freshness_information?.should.be false
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
describe '#public=' do
|
153
|
-
it 'adds the public Cache-Control directive when set true' do
|
154
|
-
@res.headers['Cache-Control'] = 'max-age=100'
|
155
|
-
@res.public = true
|
156
|
-
@res.headers['Cache-Control'].should.equal 'public, max-age=100'
|
157
|
-
end
|
158
|
-
it 'removes the private Cache-Control directive' do
|
159
|
-
@res.headers['Cache-Control'] = 'private, max-age=100'
|
160
|
-
@res.public = true
|
161
|
-
@res.headers['Cache-Control'].should.equal 'public, max-age=100'
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
describe '#public?' do
|
166
|
-
it 'is true when the public directive is present' do
|
167
|
-
@res.headers['Cache-Control'] = 'public'
|
168
|
-
@res.should.be.public
|
169
|
-
end
|
170
|
-
it 'is false when only the private directive is present' do
|
171
|
-
@res.headers['Cache-Control'] = 'private'
|
172
|
-
@res.should.not.be.public
|
173
|
-
end
|
174
|
-
it 'is false when no Cache-Control header is present' do
|
175
|
-
@res.should.not.be.public
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
describe '#private=' do
|
180
|
-
it 'adds the private Cache-Control directive when set true' do
|
181
|
-
@res.headers['Cache-Control'] = 'max-age=100'
|
182
|
-
@res.private = true
|
183
|
-
@res.headers['Cache-Control'].should.equal 'private, max-age=100'
|
184
|
-
end
|
185
|
-
it 'removes the public Cache-Control directive' do
|
186
|
-
@res.headers['Cache-Control'] = 'public, max-age=100'
|
187
|
-
@res.private = true
|
188
|
-
@res.headers['Cache-Control'].should.equal 'private, max-age=100'
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
describe '#private?' do
|
193
|
-
it 'is true when the private directive is present' do
|
194
|
-
@res.headers['Cache-Control'] = 'private'
|
195
|
-
@res.should.be.private
|
196
|
-
end
|
197
|
-
it 'is false when the private directive is not present' do
|
198
|
-
@res.headers['Cache-Control'] = 'public'
|
199
|
-
@res.should.not.be.private
|
200
|
-
end
|
201
|
-
it 'is false when no Cache-Control header is present' do
|
202
|
-
@res.should.not.be.private
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
describe '#no_cache?' do
|
207
|
-
it 'is true when a Cache-Control no-cache directive is present' do
|
208
|
-
@res.headers['Cache-Control'] = 'no-cache'
|
209
|
-
assert @res.no_cache?
|
210
|
-
end
|
211
|
-
it 'is false otherwise' do
|
212
|
-
assert !@res.no_cache?
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
describe '#must_revalidate?' do
|
217
|
-
it 'is true when a Cache-Control must-revalidate directive is present' do
|
218
|
-
@res.headers['Cache-Control'] = 'private, must-revalidate'
|
219
|
-
assert @res.must_revalidate?
|
220
|
-
end
|
221
|
-
it 'is true when a Cache-Control proxy-revalidate directive is present' do
|
222
|
-
@res.headers['Cache-Control'] = 'public, proxy-revalidate'
|
223
|
-
assert @res.must_revalidate?
|
224
|
-
end
|
225
|
-
it 'is false otherwise' do
|
226
|
-
assert !@res.must_revalidate?
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
describe '#stale?' do
|
231
|
-
it 'is true when TTL cannot be established' do
|
232
|
-
@res.should.be.stale
|
233
|
-
end
|
234
|
-
it 'is false when the TTL is <= 0' do
|
235
|
-
@res.headers['Expires'] = (@res.now + 10).httpdate
|
236
|
-
@res.should.not.be.stale
|
237
|
-
end
|
238
|
-
it 'is true when the TTL is >= 0' do
|
239
|
-
@res.headers['Expires'] = (@res.now - 10).httpdate
|
240
|
-
@res.should.be.stale
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
describe '#ttl' do
|
245
|
-
it 'is nil when no Expires or Cache-Control headers present' do
|
246
|
-
@res.ttl.should.be.nil
|
247
|
-
end
|
248
|
-
it 'uses the Expires header when no max-age is present' do
|
249
|
-
@res.headers['Expires'] = (@res.now + (60**2)).httpdate
|
250
|
-
@res.ttl.should.be.close(60**2, 1)
|
251
|
-
end
|
252
|
-
it 'returns negative values when Expires is in part' do
|
253
|
-
@res.ttl.should.be.nil
|
254
|
-
@res.headers['Expires'] = @one_hour_ago.httpdate
|
255
|
-
@res.ttl.should.be < 0
|
256
|
-
end
|
257
|
-
it 'uses the Cache-Control max-age value when present' do
|
258
|
-
@res.headers['Cache-Control'] = 'max-age=60'
|
259
|
-
@res.ttl.should.be.close(60, 1)
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
describe '#vary' do
|
264
|
-
it 'is nil when no Vary header is present' do
|
265
|
-
@res.vary.should.be.nil
|
266
|
-
end
|
267
|
-
it 'returns the literal value of the Vary header' do
|
268
|
-
@res.headers['Vary'] = 'Foo Bar Baz'
|
269
|
-
@res.vary.should.equal 'Foo Bar Baz'
|
270
|
-
end
|
271
|
-
it 'can be checked for existence using the #vary? method' do
|
272
|
-
@res.should.respond_to :vary?
|
273
|
-
@res.should.not.vary
|
274
|
-
@res.headers['Vary'] = '*'
|
275
|
-
@res.should.vary
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
describe '#vary_header_names' do
|
280
|
-
it 'returns an empty Array when no Vary header is present' do
|
281
|
-
@res.vary_header_names.should.be.empty
|
282
|
-
end
|
283
|
-
it 'parses a single header name value' do
|
284
|
-
@res.headers['Vary'] = 'Accept-Language'
|
285
|
-
@res.vary_header_names.should.equal ['Accept-Language']
|
286
|
-
end
|
287
|
-
it 'parses multiple header name values separated by spaces' do
|
288
|
-
@res.headers['Vary'] = 'Accept-Language User-Agent X-Foo'
|
289
|
-
@res.vary_header_names.should.equal \
|
290
|
-
['Accept-Language', 'User-Agent', 'X-Foo']
|
291
|
-
end
|
292
|
-
it 'parses multiple header name values separated by commas' do
|
293
|
-
@res.headers['Vary'] = 'Accept-Language,User-Agent, X-Foo'
|
294
|
-
@res.vary_header_names.should.equal \
|
295
|
-
['Accept-Language', 'User-Agent', 'X-Foo']
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|