Permalink
Fetching contributors…
Cannot retrieve contributors at this time
99 lines (78 sloc) 2.37 KB
require "zlib"
require "stringio"
require "rack/utils"
require "httpi/dime"
require "httpi/cookie"
module HTTPI
# = HTTPI::Response
#
# Represents an HTTP response and contains various response details.
class Response
# Range of HTTP response codes considered to be successful.
SuccessfulResponseCodes = 200..299
# HTTP response codes considered to be a redirect.
RedirectResponseCodes = [301, 302, 303, 307, 308]
# Initializer expects an HTTP response +code+, +headers+ and +body+.
def initialize(code, headers, body)
self.code = code.to_i
self.headers = Rack::Utils::HeaderHash.new(headers)
self.raw_body = body
end
attr_accessor :code, :headers, :raw_body
attr_writer :attachments
# Returns whether the HTTP response is considered successful.
def error?
!SuccessfulResponseCodes.include? code.to_i
end
# Returns whether the HTTP response is a multipart response.
def multipart?
!!(headers["Content-Type"] =~ /^multipart/i)
end
# Returns a list of cookies from the response.
def cookies
@cookies ||= Cookie.list_from_headers(headers)
end
# Returns any DIME attachments.
def attachments
@body ||= nil
decode_body unless @body
@attachments ||= []
end
# Returns the HTTP response body.
def body
@body ||= nil
decode_body unless @body
@body
end
attr_writer :body
private
def decode_body
return @body = "" if !raw_body || raw_body.empty?
body = gzipped_response? ? decoded_gzip_body : raw_body
@body = dime_response? ? decoded_dime_body(body) : body
end
# Returns whether the response is gzipped.
def gzipped_response?
headers["Content-Encoding"] == "gzip"
end
# Returns whether this is a DIME response.
def dime_response?
headers["Content-Type"] == "application/dime"
end
# Returns the gzip decoded response body.
def decoded_gzip_body
unless gzip = Zlib::GzipReader.new(StringIO.new(raw_body))
raise ArgumentError, "Unable to create Zlib::GzipReader"
end
gzip.read
ensure
gzip.close if gzip
end
# Returns the DIME decoded response body.
def decoded_dime_body(body = nil)
dime = Dime.new(body || raw_body)
self.attachments = dime.binary_records
dime.xml_records.first.data
end
end
end