Module: Controllers::CloudflareCaching
- Extended by:
- ActiveSupport::Concern
- Included in:
- ApplicationController
- Defined in:
- app/concerns/controllers/cloudflare_caching.rb
Overview
Cloudflare CDN caching utilities for edge caching
Usage:
1. Declare which actions are edge-cached (prevents ghost guest creation):
edge_cached # all actions
edge_cached only: %i[index show] # specific actions
2. In the controller action, set cache params:
set_cloudflare_cache(time_in_secs: 1.week.to_i, tags: ['product-123'])
To bust cache on error:
reset_cloudflare_cache
Why edge_cached matters:
Edge-cached pages skip the session cookie (Set-Cookie header) so Cloudflare
can cache them. Without edge_cached, init_current_user creates a guest user
in the database, then skip_session discards the session -- orphaning the guest.
This causes "ghost guest" proliferation.
Class Method Summary collapse
-
.edge_cached(only: nil) ⇒ Object
Declare actions as edge-cacheable.
Instance Method Summary collapse
-
#edge_cached_action? ⇒ Boolean
Returns true if the current action was declared via edge_cached.
- #reset_cloudflare_cache ⇒ Object
-
#set_cloudflare_cache(time_in_secs: 3.days.to_i, stale_time_in_secs: 1.day.to_i, public_cache_expires_in: 3.days, tags: nil) ⇒ Object
Applies headers for caching specifically for cloudflare's edge.
-
#skip_session ⇒ Object
For some static content, we don't need to track the session This helps with picky CDNs throwing off the cache if a cookie is present.
Class Method Details
.edge_cached(only: nil) ⇒ Object
Declare actions as edge-cacheable. This automatically skips init_current_user
to prevent ghost guest creation on pages served from Cloudflare's CDN.
44 45 46 47 48 49 50 51 52 |
# File 'app/concerns/controllers/cloudflare_caching.rb', line 44 def edge_cached(only: nil) if only skip_before_action :init_current_user, only: only self._edge_cached_actions = Array(only).map(&:to_s).to_set.freeze else skip_before_action :init_current_user self._edge_cached_actions = :all end end |
Instance Method Details
#edge_cached_action? ⇒ Boolean
Returns true if the current action was declared via edge_cached
56 57 58 59 60 61 62 |
# File 'app/concerns/controllers/cloudflare_caching.rb', line 56 def edge_cached_action? config = self.class._edge_cached_actions return false if config.nil? return true if config == :all config.include?(action_name) end |
#reset_cloudflare_cache ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'app/concerns/controllers/cloudflare_caching.rb', line 84 def reset_cloudflare_cache return unless response # Remove all Cloudflare-specific cache headers response.delete_header('Cloudflare-CDN-Cache-Control') response.delete_header('Cache-Tag') # Explicitly tell Cloudflare to NOT cache this response # This prevents edge caching of error pages even if other headers suggest caching response.set_header('Cloudflare-CDN-Cache-Control', 'no-store') # Also prevent browser caching expires_now @edge_cached = false end |
#set_cloudflare_cache(time_in_secs: 3.days.to_i, stale_time_in_secs: 1.day.to_i, public_cache_expires_in: 3.days, tags: nil) ⇒ Object
Applies headers for caching specifically for cloudflare's edge
69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'app/concerns/controllers/cloudflare_caching.rb', line 69 def set_cloudflare_cache(time_in_secs: 3.days.to_i, stale_time_in_secs: 1.day.to_i, public_cache_expires_in: 3.days, tags: nil) return unless response && response.ok? warn_if_not_edge_cached expires_in public_cache_expires_in, public: true skip_session # Necessary otherwise you will not get the benefit of this method cdn_cache_controls = [] cdn_cache_controls << "max-age=#{time_in_secs}" cdn_cache_controls << "stale-if-error=#{stale_time_in_secs}" response.set_header('Cloudflare-CDN-Cache-Control', cdn_cache_controls.join(',')) response.set_header('Cache-Tag', .join(',')) if .present? @edge_cached = true end |
#skip_session ⇒ Object
For some static content, we don't need to track the session
This helps with picky CDNs throwing off the cache if a cookie is present
103 104 105 |
# File 'app/concerns/controllers/cloudflare_caching.rb', line 103 def skip_session request.[:skip] = true end |