aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/http/cache.rb
diff options
context:
space:
mode:
Diffstat (limited to 'actionpack/lib/action_dispatch/http/cache.rb')
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb60
1 files changed, 49 insertions, 11 deletions
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index 5ee4c044ea..0d6015d993 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -1,4 +1,3 @@
-require 'active_support/core_ext/object/blank'
module ActionDispatch
module Http
@@ -18,12 +17,21 @@ module ActionDispatch
env[HTTP_IF_NONE_MATCH]
end
+ def if_none_match_etags
+ (if_none_match ? if_none_match.split(/\s*,\s*/) : []).collect do |etag|
+ etag.gsub(/^\"|\"$/, "")
+ end
+ end
+
def not_modified?(modified_at)
if_modified_since && modified_at && if_modified_since >= modified_at
end
def etag_matches?(etag)
- if_none_match && if_none_match == etag
+ if etag
+ etag = etag.gsub(/^\"|\"$/, "")
+ if_none_match_etags.include?(etag)
+ end
end
# Check response freshness (Last-Modified and ETag) against request
@@ -84,17 +92,37 @@ module ActionDispatch
LAST_MODIFIED = "Last-Modified".freeze
ETAG = "ETag".freeze
CACHE_CONTROL = "Cache-Control".freeze
+ SPESHUL_KEYS = %w[extras no-cache max-age public must-revalidate]
- def prepare_cache_control!
- @cache_control = {}
- @etag = self[ETAG]
-
+ def cache_control_segments
if cache_control = self[CACHE_CONTROL]
- cache_control.split(/,\s*/).each do |segment|
- first, last = segment.split("=")
- @cache_control[first.to_sym] = last || true
+ cache_control.delete(' ').split(',')
+ else
+ []
+ end
+ end
+
+ def cache_control_headers
+ cache_control = {}
+
+ cache_control_segments.each do |segment|
+ directive, argument = segment.split('=', 2)
+
+ if SPESHUL_KEYS.include? directive
+ key = directive.tr('-', '_')
+ cache_control[key.to_sym] = argument || true
+ else
+ cache_control[:extras] ||= []
+ cache_control[:extras] << segment
end
end
+
+ cache_control
+ end
+
+ def prepare_cache_control!
+ @cache_control = cache_control_headers
+ @etag = self[ETAG]
end
def handle_conditional_get!
@@ -110,14 +138,24 @@ module ActionDispatch
MUST_REVALIDATE = "must-revalidate".freeze
def set_conditional_cache_control!
- return if self[CACHE_CONTROL].present?
+ control = {}
+ cc_headers = cache_control_headers
+ if extras = cc_headers.delete(:extras)
+ @cache_control[:extras] ||= []
+ @cache_control[:extras] += extras
+ @cache_control[:extras].uniq!
+ end
- control = @cache_control
+ control.merge! cc_headers
+ control.merge! @cache_control
if control.empty?
headers[CACHE_CONTROL] = DEFAULT_CACHE_CONTROL
elsif control[:no_cache]
headers[CACHE_CONTROL] = NO_CACHE
+ if control[:extras]
+ headers[CACHE_CONTROL] += ", #{control[:extras].join(', ')}"
+ end
else
extras = control[:extras]
max_age = control[:max_age]