Implement http_cache_forever to ActionController #18394

Merged
merged 1 commit into from Feb 15, 2015

Conversation

Projects
None yet
5 participants
@arthurnn
Member

arthurnn commented Jan 8, 2015

Add http_cache_forever to ActionController, so we can cache results
forever.
Things like static pages are a good candidate for this type of caching.

This cache only controls caching headers, so it is up to the browser to
cache those requests.

First stab at #18192

@dhh @rafaelfranca @sgrif thoughts?

@dhh

This comment has been minimized.

Show comment
Hide comment
@dhh

dhh Jan 8, 2015

Member

Lovely! Need a CHANGELOG entry as well.

Member

dhh commented Jan 8, 2015

Lovely! Need a CHANGELOG entry as well.

@arthurnn

This comment has been minimized.

Show comment
Hide comment
@arthurnn

arthurnn Jan 10, 2015

Member

@dhh Changelog ✔️

Member

arthurnn commented Jan 10, 2015

@dhh Changelog ✔️

@@ -46,6 +46,20 @@ def cache_configured?
end
end
+ # Cache or yield the block. The cache is suppose to never expire.

This comment has been minimized.

@jeremy

jeremy Jan 10, 2015

Member

This needs to communicate why you'd reach for this method and what it does. You have an HTTP response that never changes, so you want browsers and proxies to cache it indefinitely. On the first hit, we serve the response with long-lived cache freshness response headers. Then subsequent requests will always revalidate as fresh.

This method belongs elsewhere, too. This module is concerned with caching within the app (fragments, template dependencies, etc) not HTTP cache freshness.

@jeremy

jeremy Jan 10, 2015

Member

This needs to communicate why you'd reach for this method and what it does. You have an HTTP response that never changes, so you want browsers and proxies to cache it indefinitely. On the first hit, we serve the response with long-lived cache freshness response headers. Then subsequent requests will always revalidate as fresh.

This method belongs elsewhere, too. This module is concerned with caching within the app (fragments, template dependencies, etc) not HTTP cache freshness.

+ last_modified: Time.parse('2011-01-01').utc,
+ public: public)
+ end
+

This comment has been minimized.

@jeremy

jeremy Jan 10, 2015

Member

We can use Last-Modified alone. It's a weak validator (implies semantic equivalence) whereas the ETag is a strong validator (implies byte-for-byte equivalence) which may not be true. We can drop the version arg then.

@jeremy

jeremy Jan 10, 2015

Member

We can use Last-Modified alone. It's a weak validator (implies semantic equivalence) whereas the ETag is a strong validator (implies byte-for-byte equivalence) which may not be true. We can drop the version arg then.

This comment has been minimized.

@arthurnn

arthurnn Jan 20, 2015

Member

we need the etag too so we can bust the cache adding a new version, see my test case test_cache_response_code_with_etag .

@arthurnn

arthurnn Jan 20, 2015

Member

we need the etag too so we can bust the cache adding a new version, see my test case test_cache_response_code_with_etag .

This comment has been minimized.

@jeremy

jeremy Feb 9, 2015

Member

Sounds good. We can just switch to weak ETags when we implement them.

@jeremy

jeremy Feb 9, 2015

Member

Sounds good. We can just switch to weak ETags when we implement them.

+ #
+ # <tt>version</tt> is the version passed as a key for the cache.
+ def http_cache_forever(public: false, version: 'v1')
+ expires_in 100.years, public: public

This comment has been minimized.

@jeremy

jeremy Jan 10, 2015

Member

Do any browsers or proxies have issues parsing dates this far in the future? e.g. http://en.wikipedia.org/wiki/Year_2038_problem

@jeremy

jeremy Jan 10, 2015

Member

Do any browsers or proxies have issues parsing dates this far in the future? e.g. http://en.wikipedia.org/wiki/Year_2038_problem

+ # Cache or yield the block. The cache is suppose to never expire.
+ #
+ # <tt>public</tt> By default the Cache-Control header is private, set this to
+ # +true+ if you want your application to be cachable by other devices (proxy caches).

This comment has been minimized.

@jeremy

jeremy Jan 10, 2015

Member

By default, HTTP responses are private, cached only on the user's web browser. To allow proxies to cache the response, set public: true to indicate that they can serve the cached response to all users.

@jeremy

jeremy Jan 10, 2015

Member

By default, HTTP responses are private, cached only on the user's web browser. To allow proxies to cache the response, set public: true to indicate that they can serve the cached response to all users.

This comment has been minimized.

@arthurnn

arthurnn Jan 20, 2015

Member

done

+ assert_equal "max-age=#{100.years.to_i}, private", @response.headers["Cache-Control"]
+ assert_not_nil @response.etag
+ end
+end

This comment has been minimized.

@jeremy

jeremy Jan 10, 2015

Member

This tests that a request without cache freshness headers results in a response with headers properly set. These should assert 200 OK responses and additionally test that requests with cache freshness headers result in 304 Not Modified responses.

@jeremy

jeremy Jan 10, 2015

Member

This tests that a request without cache freshness headers results in a response with headers properly set. These should assert 200 OK responses and additionally test that requests with cache freshness headers result in 304 Not Modified responses.

This comment has been minimized.

@arthurnn

arthurnn Jan 20, 2015

Member

Done, please check it out the last commit

@arthurnn

arthurnn Jan 20, 2015

Member

Done, please check it out the last commit

actionpack/CHANGELOG.md
@@ -1,3 +1,7 @@
+* Add http_cache_forever to ActionController, so we can cache results that won't expire.

This comment has been minimized.

@jeremy

jeremy Jan 10, 2015

Member

s/ActionController/Action Controller
s/results that won't/responses that never

@jeremy

jeremy Jan 10, 2015

Member

s/ActionController/Action Controller
s/results that won't/responses that never

This comment has been minimized.

@arthurnn

arthurnn Jan 20, 2015

Member

done

@arthurnn

This comment has been minimized.

Show comment
Hide comment
@arthurnn

arthurnn Jan 20, 2015

Member

@jeremy I addressed most of your concerns, just leaving the where this should be still for decision. Let me know your thoughts. thanks

Member

arthurnn commented Jan 20, 2015

@jeremy I addressed most of your concerns, just leaving the where this should be still for decision. Let me know your thoughts. thanks

+ expires_in 100.years, public: public
+
+ yield if stale?(etag: "#{version}-#{request.fullpath}",
+ last_modified: Time.parse('2011-01-01').utc,

This comment has been minimized.

@andyatkinson

andyatkinson Jan 28, 2015

Contributor

What was the significance of this date (curious)? Thanks.

@andyatkinson

andyatkinson Jan 28, 2015

Contributor

What was the significance of this date (curious)? Thanks.

This comment has been minimized.

@arthurnn

arthurnn Jan 28, 2015

Member

this is just a date on the past. But now I wonder if the last_modifed is necessary at all. I guess we could use only the etag, as that one has the version. Not 100% sure tho, as this is the opposite what @jeremy said in the comment above.. lets wait for him on this.

@arthurnn

arthurnn Jan 28, 2015

Member

this is just a date on the past. But now I wonder if the last_modifed is necessary at all. I guess we could use only the etag, as that one has the version. Not 100% sure tho, as this is the opposite what @jeremy said in the comment above.. lets wait for him on this.

@andyatkinson

This comment has been minimized.

Show comment
Hide comment
@andyatkinson

andyatkinson Jan 28, 2015

Contributor

@arthurnn I worked on a PR but then I realized yours was much further along. I fetched yours, ran the tests, and read through them. Looks good! 👍

Contributor

andyatkinson commented Jan 28, 2015

@arthurnn I worked on a PR but then I realized yours was much further along. I fetched yours, ran the tests, and read through them. Looks good! 👍

@dhh

This comment has been minimized.

Show comment
Hide comment
@dhh

dhh Feb 8, 2015

Member

@jeremy Can you give this a final look over? Seems like we're just about ready for a merge.

Member

dhh commented Feb 8, 2015

@jeremy Can you give this a final look over? Seems like we're just about ready for a merge.

@arthurnn

This comment has been minimized.

Show comment
Hide comment
@arthurnn

arthurnn Feb 9, 2015

Member

@jeremy let me know your thoughts, I can fix/rebase/merge this when you fell this is ready!

Member

arthurnn commented Feb 9, 2015

@jeremy let me know your thoughts, I can fix/rebase/merge this when you fell this is ready!

@jeremy

This comment has been minimized.

Show comment
Hide comment
@jeremy

jeremy Feb 9, 2015

Member

🚢

Member

jeremy commented Feb 9, 2015

🚢

@kaspth

This comment has been minimized.

Show comment
Hide comment
@kaspth

kaspth Feb 14, 2015

Member

@arthurnn just a reminder that you're also working on this and need to rebase 😄

Member

kaspth commented Feb 14, 2015

@arthurnn just a reminder that you're also working on this and need to rebase 😄

@arthurnn

This comment has been minimized.

Show comment
Hide comment
@arthurnn

arthurnn Feb 15, 2015

Member

merging this today, after breakfast =)

Member

arthurnn commented Feb 15, 2015

merging this today, after breakfast =)

Implement http_cache_forever to ActionController
Add http_cache_forever to ActionController, so we can cache results
forever.
Things like static pages are a good candidate for this type of caching.

This cache only controls caching headers, so it is up to the browser to
cache those requests.

arthurnn added a commit that referenced this pull request Feb 15, 2015

Merge pull request #18394 from arthurnn/http_cache_forever
Implement http_cache_forever to ActionController

@arthurnn arthurnn merged commit e825042 into rails:master Feb 15, 2015

1 check passed

continuous-integration/travis-ci The Travis CI build passed
Details

@arthurnn arthurnn deleted the arthurnn:http_cache_forever branch Feb 15, 2015

@kaspth

This comment has been minimized.

Show comment
Hide comment
@kaspth

kaspth Feb 15, 2015

Member

forever ❤️

Member

kaspth commented Feb 15, 2015

forever ❤️

@arthurnn

This comment has been minimized.

Show comment
Hide comment
@arthurnn

arthurnn Feb 15, 2015

Member

🎉 😸

Member

arthurnn commented Feb 15, 2015

🎉 😸

@dhh

This comment has been minimized.

Show comment
Hide comment
@dhh

dhh Feb 15, 2015

Member

Boom! 🤘

Member

dhh commented Feb 15, 2015

Boom! 🤘

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment