Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convenient cache and content type methods for Rack::Response. #1555

Merged
merged 1 commit into from Feb 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/rack.rb
Expand Up @@ -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'
Expand Down
22 changes: 22 additions & 0 deletions lib/rack/response.rb
Expand Up @@ -178,10 +178,16 @@ def add_header(key, v)
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
Expand Down Expand Up @@ -228,6 +234,22 @@ def cache_control=(v)
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
Expand Down
33 changes: 33 additions & 0 deletions test/spec_response.rb
Expand Up @@ -30,6 +30,14 @@
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
Expand Down Expand Up @@ -609,6 +617,31 @@ def obj.each

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
Expand Down