Class Rack::Cache::Response

  1. lib/rack/cache/response.rb
Parent: Object

Provides access to the response generated by the downstream application. The response, original_response, and entry objects exposed by the Core caching engine are instances of this class.

Response objects respond to a variety of convenience methods, including those defined in Rack::Response::Helpers, Rack::Cache::Headers, and Rack::Cache::ResponseHeaders.

Note that Rack::Cache::Response is not a subclass of Rack::Response and does not perform many of the same initialization and finalization tasks. For example, the body is not slurped during initialization and there are no facilities for generating response output.

Included modules

  1. Rack::Response::Helpers

Constants

CACHEABLE_RESPONSE_CODES = [ 200, # OK 203, # Non-Authoritative Information 300, # Multiple Choices 301, # Moved Permanently 302, # Found 404, # Not Found 410 # Gone ].to_set   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

NOT_MODIFIED_OMIT_HEADERS = %w[ Allow Content-Encoding Content-Language Content-Length Content-MD5 Content-Type Last-Modified ].to_set   Headers that MUST NOT be included with 304 Not Modified responses.

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

Attributes

body [RW] Rack response tuple accessors.
headers [RW] Rack response tuple accessors.
now [R] The time when the Response object was instantiated.
status [RW] Rack response tuple accessors.

Public class methods

new (status, headers, body)

Create a Response instance given the response status code, header hash, and body.

[show source]
    # File lib/rack/cache/response.rb, line 32
32:     def initialize(status, headers, body)
33:       @status = status.to_i
34:       @headers = Rack::Utils::HeaderHash.new(headers)
35:       @body = body
36:       @now = Time.now
37:       @headers['Date'] ||= @now.httpdate
38:     end

Public instance methods

age ()

The age of the response.

[show source]
     # File lib/rack/cache/response.rb, line 148
148:     def age
149:       (headers['Age'] ||  [(now - date).to_i, 0].max).to_i
150:     end
cache_control ()

A Hash of name=value pairs that correspond to the Cache-Control header. Valueless parameters (e.g., must-revalidate, no-store) have a Hash value of true. This method always returns a Hash, empty if no Cache-Control header is present.

[show source]
    # File lib/rack/cache/response.rb, line 68
68:     def cache_control
69:       @cache_control ||= CacheControl.new(headers['Cache-Control'])
70:     end
cache_control= (value)

Set the Cache-Control header to the values specified by the Hash. See the cache_control method for information on expected Hash structure.

[show source]
    # File lib/rack/cache/response.rb, line 74
74:     def cache_control=(value)
75:       if value.respond_to? :to_hash
76:         cache_control.clear
77:         cache_control.merge!(value)
78:         value = cache_control.to_s
79:       end
80: 
81:       if value.nil? || value.empty?
82:         headers.delete('Cache-Control')
83:       else
84:         headers['Cache-Control'] = value
85:       end
86:     end
cacheable? ()

Determine if the response is worth caching under any circumstance. Responses marked “private” with an explicit Cache-Control directive are considered uncacheable

Responses with neither a freshness lifetime (Expires, max-age) nor cache validator (Last-Modified, ETag) are considered uncacheable.

[show source]
     # File lib/rack/cache/response.rb, line 102
102:     def cacheable?
103:       return false unless CACHEABLE_RESPONSE_CODES.include?(status)
104:       return false if cache_control.no_store? || cache_control.private?
105:       validateable? || fresh?
106:     end
client_ttl= (seconds)

Set the response’s time-to-live for private/client caches. This adjusts the Cache-Control/max-age directive.

[show source]
     # File lib/rack/cache/response.rb, line 196
196:     def client_ttl=(seconds)
197:       self.max_age = age + seconds
198:     end
date ()

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

[show source]
     # File lib/rack/cache/response.rb, line 138
138:     def date
139:       if date = headers['Date']
140:         Time.httpdate(date)
141:       else
142:         headers['Date'] = now.httpdate unless headers.frozen?
143:         now
144:       end
145:     end
etag ()

The literal value of ETag HTTP header or nil if no ETag is specified.

[show source]
     # File lib/rack/cache/response.rb, line 207
207:     def etag
208:       headers['ETag']
209:     end
expire! ()

Mark the response stale by setting the Age header to be equal to the maximum age of the response.

[show source]
     # File lib/rack/cache/response.rb, line 132
132:     def expire!
133:       headers['Age'] = max_age.to_s if fresh?
134:     end
expires ()

The value of the Expires header as a Time object.

[show source]
     # File lib/rack/cache/response.rb, line 164
164:     def expires
165:       headers['Expires'] && Time.httpdate(headers['Expires'])
166:     end
fresh? ()

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.

[show source]
    # File lib/rack/cache/response.rb, line 92
92:     def fresh?
93:       ttl && ttl > 0
94:     end
initialize_copy (other)
[show source]
    # File lib/rack/cache/response.rb, line 40
40:     def initialize_copy(other)
41:       super
42:       @headers = other.headers.dup
43:     end
last_modified ()

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

[show source]
     # File lib/rack/cache/response.rb, line 202
202:     def last_modified
203:       headers['Last-Modified']
204:     end
max_age ()

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 s-maxage directive, then a max-age directive, and then fall back on an expires header; return nil when no maximum age can be established.

[show source]
     # File lib/rack/cache/response.rb, line 157
157:     def max_age
158:       cache_control.shared_max_age ||
159:         cache_control.max_age ||
160:         (expires && (expires - date))
161:     end
max_age= (value)

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

[show source]
     # File lib/rack/cache/response.rb, line 170
170:     def max_age=(value)
171:       self.cache_control = cache_control.merge('max-age' => value.to_s)
172:     end
must_revalidate? ()

Indicates that the cache must not serve a stale response in any circumstance without first revalidating with the origin. When present, the TTL of the response should not be overriden to be greater than the value provided by the origin.

[show source]
     # File lib/rack/cache/response.rb, line 126
126:     def must_revalidate?
127:       cache_control.must_revalidate || cache_control.proxy_revalidate
128:     end
not_modified! ()

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

[show source]
     # File lib/rack/cache/response.rb, line 229
229:     def not_modified!
230:       self.status = 304
231:       self.body = []
232:       NOT_MODIFIED_OMIT_HEADERS.each { |name| headers.delete(name) }
233:       nil
234:     end
private= (value)

Mark the response “private”, making it ineligible for serving other clients.

[show source]
     # File lib/rack/cache/response.rb, line 116
116:     def private=(value)
117:       value = value ? true : nil
118:       self.cache_control = cache_control.
119:         merge('public' => !value, 'private' => value)
120:     end
shared_max_age= (value)

Like max_age= but sets the s-maxage directive, which applies only to shared caches.

[show source]
     # File lib/rack/cache/response.rb, line 176
176:     def shared_max_age=(value)
177:       self.cache_control = cache_control.merge('s-maxage' => value.to_s)
178:     end
to_a ()

Return the status, headers, and body in a three-tuple.

[show source]
    # File lib/rack/cache/response.rb, line 46
46:     def to_a
47:       [status, headers.to_hash, body]
48:     end
ttl ()

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.

[show source]
     # File lib/rack/cache/response.rb, line 184
184:     def ttl
185:       max_age - age if max_age
186:     end
ttl= (seconds)

Set the response’s time-to-live for shared caches to the specified number of seconds. This adjusts the Cache-Control/s-maxage directive.

[show source]
     # File lib/rack/cache/response.rb, line 190
190:     def ttl=(seconds)
191:       self.shared_max_age = age + seconds
192:     end
validateable? ()

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

[show source]
     # File lib/rack/cache/response.rb, line 110
110:     def validateable?
111:       headers.key?('Last-Modified') || headers.key?('ETag')
112:     end
vary ()

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

[show source]
     # File lib/rack/cache/response.rb, line 237
237:     def vary
238:       headers['Vary']
239:     end
vary? ()

Does the response include a Vary header?

[show source]
     # File lib/rack/cache/response.rb, line 242
242:     def vary?
243:       ! vary.nil?
244:     end
vary_header_names ()

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

[show source]
     # File lib/rack/cache/response.rb, line 248
248:     def vary_header_names
249:       return [] unless vary = headers['Vary']
250:       vary.split(/[\s,]+/)
251:     end