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"