aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2008-07-16 04:32:15 -0700
committerJeremy Kemper <jeremy@bitsweat.net>2008-07-17 23:18:10 -0700
commit57a2780f14447152ece1b1301fc6c25b2ec43da5 (patch)
tree461185af231d685c355cc18b3e69584228dc1173 /actionpack/lib/action_controller
parenta1fcbd971d681e44de5ea33e6a8470ff8b8144c0 (diff)
downloadrails-57a2780f14447152ece1b1301fc6c25b2ec43da5.tar.gz
rails-57a2780f14447152ece1b1301fc6c25b2ec43da5.tar.bz2
rails-57a2780f14447152ece1b1301fc6c25b2ec43da5.zip
etag! and last_modified! conditional GET helpers
Diffstat (limited to 'actionpack/lib/action_controller')
-rwxr-xr-xactionpack/lib/action_controller/base.rb15
-rwxr-xr-xactionpack/lib/action_controller/response.rb40
2 files changed, 47 insertions, 8 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index c56812c2d9..50727c67c4 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -519,6 +519,8 @@ module ActionController #:nodoc:
public
# Extracts the action_name from the request parameters and performs that action.
def process(request, response, method = :perform_action, *arguments) #:nodoc:
+ response.request = request
+
initialize_template_class(response)
assign_shortcuts(request, response)
initialize_current_url
@@ -529,8 +531,6 @@ module ActionController #:nodoc:
send(method, *arguments)
assign_default_content_type_and_charset
-
- response.request = request
response.prepare! unless component_request?
response
ensure
@@ -968,6 +968,17 @@ module ActionController #:nodoc:
render :nothing => true, :status => status
end
+ # Sets the Last-Modified response header. Returns 304 Not Modified if the
+ # If-Modified-Since request header is <= last modified.
+ def last_modified!(utc_time)
+ head(:not_modified) if response.last_modified!(utc_time)
+ end
+
+ # Sets the ETag response header. Returns 304 Not Modified if the
+ # If-None-Match request header matches.
+ def etag!(etag)
+ head(:not_modified) if response.etag!(etag)
+ end
# Clears the rendered results, allowing for another render to be performed.
def erase_render_results #:nodoc:
diff --git a/actionpack/lib/action_controller/response.rb b/actionpack/lib/action_controller/response.rb
index 1d9f6676ba..9955532844 100755
--- a/actionpack/lib/action_controller/response.rb
+++ b/actionpack/lib/action_controller/response.rb
@@ -41,20 +41,48 @@ module ActionController
set_content_length!
end
+ # Sets the Last-Modified response header. Returns whether it's older than
+ # the If-Modified-Since request header.
+ def last_modified!(utc_time)
+ headers['Last-Modified'] ||= utc_time.httpdate
+ if request && since = request.headers['HTTP_IF_MODIFIED_SINCE']
+ utc_time <= Time.rfc2822(since)
+ end
+ end
+
+ # Sets the ETag response header. Returns whether it matches the
+ # If-None-Match request header.
+ def etag!(tag)
+ headers['ETag'] ||= %("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key(tag))}")
+ if request && request.headers['HTTP_IF_NONE_MATCH'] == headers['ETag']
+ true
+ end
+ end
private
def handle_conditional_get!
- if body.is_a?(String) && (headers['Status'] ? headers['Status'][0..2] == '200' : true) && !body.empty?
- self.headers['ETag'] ||= %("#{Digest::MD5.hexdigest(body)}")
- self.headers['Cache-Control'] = 'private, max-age=0, must-revalidate' if headers['Cache-Control'] == DEFAULT_HEADERS['Cache-Control']
+ if nonempty_ok_response?
+ set_conditional_cache_control!
- if request.headers['HTTP_IF_NONE_MATCH'] == headers['ETag']
- self.headers['Status'] = '304 Not Modified'
+ if etag!(body)
+ headers['Status'] = '304 Not Modified'
self.body = ''
end
end
end
+ def nonempty_ok_response?
+ status = headers['Status']
+ ok = !status || status[0..2] == '200'
+ ok && body.is_a?(String) && !body.empty?
+ end
+
+ def set_conditional_cache_control!
+ if headers['Cache-Control'] == DEFAULT_HEADERS['Cache-Control']
+ headers['Cache-Control'] = 'private, max-age=0, must-revalidate'
+ end
+ end
+
def convert_content_type!
if content_type = headers.delete("Content-Type")
self.headers["type"] = content_type
@@ -73,4 +101,4 @@ module ActionController
self.headers["Content-Length"] = body.size unless body.respond_to?(:call)
end
end
-end \ No newline at end of file
+end