Class: Wrest::Native::Response

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Includes:
HttpCodes
Defined in:
lib/wrest/native/response.rb

Overview

Decorates a response providing support for deserialisation.

The following methods are also available (unlisted by rdoc because they're forwarded to Net::HTTP::Response):

:@Http_response, :code, :message, :body, :Http_version, :[], :content_length, :content_type, :each_header, :each_name, :each_value, :fetch, :get_fields, :key?, :type_params

They behave exactly like their Net::HttpResponse equivalents.

Also provides set of HTTP response code checkers. For instance, the method ok? checks if the response was successful with HTTP code 200. See HttpCodes for a list of all such response checkers.

Direct Known Subclasses

Redirection

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Methods included from HttpCodes

#accepted?, #bad_request?, #created?, #forbidden?, #found?, #internal_server_error?, #method_not_allowed?, #moved_permanently?, #no_content?, #not_acceptable?, #not_found?, #not_modified?, #ok?, #see_other?, #temporary_redirect?, #unauthorized?, #unprocessable_entity?

Constructor Details

- (Response) initialize(http_response)

Returns a new instance of Response



50
51
52
# File 'lib/wrest/native/response.rb', line 50

def initialize(http_response)
  @http_response = http_response
end

Instance Attribute Details

- (Object) deserialised_body

Returns the value of attribute deserialised_body



27
28
29
# File 'lib/wrest/native/response.rb', line 27

def deserialised_body
  @deserialised_body
end

- (Object) http_response (readonly)

Returns the value of attribute http_response



26
27
28
# File 'lib/wrest/native/response.rb', line 26

def http_response
  @http_response
end

Class Method Details

+ (Object) new(http_response)

We're overriding :new to act as a factory so we can build the appropriate Response instance based on the response code.



43
44
45
46
47
48
# File 'lib/wrest/native/response.rb', line 43

def self.new(http_response)
  code = http_response.code.to_i
  instance = ((300..303).include?(code) || (305..399).include?(code)  ? Wrest::Native::Redirection : self).allocate
  instance.send :initialize, http_response
  instance
end

Instance Method Details

- (Object) ==(other)

Checks equality between two Wrest::Native::Response objects.



59
60
61
62
63
64
65
66
67
68
# File 'lib/wrest/native/response.rb', line 59

def ==(other)
  return true if self.equal?(other)
  return false unless other.class == self.class
  return true if self.code == other.code and
      self.headers == other.headers and
      self.http_version == other.http_version and
      self.message == other.message and
      self.body == other.body
  false
end

- (Object) cache_control_headers

The values in Cache-Control header as an array.



198
199
200
# File 'lib/wrest/native/response.rb', line 198

def cache_control_headers
  @cache_control_headers ||= recalculate_cache_control_headers
end

- (Boolean) cacheable?

Returns whether this response is cacheable.

Returns:

  • (Boolean)


111
112
113
114
115
# File 'lib/wrest/native/response.rb', line 111

def cacheable?
  code_cacheable? && no_cache_flag_not_set? && no_store_flag_not_set? &&
      (not max_age.nil? or (expires_not_in_our_past? && expires_not_in_its_past?)) && pragma_nocache_not_set? &&
      vary_tag_not_set?
end

- (Boolean) can_be_validated?

Can this response be validated by sending a validation request to the server. The response need to have either Last-Modified or ETag header (or both) for it to be validatable.

Returns:

  • (Boolean)


238
239
240
# File 'lib/wrest/native/response.rb', line 238

def can_be_validated?
  not (last_modified.nil? and headers['etag'].nil?)
end

- (Boolean) code_cacheable?

:nodoc:

Returns:

  • (Boolean)


118
119
120
# File 'lib/wrest/native/response.rb', line 118

def code_cacheable?
  !code.nil? && ([200, 203, 300, 301, 302, 304, 307].include?(code.to_i))
end

- (Boolean) connection_closed?

Returns:

  • (Boolean)


106
107
108
# File 'lib/wrest/native/response.rb', line 106

def connection_closed?
  self[Native::StandardHeaders::Connection].downcase == Native::StandardTokens::Close.downcase
end

- (Object) current_age

Age of the response calculated according to RFC 2616 13.2.3



185
186
187
188
189
190
191
192
193
194
195
# File 'lib/wrest/native/response.rb', line 185

def current_age
  current_time = Time.now.to_i

  # RFC 2616 13.2.3 Age Calculations. TODO: include response_delay in the calculation as defined in RFC. For this, include original Request with Response.
  date_value             = DateTime.parse(headers['date']).to_i rescue current_time
  age_value              = headers['age'].to_i || 0

  apparent_age           = current_time - date_value

  [apparent_age, age_value].max
end

- (Object) deserialise(options = {})



76
77
78
# File 'lib/wrest/native/response.rb', line 76

def deserialise(options = {})
    @deserialised_body ||= deserialise_using(Wrest::Components::Translators.lookup(@http_response.content_type),options)
end

- (Object) deserialise_using(translator, options = {})



80
81
82
# File 'lib/wrest/native/response.rb', line 80

def deserialise_using(translator,options = {})
  translator.deserialise(@http_response,options)
end

- (Boolean) expired?

Has this response expired? The expiry is calculated from the Max-Age/Expires header.

Returns:

  • (Boolean)


223
224
225
226
227
228
229
230
# File 'lib/wrest/native/response.rb', line 223

def expired?
  freshness=freshness_lifetime
  if freshness <= 0
    return true
  end

  freshness <= current_age
end

- (Object) expires

Returns the Expires date from the response headers.



160
161
162
163
# File 'lib/wrest/native/response.rb', line 160

def expires
  return @expires if @expires
  @expires = parse_datefield(headers, "expires")
end

- (Boolean) expires_not_in_its_past?

Is the Expires of this response earlier than its Date header.

Returns:

  • (Boolean)


175
176
177
178
179
180
181
182
# File 'lib/wrest/native/response.rb', line 175

def expires_not_in_its_past?
  # Invalid header value for Date or Expires means the response is not cacheable
  if  expires.nil? || response_date.nil?
    false
  else
     expires > response_date
  end
end

- (Boolean) expires_not_in_our_past?

Returns whether the Expires header of this response is earlier than current time.

Returns:

  • (Boolean)


166
167
168
169
170
171
172
# File 'lib/wrest/native/response.rb', line 166

def expires_not_in_our_past?
  if expires.nil?
    false
  else
    expires.to_i > Time.now.to_i
  end
end

- (Object) follow(redirect_request_options = {})

A null object implementation - invoking this method on a response simply returns the same response unless the response is Redirection (code 3xx), in which case a get is invoked on the url stored in the response headers under the key 'location' and the new Response is returned.



102
103
104
# File 'lib/wrest/native/response.rb', line 102

def follow(redirect_request_options = {})
  self
end

- (Object) freshness_lifetime

How long (in seconds) is this response expected to be fresh



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

def freshness_lifetime
  @freshness_lifetime ||= recalculate_freshness_lifetime
end

- (Object) hash

Return the hash of a Wrest::Native::Response object.



71
72
73
# File 'lib/wrest/native/response.rb', line 71

def hash
  self.code.hash + self.message.hash + self.headers.hash + self.http_version.hash + self.body.hash
end

- (Object) headers

Gives a hash of the response headers. The keys of the hash are case-insensitive.



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/wrest/native/response.rb', line 85

def headers
  return @headers if @headers

  nethttp_headers_with_string_values=@http_response.to_hash.inject({}) {|new_headers, (old_key, old_value)|
    new_headers[old_key] = old_value.is_a?(Array) ? old_value.join(",") : old_value
    new_headers
    }
  
  @headers=Wrest::HashWithCaseInsensitiveAccess.new(nethttp_headers_with_string_values)

end

- (Object) initialize_copy(source)



54
55
56
# File 'lib/wrest/native/response.rb', line 54

def initialize_copy(source)
  @headers = source.headers.clone
end

- (Object) last_modified



232
233
234
# File 'lib/wrest/native/response.rb', line 232

def last_modified
  headers['last-modified']
end

- (Object) max_age

:nodoc:



123
124
125
126
127
128
129
130
131
132
133
# File 'lib/wrest/native/response.rb', line 123

def max_age
  return @max_age if @max_age

  max_age  =cache_control_headers.grep(/max-age/)

  @max_age = unless max_age.empty?
               max_age.first.split('=').last.to_i
             else
               nil
             end
end

- (Boolean) no_cache_flag_not_set?

Returns:

  • (Boolean)


135
136
137
# File 'lib/wrest/native/response.rb', line 135

def no_cache_flag_not_set?
  not cache_control_headers.include?('no-cache')
end

- (Boolean) no_store_flag_not_set?

Returns:

  • (Boolean)


139
140
141
# File 'lib/wrest/native/response.rb', line 139

def no_store_flag_not_set?
  not cache_control_headers.include?('no-store')
end

- (Object) parse_datefield(hash, key)

:nodoc: helper function. Used to parse date fields. this function is used and tested by the expires and response_date methods



246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/wrest/native/response.rb', line 246

def parse_datefield(hash, key)
  if hash[key]
    # Can't trust external input. Do not crash even if invalid dates are passed.
    begin
      DateTime.parse(hash[key].to_s)
    rescue ArgumentError
      nil
    end
  else
    nil
  end
end

- (Boolean) pragma_nocache_not_set?

Returns:

  • (Boolean)


143
144
145
# File 'lib/wrest/native/response.rb', line 143

def pragma_nocache_not_set?
  headers['pragma'].nil? || (not headers['pragma'].include? 'no-cache')
end

- (Object) recalculate_cache_control_headers

:nodoc:



203
204
205
# File 'lib/wrest/native/response.rb', line 203

def recalculate_cache_control_headers
  headers['cache-control'].split(",").collect {|cc| cc.strip } rescue []
end

- (Object) recalculate_freshness_lifetime

:nodoc:



213
214
215
216
217
218
219
220
# File 'lib/wrest/native/response.rb', line 213

def recalculate_freshness_lifetime
  return max_age if max_age

  response_date = DateTime.parse(headers['date']).to_i
  expires_date  = DateTime.parse(headers['expires']).to_i

  return (expires_date - response_date)
end

- (Object) response_date

Returns the Date from the response headers.



153
154
155
156
# File 'lib/wrest/native/response.rb', line 153

def response_date
  return @response_date if @response_date
  @response_date = parse_datefield(headers, "date")
end

- (Boolean) vary_tag_not_set?

:nodoc:

Returns:

  • (Boolean)


148
149
150
# File 'lib/wrest/native/response.rb', line 148

def vary_tag_not_set?
  headers['vary'].nil?
end