1 2 3 4 5 6 7 8 9 10 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 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
|
# frozen_string_literal: true
# Released under the MIT License.
# Copyright, 2020-2025, by Samuel Williams.
# Copyright, 2023, by Thomas Morgan.
require_relative "split"
module Protocol
module HTTP
module Header
# Represents the `cache-control` header, which is a list of cache directives.
class CacheControl < Split
# The `private` directive indicates that the response is intended for a single user and must not be stored by shared caches.
PRIVATE = "private"
# The `public` directive indicates that the response may be stored by any cache, even if it would normally be considered non-cacheable.
PUBLIC = "public"
# The `no-cache` directive indicates that caches must revalidate the response with the origin server before serving it to clients.
NO_CACHE = "no-cache"
# The `no-store` directive indicates that caches must not store the response under any circumstances.
NO_STORE = "no-store"
# The `max-age` directive indicates the maximum amount of time, in seconds, that a response is considered fresh.
MAX_AGE = "max-age"
# The `s-maxage` directive is similar to `max-age` but applies only to shared caches. If both `s-maxage` and `max-age` are present, `s-maxage` takes precedence in shared caches.
S_MAXAGE = "s-maxage"
# The `static` directive is a custom directive often used to indicate that the resource is immutable or rarely changes, allowing longer caching periods.
STATIC = "static"
# The `dynamic` directive is a custom directive used to indicate that the resource is generated dynamically and may change frequently, requiring shorter caching periods.
DYNAMIC = "dynamic"
# The `streaming` directive is a custom directive used to indicate that the resource is intended for progressive or chunked delivery, such as live video streams.
STREAMING = "streaming"
# The `must-revalidate` directive indicates that once a response becomes stale, caches must not use it to satisfy subsequent requests without revalidating it with the origin server.
MUST_REVALIDATE = "must-revalidate"
# The `proxy-revalidate` directive is similar to `must-revalidate` but applies only to shared caches.
PROXY_REVALIDATE = "proxy-revalidate"
# Initializes the cache control header with the given value. The value is expected to be a comma-separated string of cache directives.
#
# @parameter value [String | Nil] the raw Cache-Control header value.
def initialize(value = nil)
super(value&.downcase)
end
# Adds a directive to the Cache-Control header. The value will be normalized to lowercase before being added.
#
# @parameter value [String] the directive to add.
def << value
super(value.downcase)
end
# @returns [Boolean] whether the `static` directive is present.
def static?
self.include?(STATIC)
end
# @returns [Boolean] whether the `dynamic` directive is present.
def dynamic?
self.include?(DYNAMIC)
end
# @returns [Boolean] whether the `streaming` directive is present.
def streaming?
self.include?(STREAMING)
end
# @returns [Boolean] whether the `private` directive is present.
def private?
self.include?(PRIVATE)
end
# @returns [Boolean] whether the `public` directive is present.
def public?
self.include?(PUBLIC)
end
# @returns [Boolean] whether the `no-cache` directive is present.
def no_cache?
self.include?(NO_CACHE)
end
# @returns [Boolean] whether the `no-store` directive is present.
def no_store?
self.include?(NO_STORE)
end
# @returns [Boolean] whether the `must-revalidate` directive is present.
def must_revalidate?
self.include?(MUST_REVALIDATE)
end
# @returns [Boolean] whether the `proxy-revalidate` directive is present.
def proxy_revalidate?
self.include?(PROXY_REVALIDATE)
end
# @returns [Integer | Nil] the value of the `max-age` directive in seconds, or `nil` if the directive is not present or invalid.
def max_age
find_integer_value(MAX_AGE)
end
# @returns [Integer | Nil] the value of the `s-maxage` directive in seconds, or `nil` if the directive is not present or invalid.
def s_maxage
find_integer_value(S_MAXAGE)
end
private
# Finds and parses an integer value from a directive.
#
# @parameter value_name [String] the directive name to search for (e.g., "max-age").
# @returns [Integer | Nil] the parsed integer value, or `nil` if not found or invalid.
def find_integer_value(value_name)
if value = self.find{|value| value.start_with?(value_name)}
_, age = value.split("=", 2)
if age =~ /\A[0-9]+\z/
return Integer(age)
end
end
end
end
end
end
end
|