lib/httpx/response.rb in httpx-0.15.4 vs lib/httpx/response.rb in httpx-0.16.0

- old
+ new

@@ -1,7 +1,8 @@ # frozen_string_literal: true +require "objspace" require "stringio" require "tempfile" require "fileutils" require "forwardable" @@ -90,12 +91,22 @@ @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) @@ -132,22 +143,30 @@ close end end def to_s - rewind - if @buffer - content = @buffer.read + case @buffer + when StringIO begin - return content.force_encoding(@encoding) + @buffer.string.force_encoding(@encoding) + rescue ArgumentError + @buffer.string + end + when Tempfile, File + rewind + content = _with_same_buffer_pos { @buffer.read } + begin + content.force_encoding(@encoding) rescue ArgumentError # ex: unknown encoding name - utf - return content + content end + when nil + "".b + else + @buffer end - "".b - ensure - close end alias_method :to_str, :to_s def empty? @length.zero? @@ -175,11 +194,15 @@ @length = 0 @state = :closed end def ==(other) - to_s == other.to_s + if other.respond_to?(:read) + _with_same_buffer_pos { FileUtils.compare_stream(@buffer, other) } + else + to_s == other.to_s + end end # :nocov: def inspect "#<HTTPX::Response::Body:#{object_id} " \ @@ -202,11 +225,11 @@ if @length > @threshold_size @state = :buffer @buffer = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR) else @state = :memory - @buffer = StringIO.new("".b, File::RDWR) + @buffer = StringIO.new("".b) end when :memory if @length > @threshold_size aux = @buffer @buffer = Tempfile.new("httpx", encoding: Encoding::BINARY, mode: File::RDWR) @@ -220,10 +243,22 @@ end end return unless %i[memory buffer].include?(@state) end + + def _with_same_buffer_pos + return yield unless @buffer && @buffer.respond_to?(:pos) + + current_pos = @buffer.pos + @buffer.rewind + begin + yield + rescue StandardError + @buffer.pos = current_pos + end + end end end class ContentType MIME_TYPE_RE = %r{^([^/]+/[^;]+)(?:$|;)}.freeze @@ -284,17 +319,9 @@ end def raise_for_status raise @error end - - # rubocop:disable Style/MissingRespondToMissing - def method_missing(meth, *, &block) - raise NoMethodError, "undefined response method `#{meth}' for error response" if @options.response_class.public_method_defined?(meth) - - super - end - # rubocop:enable Style/MissingRespondToMissing end end require "httpx/pmatch_extensions" if RUBY_VERSION >= "3.0.0"