Module: Otto::ResponseHelpers
- Includes:
- BaseHelpers
- Defined in:
- lib/otto/helpers/response.rb
Instance Attribute Summary collapse
-
#request ⇒ Object
Returns the value of attribute request.
Instance Method Summary collapse
- #cookie_security_headers ⇒ Object
-
#no_cache! ⇒ void
Set cache control headers to prevent caching.
-
#send_csp_headers(content_type, nonce, opts = {}) ⇒ void
Set Content Security Policy (CSP) headers with nonce support.
- #send_secure_cookie(name, value, ttl, opts = {}) ⇒ Object
- #send_session_cookie(name, value, opts = {}) ⇒ Object
Methods included from BaseHelpers
Instance Attribute Details
#request ⇒ Object
Returns the value of attribute request.
9 10 11 |
# File 'lib/otto/helpers/response.rb', line 9 def request @request end |
Instance Method Details
#cookie_security_headers ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/otto/helpers/response.rb', line 65 def # Add security headers that complement cookie security headers = {} # Prevent MIME type sniffing headers['x-content-type-options'] = 'nosniff' # Add referrer policy headers['referrer-policy'] = 'strict-origin-when-cross-origin' # Add frame options headers['x-frame-options'] = 'DENY' # Add XSS protection headers['x-xss-protection'] = '1; mode=block' headers end |
#no_cache! ⇒ void
This method returns an undefined value.
Set cache control headers to prevent caching
This method sets comprehensive cache control headers to ensure that the response is not cached by browsers, proxies, or CDNs. This is particularly useful for sensitive pages or dynamic content that should always be fresh.
149 150 151 152 153 |
# File 'lib/otto/helpers/response.rb', line 149 def no_cache! headers['cache-control'] = 'no-store, no-cache, must-revalidate, max-age=0' headers['expires'] = 'Mon, 7 Nov 2011 00:00:00 UTC' headers['pragma'] = 'no-cache' end |
#send_csp_headers(content_type, nonce, opts = {}) ⇒ void
This method returns an undefined value.
Set Content Security Policy (CSP) headers with nonce support
This method generates and sets CSP headers with the provided nonce value, following the same usage pattern as send_cookie methods. The CSP policy is generated dynamically based on the security configuration and environment.
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/otto/helpers/response.rb', line 107 def send_csp_headers(content_type, nonce, opts = {}) # Set content type if not already set headers['content-type'] ||= content_type # Warn if CSP header already exists but don't skip if headers['content-security-policy'] warn 'CSP header already set, overriding with nonce-based policy' end # Get security configuration security_config = opts[:security_config] || (request&.env && request.env['otto.security_config']) || nil # Skip if CSP nonce support is not enabled return unless security_config&.csp_nonce_enabled? # Generate CSP policy with nonce development_mode = opts[:development_mode] || false csp_policy = security_config.generate_nonce_csp(nonce, development_mode: development_mode) # Debug logging if enabled debug_enabled = opts[:debug] || security_config.debug_csp? if debug_enabled && defined?(Otto.logger) Otto.logger.debug "[CSP] #{csp_policy}" end # Set the CSP header headers['content-security-policy'] = csp_policy end |
#send_secure_cookie(name, value, ttl, opts = {}) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/otto/helpers/response.rb', line 11 def (name, value, ttl, opts = {}) # Default security options defaults = { secure: true, httponly: true, same_site: :strict, path: '/', } # Merge with provided options = defaults.merge(opts) # Set expiration using max-age (preferred) and expires (fallback) if ttl&.positive? [:max_age] = ttl [:expires] = (Time.now.utc + ttl + 10) elsif ttl&.negative? # For deletion, set both to past date [:max_age] = 0 [:expires] = Time.now.utc - 86_400 end # Set the cookie value [:value] = value # Validate SameSite attribute valid_same_site = [:strict, :lax, :none, 'Strict', 'Lax', 'None'] [:same_site] = :strict unless valid_same_site.include?([:same_site]) # If SameSite=None, Secure must be true [:secure] = true if [:same_site].to_s.downcase == 'none' name, end |
#send_session_cookie(name, value, opts = {}) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/otto/helpers/response.rb', line 46 def (name, value, opts = {}) # Session cookies don't have expiration session_opts = opts.merge( secure: true, httponly: true, samesite: :strict, ) # Remove expiration-related options for session cookies session_opts.delete(:max_age) session_opts.delete(:expires) # Adjust secure flag for local development session_opts[:secure] = false if request.local? session_opts[:value] = value name, session_opts end |