Class: Resourceful::Response

Inherits:
Object
  • Object
show all
Defined in:
lib/resourceful/response.rb

Constant Summary collapse

REDIRECT_RESPONSE_CODES =
[301,302,303,307]
NORMALLY_CACHEABLE_RESPONSE_CODES =
[200, 203, 300, 301, 410]
CODE_NAMES =
{
  100 => "Continue".freeze,
  101 => "Switching Protocols".freeze,

  200 => "OK".freeze,
  201 => "Created".freeze,
  202 => "Accepted".freeze,
  203 => "Non-Authoritative Information".freeze,
  204 => "No Content".freeze,
  205 => "Reset Content".freeze,
  206 => "Partial Content".freeze,

  300 => "Multiple Choices".freeze,
  301 => "Moved Permanently".freeze,
  302 => "Found".freeze,
  303 => "See Other".freeze,
  304 => "Not Modified".freeze,
  305 => "Use Proxy".freeze,
  307 => "Temporary Redirect".freeze,

  400 => "Bad Request".freeze,
  401 => "Unauthorized".freeze,
  402 => "Payment Required".freeze,
  403 => "Forbidden".freeze,
  404 => "Not Found".freeze,
  405 => "Method Not Allowed".freeze,
  406 => "Not Acceptable".freeze,
  407 => "Proxy Authentication Required".freeze,
  408 => "Request Timeout".freeze,
  409 => "Conflict".freeze,
  410 => "Gone".freeze,
  411 => "Length Required".freeze,
  412 => "Precondition Failed".freeze,
  413 => "Request Entity Too Large".freeze,
  414 => "Request-URI Too Long".freeze,
  415 => "Unsupported Media Type".freeze,
  416 => "Requested Range Not Satisfiable".freeze,
  417 => "Expectation Failed".freeze,

  500 => "Internal Server Error".freeze,
  501 => "Not Implemented".freeze,
  502 => "Bad Gateway".freeze,
  503 => "Service Unavailable".freeze,
  504 => "Gateway Timeout".freeze,
  505 => "HTTP Version Not Supported".freeze,
}.freeze
CODES =
CODE_NAMES.keys

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uri, code, header, body) ⇒ Response

Returns a new instance of Response.



17
18
19
20
# File 'lib/resourceful/response.rb', line 17

def initialize(uri, code, header, body)
  @uri, @code, @header, @body = uri, code, header, body
  @response_time = Time.now
end

Instance Attribute Details

#authoritativeObject Also known as: authoritative?

Returns the value of attribute authoritative.



14
15
16
# File 'lib/resourceful/response.rb', line 14

def authoritative
  @authoritative
end

#bodyObject (readonly)

Returns the value of attribute body.



11
12
13
# File 'lib/resourceful/response.rb', line 11

def body
  @body
end

#codeObject (readonly)

Returns the value of attribute code.



11
12
13
# File 'lib/resourceful/response.rb', line 11

def code
  @code
end

#headerObject (readonly) Also known as: headers

Returns the value of attribute header.



11
12
13
# File 'lib/resourceful/response.rb', line 11

def header
  @header
end

#request_timeObject

Returns the value of attribute request_time.



14
15
16
# File 'lib/resourceful/response.rb', line 14

def request_time
  @request_time
end

#response_timeObject (readonly)

Returns the value of attribute response_time.



11
12
13
# File 'lib/resourceful/response.rb', line 11

def response_time
  @response_time
end

#uriObject (readonly)

Returns the value of attribute uri.



11
12
13
# File 'lib/resourceful/response.rb', line 11

def uri
  @uri
end

Instance Method Details

#cacheable?Boolean

Is this response cachable?

Returns:

  • (Boolean)

    true|false



52
53
54
55
56
57
58
59
60
61
# File 'lib/resourceful/response.rb', line 52

def cacheable?
  @cacheable ||= begin
    @cacheable = true  if NORMALLY_CACHEABLE_RESPONSE_CODES.include?(code.to_i)
    @cacheable = false if header.vary && header.vary.include?('*')
    @cacheable = false if header.cache_control && header.cache_control.include?('no-cache')
    @cacheable = true  if header.cache_control && header.cache_control.include?('public')
    @cacheable = true  if header.cache_control && header.cache_control.include?('private')
    @cacheable || false
  end
end

#client_error?Boolean

Is the response the result of a client error? True for 4xx series response codes

Returns:

  • (Boolean)

    true|false



200
201
202
# File 'lib/resourceful/response.rb', line 200

def client_error?
  @code.in? 400..499
end

#current_ageObject

Algorithm taken from RCF2616#13.2.3



77
78
79
80
81
82
83
84
85
# File 'lib/resourceful/response.rb', line 77

def current_age
  age_value   = header['Age'] ? header['Age'].first.to_i : 0
  date_value  = Time.httpdate(header['Date'].first)
  now         = Time.now

  apparent_age = [0, response_time - date_value].max
  corrected_received_age = [apparent_age, age_value].max
  current_age = corrected_received_age + (response_time - request_time) + (now - response_time)
end

#error?Boolean

Is the response the result of any kind of error? True for 4xx and 5xx series response codes

Returns:

  • (Boolean)

    true|false



216
217
218
# File 'lib/resourceful/response.rb', line 216

def error?
  server_error? || client_error?
end

#expired?Boolean

Is this a cached response that has expired?

Returns:

  • (Boolean)

    true|false



25
26
27
28
29
30
31
32
33
34
# File 'lib/resourceful/response.rb', line 25

def expired?
  if header['Cache-Control'] and header['Cache-Control'].first.include?('max-age')
    max_age = header['Cache-Control'].first.split(',').grep(/max-age/).first.split('=').last.to_i
    return true if current_age > max_age
  elsif header['Expire']
    return true if Time.httpdate(header['Expire'].first) < Time.now
  end

  false
end

#informational?Boolean

Is the response informational? True for 1xx series response codes

Returns:

  • (Boolean)

    true|false



167
168
169
# File 'lib/resourceful/response.rb', line 167

def informational?
  @code.in? 100..199
end

#must_be_revalidated?Boolean

Does this response force revalidation?

Returns:

  • (Boolean)


64
65
66
# File 'lib/resourceful/response.rb', line 64

def must_be_revalidated?
  header.cache_control && header.cache_control.include?('must-revalidate')
end

#redirect?Boolean

Is the response a actual redirect? True for 301, 302, 303, 307 response codes

Returns:

  • (Boolean)

    true|false



192
193
194
# File 'lib/resourceful/response.rb', line 192

def redirect?
  @code.in? REDIRECT_RESPONSE_CODES
end

#redirection?Boolean

Is the response a redirect? True for 3xx series response codes

Returns:

  • (Boolean)

    true|false



184
185
186
# File 'lib/resourceful/response.rb', line 184

def redirection?
  @code.in? 300..399
end

#revalidate!(not_modified_response) ⇒ Object

Update our headers from a later 304 response



69
70
71
72
73
74
# File 'lib/resourceful/response.rb', line 69

def revalidate!(not_modified_response)
  header.merge!(not_modified_response.header)
  @request_time  = not_modified_response.request_time
  @response_time = not_modified_response.response_time
  @authoritative = true
end

#server_error?Boolean

Is the response the result of a server error? True for 5xx series response codes

Returns:

  • (Boolean)

    true|false



208
209
210
# File 'lib/resourceful/response.rb', line 208

def server_error?
  @code.in? 500..599
end

#stale?Boolean

Is this a cached response that is stale?

Returns:

  • (Boolean)

    true|false



39
40
41
42
43
44
45
46
47
# File 'lib/resourceful/response.rb', line 39

def stale?
  return true if expired?
  if header['Cache-Control']
    return true if header['Cache-Control'].include?('must-revalidate')
    return true if header['Cache-Control'].include?('no-cache')
  end

  false
end

#successful?Boolean Also known as: success?

Is the response code sucessful? True for only 2xx series response codes.

Returns:

  • (Boolean)

    true|false



175
176
177
# File 'lib/resourceful/response.rb', line 175

def successful?
  @code.in? 200..299
end