lib/httpx/response.rb in httpx-0.16.1 vs lib/httpx/response.rb in httpx-0.17.0
- old
+ new
@@ -12,10 +12,12 @@
attr_reader :status, :headers, :body, :version
def_delegator :@body, :to_s
+ def_delegator :@body, :to_str
+
def_delegator :@body, :read
def_delegator :@body, :copy_to
def_delegator :@body, :close
@@ -43,11 +45,11 @@
@request.verb == :head ||
no_data?
end
def content_type
- ContentType.parse(@headers["content-type"])
+ @content_type ||= ContentType.new(@headers["content-type"])
end
def complete?
bodyless? || (@request.verb == :connect && @status == 200)
end
@@ -66,12 +68,35 @@
return if @status < 400
raise HTTPError, self
end
+ def json(options = nil)
+ decode("json", options)
+ end
+
+ def form
+ decode("form")
+ end
+
private
+ def decode(format, options = nil)
+ # TODO: check if content-type is a valid format, i.e. "application/json" for json parsing
+ transcoder = Transcoder.registry(format)
+
+ raise Error, "no decoder available for \"#{format}\"" unless transcoder.respond_to?(:decode)
+
+ decoder = transcoder.decode(self)
+
+ raise Error, "no decoder available for \"#{format}\"" unless decoder
+
+ decoder.call(self, options)
+ rescue Registry::Error
+ raise Error, "no decoder available for \"#{format}\""
+ end
+
def no_data?
@status < 200 ||
@status == 204 ||
@status == 205 ||
@status == 304 || begin
@@ -91,22 +116,12 @@
@window_size = options.window_size
@encoding = response.content_type.charset || Encoding::BINARY
@length = 0
@buffer = nil
@state = :idle
- ObjectSpace.define_finalizer(self, self.class.finalize(@buffer))
end
- def self.finalize(buffer)
- proc {
- return unless buffer
-
- @buffer.close
- @buffer.unlink if @buffer.respond_to?(:unlink)
- }
- end
-
def closed?
@state == :closed
end
def write(chunk)
@@ -262,33 +277,25 @@
class ContentType
MIME_TYPE_RE = %r{^([^/]+/[^;]+)(?:$|;)}.freeze
CHARSET_RE = /;\s*charset=([^;]+)/i.freeze
- attr_reader :mime_type, :charset
-
- def initialize(mime_type, charset)
- @mime_type = mime_type
- @charset = charset
+ def initialize(header_value)
+ @header_value = header_value
end
- class << self
- # Parse string and return ContentType struct
- def parse(str)
- new(mime_type(str), charset(str))
- end
+ def mime_type
+ return @mime_type if defined?(@mime_type)
- private
+ m = @header_value.to_s[MIME_TYPE_RE, 1]
+ m && @mime_type = m.strip.downcase
+ end
- def mime_type(str)
- m = str.to_s[MIME_TYPE_RE, 1]
- m && m.strip.downcase
- end
+ def charset
+ return @charset if defined?(@charset)
- def charset(str)
- m = str.to_s[CHARSET_RE, 1]
- m && m.strip.delete('"')
- end
+ m = @header_value.to_s[CHARSET_RE, 1]
+ m && @charset = m.strip.delete('"')
end
end
class ErrorResponse
include Loggable