lib/httpx/request/body.rb in httpx-1.0.2 vs lib/httpx/request/body.rb in httpx-1.1.0

- old
+ new

@@ -1,24 +1,23 @@ # frozen_string_literal: true module HTTPX + # Implementation of the HTTP Request body as a delegator which iterates (responds to +each+) payload chunks. class Request::Body < SimpleDelegator class << self def new(_, options) return options.body if options.body.is_a?(self) super end end - attr_reader :threshold_size - + # inits the instance with the request +headers+ and +options+, which contain the payload definition. def initialize(headers, options) @headers = headers - @threshold_size = options.body_threshold_size - # forego compression in the Range cases + # forego compression in the Range request case if @headers.key?("range") @headers.delete("accept-encoding") else @headers["accept-encoding"] ||= options.supported_compression_formats end @@ -30,10 +29,11 @@ @headers["content-type"] ||= @body.content_type @headers["content-length"] = @body.bytesize unless unbounded_body? super(@body) end + # consumes and yields the request payload in chunks. def each(&block) return enum_for(__method__) unless block return if @body.nil? body = stream(@body) @@ -44,45 +44,52 @@ else block[body.to_s] end end + # if the +@body+ is rewindable, it rewinnds it. def rewind return if empty? @body.rewind if @body.respond_to?(:rewind) end + # return +true+ if the +body+ has been fully drained (or does nnot exist). def empty? return true if @body.nil? return false if chunked? @body.bytesize.zero? end + # returns the +@body+ payload size in bytes. def bytesize return 0 if @body.nil? @body.bytesize end + # sets the body to yield using chunked trannsfer encoding format. def stream(body) encoded = body encoded = Transcoder::Chunker.encode(body.enum_for(:each)) if chunked? encoded end + # returns whether the body yields infinitely. def unbounded_body? return @unbounded_body if defined?(@unbounded_body) @unbounded_body = !@body.nil? && (chunked? || @body.bytesize == Float::INFINITY) end + # returns whether the chunked transfer encoding header is set. def chunked? @headers["transfer-encoding"] == "chunked" end + # sets the chunked transfer encoding header. def chunk! @headers.add("transfer-encoding", "chunked") end # :nocov: @@ -92,10 +99,17 @@ end # :nocov: private + # wraps the given body with the appropriate encoder. + # + # ..., json: { foo: "bar" }) #=> json encoder + # ..., form: { foo: "bar" }) #=> form urlencoded encoder + # ..., form: { foo: Pathname.open("path/to/file") }) #=> multipart urlencoded encoder + # ..., form: { foo: File.open("path/to/file") }) #=> multipart urlencoded encoder + # ..., form: { body: "bla") }) #=> raw data encoder def initialize_body(options) @body = if options.body Transcoder::Body.encode(options.body) elsif options.form Transcoder::Form.encode(options.form) @@ -103,22 +117,19 @@ Transcoder::JSON.encode(options.json) elsif options.xml Transcoder::Xml.encode(options.xml) end - return unless @body + return unless @body && options.compress_request_body && @headers.key?("content-encoding") - return unless options.compress_request_body - - return unless @headers.key?("content-encoding") - @headers.get("content-encoding").each do |encoding| @body = self.class.initialize_deflater_body(@body, encoding) end end class << self + # returns the +body+ wrapped with the correct deflater accordinng to the given +encodisng+. def initialize_deflater_body(body, encoding) case encoding when "gzip" Transcoder::GZIP.encode(body) when "deflate" @@ -130,14 +141,16 @@ end end end end + # Wrapper yielder which can be used with functions which expect an IO writer. class ProcIO def initialize(block) @block = block end + # Implementation the IO write protocol, which yield the given chunk to +@block+. def write(data) @block.call(data.dup) data.bytesize end end