Module: Grape::App::Helpers::Caching
- Defined in:
- lib/grape/app/helpers/caching.rb
Overview
Caching support for Grape. “Borrowed” from [Ruby on Rails](github.com/rails/rails/blob/66cabeda2c46c582d19738e1318be8d59584cc5b/actionpack/lib/action_controller/metal/conditional_get.rb)
Instance Method Summary collapse
- #cache_control(max_age: nil, no_cache: false, public: false, must_revalidate: false, stale_while_revalidate: nil, stale_if_error: nil, extras: nil) ⇒ Object
-
#expires_in(seconds, public: false, must_revalidate: false, stale_while_revalidate: nil, stale_if_error: nil, extras: {}) ⇒ Object
Sets an HTTP 1.1 Cache-Control header.
-
#expires_now(public: false) ⇒ Object
Sets an HTTP 1.1 Cache-Control header of ‘no-cache`.
-
#fresh_when(object = nil, etag: nil, last_modified: nil, last_modified_field: :updated_at, **cache_control) ⇒ Object
Sets the ‘etag`, or `last_modified`, or both on the response and renders a “304 Not Modified” response if the request is already fresh.
-
#stale?(object = nil, **freshness_opts) ⇒ Boolean
Sets the ‘etag` and/or `last_modified` on the response and checks it against the client request.
Instance Method Details
#cache_control(max_age: nil, no_cache: false, public: false, must_revalidate: false, stale_while_revalidate: nil, stale_if_error: nil, extras: nil) ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/grape/app/helpers/caching.rb', line 88 def cache_control(max_age: nil, no_cache: false, public: false, must_revalidate: false, stale_while_revalidate: nil, stale_if_error: nil, extras: nil) extras = extras.map {|k, v| "#{k}=#{v}" } if extras.is_a?(Hash) opts = [] if no_cache opts << 'public' if public opts << 'no-cache' else opts << "max-age=#{max_age.to_i}" if max_age opts << (public ? 'public' : 'private') opts << 'must-revalidate' if must_revalidate opts << "stale-while-revalidate=#{stale_while_revalidate.to_i}" if stale_while_revalidate opts << "stale-if-error=#{stale_if_error.to_i}" if stale_if_error end opts.concat(extras) if extras header 'Cache-Control', opts.join(', ') end |
#expires_in(seconds, public: false, must_revalidate: false, stale_while_revalidate: nil, stale_if_error: nil, extras: {}) ⇒ Object
Sets an HTTP 1.1 Cache-Control header. Defaults to ‘private`.
This method will overwrite an existing Cache-Control header. See www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities.
The method will also ensure an HTTP Date header for client compatibility.
68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/grape/app/helpers/caching.rb', line 68 def expires_in(seconds, public: false, must_revalidate: false, stale_while_revalidate: nil, stale_if_error: nil, extras: {}) header 'Date', Time.now.httpdate cache_control( max_age: seconds, public: public, must_revalidate: must_revalidate, stale_while_revalidate: stale_while_revalidate, stale_if_error: stale_if_error, extras: extras, ) end |
#expires_now(public: false) ⇒ Object
Sets an HTTP 1.1 Cache-Control header of ‘no-cache`. This means the resource will be marked as stale, so clients must always revalidate. Intermediate/browser caches may still store the asset.
84 85 86 |
# File 'lib/grape/app/helpers/caching.rb', line 84 def expires_now(public: false) cache_control(no_cache: true, public: public) end |
#fresh_when(object = nil, etag: nil, last_modified: nil, last_modified_field: :updated_at, **cache_control) ⇒ Object
Sets the ‘etag`, or `last_modified`, or both on the response and renders a “304 Not Modified” response if the request is already fresh.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/grape/app/helpers/caching.rb', line 20 def fresh_when(object = nil, etag: nil, last_modified: nil, last_modified_field: :updated_at, **cache_control) etag ||= object last_modified = object.try(last_modified_field) || object.try(:maximum, last_modified_field) if last_modified.nil? etag = ActiveSupport::Digest.hexdigest(ActiveSupport::Cache.(etag)) header 'ETag', etag header 'Last-Modified', last_modified.httpdate if last_modified cache_control(**cache_control) unless cache_control.empty? if_modified_since = headers['if-modified-since'] if_modified_since = Time.rfc2822(if_modified_since) rescue nil if if_modified_since # rubocop:disable Style/RescueModifier if_none_match = headers['if-none-match'] return unless if_modified_since || if_none_match fresh = true fresh &&= last_modified && if_modified_since >= last_modified if if_modified_since fresh &&= if_none_match == etag if if_none_match error! 'Not Modified', 304 if fresh end |
#stale?(object = nil, **freshness_opts) ⇒ Boolean
Sets the ‘etag` and/or `last_modified` on the response and checks it against the client request. If the request doesn’t match the options provided, the request is considered stale and should be generated from scratch. Otherwise, it’s fresh and we don’t need to generate anything and reply with ‘304 Not Modified`.
@example:
get '/articles/:id' do
article = Article.find(params[:id])
stats = article.really_expensive_call if stale?(article)
end
51 52 53 54 |
# File 'lib/grape/app/helpers/caching.rb', line 51 def stale?(object = nil, **freshness_opts) fresh_when(object, **freshness_opts) true end |