Module: Rack::Cache::ResponseHeaders

Includes:
Headers
Included in:
Response
Defined in:
lib/rack/cache/headers.rb

Overview

HTTP response header helper methods.

Constant Summary collapse

CACHEABLE_RESPONSE_CODES =

Status codes of responses that MAY be stored by a cache or used in reply to a subsequent request.

tools.ietf.org/html/rfc2616#section-13.4

[
  200, # OK
  203, # Non-Authoritative Information
  300, # Multiple Choices
  301, # Moved Permanently
  302, # Found
  404, # Not Found
  410  # Gone
].to_set
NOT_MODIFIED_OMIT_HEADERS =

Headers that MUST NOT be included with 304 Not Modified responses.

tools.ietf.org/html/rfc2616#section-10.3.5

%w[
  Allow
  Content-Encoding
  Content-Language
  Content-Length
  Content-Md5
  Content-Type
  Last-Modified
].to_set

Instance Method Summary collapse

Methods included from Headers

#cache_control, #cache_control=, #etag, #header?

Instance Method Details

#ageObject

The age of the response.



160
161
162
# File 'lib/rack/cache/headers.rb', line 160

def age
  [(now - date).to_i, 0].max
end

#cacheable?Boolean

Determine if the response is worth caching under any circumstance. An object that is cacheable may not necessary be served from cache without first validating the response with the origin.

An object that includes no freshness lifetime (Expires, max-age) and that does not include a validator (Last-Modified, Etag) serves no purpose in a cache that only serves fresh or valid objects.

Returns:

  • (Boolean)


117
118
119
120
121
# File 'lib/rack/cache/headers.rb', line 117

def cacheable?
  return false unless CACHEABLE_RESPONSE_CODES.include?(status)
  return false if no_store?
  validateable? || fresh?
end

#dateObject

The date, as specified by the Date header. When no Date header is present, set the Date header to Time.now and return.



150
151
152
153
154
155
156
157
# File 'lib/rack/cache/headers.rb', line 150

def date
  if date = headers['Date']
    Time.httpdate(date)
  else
    headers['Date'] = now.httpdate unless headers.frozen?
    now
  end
end

#etag_matches?(etag) ⇒ Boolean

Determine if response’s ETag matches the etag value provided. Return false when either value is nil.

Returns:

  • (Boolean)


224
225
226
# File 'lib/rack/cache/headers.rb', line 224

def etag_matches?(etag)
  etag && self.etag == etag
end

#expires_atObject

The Time when the response should be considered stale. With a Cache-Control/max-age value is present, this is calculated by adding the number of seconds specified to the responses #date value. Falls back to the time specified in the Expires header or returns nil if neither is present.



187
188
189
190
191
192
193
# File 'lib/rack/cache/headers.rb', line 187

def expires_at
  if max_age = cache_control['max-age']
    date + max_age.to_i
  elsif time = headers['Expires']
    Time.httpdate(time)
  end
end

#fresh?Boolean

Determine if the response is “fresh”. Fresh responses may be served from cache without any interaction with the origin. A response is considered fresh when it includes a Cache-Control/max-age indicator or Expiration header and the calculated age is less than the freshness lifetime.

Returns:

  • (Boolean)


100
101
102
# File 'lib/rack/cache/headers.rb', line 100

def fresh?
  ttl && ttl > 0
end

#freshness_information?Boolean

The response includes specific information about its freshness. True when a Cache-Control header with max-age value is present or when the Expires header is set.

Returns:

  • (Boolean)


126
127
128
# File 'lib/rack/cache/headers.rb', line 126

def freshness_information?
  header?('Expires') || !cache_control['max-age'].nil?
end

#last_modifiedObject

The String value of the Last-Modified header exactly as it appears in the response (i.e., no date parsing / conversion is performed).



211
212
213
# File 'lib/rack/cache/headers.rb', line 211

def last_modified
  headers['Last-Modified']
end

#last_modified_at?(time_value) ⇒ Boolean

Determine if the response was last modified at the time provided. time_value is the exact string provided in an origin response’s Last-Modified header.

Returns:

  • (Boolean)


218
219
220
# File 'lib/rack/cache/headers.rb', line 218

def last_modified_at?(time_value)
  time_value && last_modified == time_value
end

#max_ageObject

The number of seconds after the time specified in the response’s Date header when the the response should no longer be considered fresh. First check for a Cache-Control max-age value, and fall back on an expires header; return nil when no maximum age can be established.



168
169
170
171
172
173
174
# File 'lib/rack/cache/headers.rb', line 168

def max_age
  if age = cache_control['max-age']
    age.to_i
  elsif headers['Expires']
    Time.httpdate(headers['Expires']) - date
  end
end

#max_age=(value) ⇒ Object

Sets the number of seconds after which the response should no longer be considered fresh. This sets the Cache-Control max-age value.



178
179
180
# File 'lib/rack/cache/headers.rb', line 178

def max_age=(value)
  self.cache_control = cache_control.merge('max-age' => value.to_s)
end

#no_cache?Boolean

Indicates that the response should not be served from cache without first revalidating with the origin. Note that this does not necessary imply that a caching agent ought not store the response in its cache.

Returns:

  • (Boolean)


139
140
141
# File 'lib/rack/cache/headers.rb', line 139

def no_cache?
  !cache_control['no-cache'].nil?
end

#no_store?Boolean

Indicates that the response should not be stored under any circumstances.

Returns:

  • (Boolean)


144
145
146
# File 'lib/rack/cache/headers.rb', line 144

def no_store?
  cache_control['no-store']
end

#not_modified!Object

Modify the response so that it conforms to the rules defined for ‘304 Not Modified’. This sets the status, removes the body, and discards any headers that MUST NOT be included in 304 responses.

tools.ietf.org/html/rfc2616#section-10.3.5



246
247
248
249
250
251
# File 'lib/rack/cache/headers.rb', line 246

def not_modified!
  self.status = 304
  self.body = []
  NOT_MODIFIED_OMIT_HEADERS.each { |name| headers.delete(name) }
  nil
end

#stale?Boolean

Determine if the response is “stale”. Stale responses must be validated with the origin before use. This is the inverse of #fresh?.

Returns:

  • (Boolean)


106
107
108
# File 'lib/rack/cache/headers.rb', line 106

def stale?
  !fresh?
end

#ttlObject

The response’s time-to-live in seconds, or nil when no freshness information is present in the response. When the responses #ttl is <= 0, the response may not be served from cache without first revalidating with the origin.



199
200
201
# File 'lib/rack/cache/headers.rb', line 199

def ttl
  max_age - age if max_age
end

#ttl=(seconds) ⇒ Object

Set the response’s time-to-live to the specified number of seconds. This adjusts the Cache-Control/max-age value.



205
206
207
# File 'lib/rack/cache/headers.rb', line 205

def ttl=(seconds)
  self.max_age = age + seconds
end

#validateable?Boolean

Determine if the response includes headers that can be used to validate the response with the origin using a conditional GET request.

Returns:

  • (Boolean)


132
133
134
# File 'lib/rack/cache/headers.rb', line 132

def validateable?
  header?('Last-Modified') || header?('Etag')
end

#varyObject

The literal value of the Vary header, or nil when no Vary header is present.



255
256
257
# File 'lib/rack/cache/headers.rb', line 255

def vary
  headers['Vary']
end

#vary?Boolean

Does the response include a Vary header?

Returns:

  • (Boolean)


260
261
262
# File 'lib/rack/cache/headers.rb', line 260

def vary?
  ! vary.nil?
end

#vary_header_namesObject

An array of header names given in the Vary header or an empty array when no Vary header is present.



266
267
268
269
# File 'lib/rack/cache/headers.rb', line 266

def vary_header_names
  return [] unless vary = headers['Vary']
  vary.split(/[\s,]+/)
end