summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSamuel Williams <samuel.williams@oriontransfer.co.nz>2015-09-08 17:25:56 +1200
committerSamuel Williams <samuel.williams@oriontransfer.co.nz>2020-02-05 18:16:17 +1300
commitdbced5bfaa06904ef89ad8a7d29d4605c4041062 (patch)
tree073a170f33d452d15ed1365be4074949d68e882b
parent64f53e4a8c6dce5da0b7f81c0aa6629cf926cc5a (diff)
downloadrack-dbced5bfaa06904ef89ad8a7d29d4605c4041062.tar.gz
Convenient cache and content type methods for `Rack::Response`.
-rw-r--r--lib/rack.rb1
-rw-r--r--lib/rack/response.rb22
-rw-r--r--test/spec_response.rb33
3 files changed, 56 insertions, 0 deletions
diff --git a/lib/rack.rb b/lib/rack.rb
index 7600c40f..cab2bb8b 100644
--- a/lib/rack.rb
+++ b/lib/rack.rb
@@ -27,6 +27,7 @@ module Rack
SERVER_ADDR = 'SERVER_ADDR'
SERVER_PORT = 'SERVER_PORT'
CACHE_CONTROL = 'Cache-Control'
+ EXPIRES = 'Expires'
CONTENT_LENGTH = 'Content-Length'
CONTENT_TYPE = 'Content-Type'
SET_COOKIE = 'Set-Cookie'
diff --git a/lib/rack/response.rb b/lib/rack/response.rb
index 408a38fc..fbbcb03e 100644
--- a/lib/rack/response.rb
+++ b/lib/rack/response.rb
@@ -178,10 +178,16 @@ module Rack
end
end
+ # Get the content type of the response.
def content_type
get_header CONTENT_TYPE
end
+ # Set the content type of the response.
+ def content_type=(content_type)
+ set_header CONTENT_TYPE, content_type
+ end
+
def media_type
MediaType.type(content_type)
end
@@ -228,6 +234,22 @@ module Rack
set_header CACHE_CONTROL, v
end
+ # Specifies that the content shouldn't be cached. Overrides `cache!` if already called.
+ def do_not_cache!
+ set_header CACHE_CONTROL, "no-cache, must-revalidate"
+ set_header EXPIRES, Time.now.httpdate
+ end
+
+ # Specify that the content should be cached.
+ # @param duration [Integer] The number of seconds until the cache expires.
+ # @option directive [String] The cache control directive, one of "public", "private", "no-cache" or "no-store".
+ def cache!(duration = 3600, directive: "public")
+ unless headers[CACHE_CONTROL] =~ /no-cache/
+ set_header CACHE_CONTROL, "#{directive}, max-age=#{duration}"
+ set_header EXPIRES, (Time.now + duration).httpdate
+ end
+ end
+
def etag
get_header ETAG
end
diff --git a/test/spec_response.rb b/test/spec_response.rb
index b2ba59a8..1dfafcdb 100644
--- a/test/spec_response.rb
+++ b/test/spec_response.rb
@@ -30,6 +30,14 @@ describe Rack::Response do
assert_equal etag, response.to_a[1]['ETag']
end
+ it 'has a content-type method' do
+ response = Rack::Response.new
+ content_type = 'foo'
+ response.content_type = content_type
+ assert_equal content_type, response.content_type
+ assert_equal content_type, response.to_a[1]['Content-Type']
+ end
+
it "have sensible default values" do
response = Rack::Response.new
status, header, body = response.finish
@@ -609,6 +617,31 @@ describe Rack::Response do
res.finish.flatten.must_be_kind_of(Array)
end
+
+ it "should specify not to cache content" do
+ response = Rack::Response.new
+
+ response.cache!(1000)
+ response.do_not_cache!
+
+ expect(response['Cache-Control']).must_equal "no-cache, must-revalidate"
+
+ expires_header = Time.parse(response['Expires'])
+ expect(expires_header).must_be :<=, Time.now
+ end
+
+ it "should specify to cache content" do
+ response = Rack::Response.new
+
+ duration = 120
+ expires = Time.now + 100 # At least this far into the future
+ response.cache!(duration)
+
+ expect(response['Cache-Control']).must_equal "public, max-age=120"
+
+ expires_header = Time.parse(response['Expires'])
+ expect(expires_header).must_be :>=, expires
+ end
end
describe Rack::Response, 'headers' do