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