2010-01-25 22:04:59 +01:00
|
|
|
module RestClient
|
|
|
|
|
|
|
|
class AbstractResponse
|
|
|
|
|
2010-02-10 21:31:59 +01:00
|
|
|
attr_reader :net_http_res, :args
|
2010-01-25 22:04:59 +01:00
|
|
|
|
2010-02-10 21:31:59 +01:00
|
|
|
def initialize net_http_res, args
|
2010-01-27 23:07:03 +01:00
|
|
|
@net_http_res = net_http_res
|
2010-02-10 21:31:59 +01:00
|
|
|
@args = args
|
2010-01-27 23:07:03 +01:00
|
|
|
end
|
|
|
|
|
2010-01-25 22:04:59 +01:00
|
|
|
# HTTP status code
|
|
|
|
def code
|
|
|
|
@code ||= @net_http_res.code.to_i
|
|
|
|
end
|
|
|
|
|
|
|
|
# A hash of the headers, beautified with symbols and underscores.
|
|
|
|
# e.g. "Content-type" will become :content_type.
|
|
|
|
def headers
|
|
|
|
@headers ||= self.class.beautify_headers(@net_http_res.to_hash)
|
|
|
|
end
|
|
|
|
|
|
|
|
# The raw headers.
|
|
|
|
def raw_headers
|
|
|
|
@raw_headers ||= @net_http_res.to_hash
|
|
|
|
end
|
|
|
|
|
|
|
|
# Hash of cookies extracted from response headers
|
|
|
|
def cookies
|
|
|
|
@cookies ||= (self.headers[:set_cookie] || []).inject({}) do |out, cookie_content|
|
|
|
|
# correctly parse comma-separated cookies containing HTTP dates (which also contain a comma)
|
|
|
|
cookie_content.split(/,\s*/).inject([""]) { |array, blob|
|
|
|
|
blob =~ /expires=.+?$/ ? array.push(blob) : array.last.concat(blob)
|
|
|
|
array
|
|
|
|
}.each do |cookie|
|
|
|
|
next if cookie.empty?
|
|
|
|
key, *val = cookie.split(";").first.split("=")
|
|
|
|
out[key] = val.join("=")
|
|
|
|
end
|
|
|
|
out
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Return the default behavior corresponding to the response code:
|
2010-02-10 21:31:59 +01:00
|
|
|
# the response itself for code in 200..206, redirection for 301..303 in get and head cases, and an exception in other cases
|
|
|
|
def return! &block
|
2010-01-25 22:04:59 +01:00
|
|
|
if (200..206).include? code
|
|
|
|
self
|
2010-02-10 21:31:59 +01:00
|
|
|
elsif (301..303).include? code
|
|
|
|
unless [:get, :head].include? args[:method]
|
|
|
|
raise Exceptions::EXCEPTIONS_MAP[code], self
|
|
|
|
else
|
|
|
|
follow_redirection &block
|
|
|
|
end
|
2010-01-25 22:04:59 +01:00
|
|
|
elsif Exceptions::EXCEPTIONS_MAP[code]
|
|
|
|
raise Exceptions::EXCEPTIONS_MAP[code], self
|
|
|
|
else
|
|
|
|
raise RequestFailed, self
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2010-01-26 19:41:53 +01:00
|
|
|
def inspect
|
2010-02-10 21:31:59 +01:00
|
|
|
"#{code} #{STATUSES[code]} | #{(headers[:content_type] || '').gsub(/;.*$/, '')} #{size} bytes\n"
|
2010-01-26 19:41:53 +01:00
|
|
|
end
|
|
|
|
|
2010-02-10 21:31:59 +01:00
|
|
|
# Follow a redirection
|
|
|
|
def follow_redirection &block
|
|
|
|
url = headers[:location]
|
|
|
|
if url !~ /^http/
|
|
|
|
url = URI.parse(args[:url]).merge(url).to_s
|
|
|
|
end
|
|
|
|
redirected_args = args.dup
|
|
|
|
redirected_args[:url] = url
|
|
|
|
Request.execute redirected_args, &block
|
|
|
|
end
|
2010-01-26 19:41:53 +01:00
|
|
|
|
2010-01-25 22:04:59 +01:00
|
|
|
def AbstractResponse.beautify_headers(headers)
|
|
|
|
headers.inject({}) do |out, (key, value)|
|
|
|
|
out[key.gsub(/-/, '_').downcase.to_sym] = %w{set-cookie}.include?(key.downcase) ? value : value.first
|
|
|
|
out
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|