Skip to content

Commit

Permalink
Allow customisation of non-cached headers
Browse files Browse the repository at this point in the history
Headers specified in the :non_cached_headers option are included in responses but not stored in cached entities.
  • Loading branch information
Matt-Yorkley committed Aug 19, 2023
1 parent d07cce7 commit 88e05fe
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 15 deletions.
2 changes: 1 addition & 1 deletion lib/rack/cache/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def fetch
# Write the response to the cache.
def store(response)
strip_ignore_headers(response)
metastore.store(@request, response, entitystore)
metastore.store(@request, response, entitystore, non_cached_headers)
response.headers['age'] = response.age.to_s
rescue => e
log_error(e)
Expand Down
3 changes: 2 additions & 1 deletion lib/rack/cache/meta_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def lookup(request, entity_store)
# Write a cache entry to the store under the given key. Existing
# entries are read and any that match the response are removed.
# This method calls #write with the new list of cache entries.
def store(request, response, entity_store)
def store(request, response, entity_store, non_cached_headers)
key = cache_key(request)
stored_env = persist_request(request)

Expand Down Expand Up @@ -97,6 +97,7 @@ def store(request, response, entity_store)

headers = persist_response(response)
headers.delete('age')
non_cached_headers.each{ |h| headers.delete(h) }

entries.unshift [stored_env, headers]
if request.env['rack-cache.use_native_ttl'] && response.fresh?
Expand Down
33 changes: 20 additions & 13 deletions lib/rack/cache/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ def option_name(key)
# Default: []
option_accessor :transfer_headers

# Set of response headers that will be passed to the client when present
# in any responses but will not be stored in cached entries.
#
# Default: []
option_accessor :non_cached_headers

# Set of request headers that trigger "private" cache-control behavior
# on responses that don't explicitly state whether the response is
# public or private via a cache-control directive. Applications that use
Expand Down Expand Up @@ -149,19 +155,20 @@ def set(option, value=self, &block)
private
def initialize_options(options={})
@default_options = {
'rack-cache.cache_key' => Key,
'rack-cache.verbose' => true,
'rack-cache.storage' => Rack::Cache::Storage.instance,
'rack-cache.metastore' => 'heap:/',
'rack-cache.entitystore' => 'heap:/',
'rack-cache.default_ttl' => 0,
'rack-cache.ignore_headers' => ['set-cookie'],
'rack-cache.transfer_headers' => [],
'rack-cache.private_headers' => ['Authorization', 'Cookie'],
'rack-cache.allow_reload' => false,
'rack-cache.allow_revalidate' => false,
'rack-cache.use_native_ttl' => false,
'rack-cache.fault_tolerant' => false,
'rack-cache.cache_key' => Key,
'rack-cache.verbose' => true,
'rack-cache.storage' => Rack::Cache::Storage.instance,
'rack-cache.metastore' => 'heap:/',
'rack-cache.entitystore' => 'heap:/',
'rack-cache.default_ttl' => 0,
'rack-cache.ignore_headers' => ['set-cookie'],
'rack-cache.transfer_headers' => [],
'rack-cache.non_cached_headers' => [],
'rack-cache.private_headers' => ['Authorization', 'Cookie'],
'rack-cache.allow_reload' => false,
'rack-cache.allow_revalidate' => false,
'rack-cache.use_native_ttl' => false,
'rack-cache.fault_tolerant' => false,
}
self.options = options
end
Expand Down
28 changes: 28 additions & 0 deletions test/context_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,34 @@
cache.trace.must_include :valid
end

it 'excludes specified headers from being cached in responses' do
count = 0
respond_with do |req,res|
count += 1
res['ETAG'] = '"12345"'
if count == 1
res['not-cached'] = '"1"'
end
res.status = (count == 1) ? 200 : 304
end

get '/', 'rack-cache.non_cached_headers' => ['not-cached']
assert app.called?
assert response.ok?
response.headers.must_include 'not-cached'
cache.trace.must_include :miss
cache.trace.must_include :store
cache.trace.wont_include :ignore

get '/', 'rack-cache.non_cached_headers' => ['not-cached']
assert app.called?
assert response.ok?
response.headers.wont_include 'not-cached'
cache.trace.must_include :stale
cache.trace.must_include :valid
cache.trace.must_include :store
end

it 'replaces cached responses when validation results in non-304 response' do
timestamp = Time.now.httpdate
count = 0
Expand Down

0 comments on commit 88e05fe

Please sign in to comment.