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