Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Request::Body#source #438

Merged
merged 2 commits into from
Nov 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 10 additions & 14 deletions lib/http/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ def initialize(opts)
raise(UnsupportedSchemeError, "unknown scheme: #{scheme}") unless SCHEMES.include?(@scheme)

@proxy = opts[:proxy] || {}
@body = request_body(opts[:body], opts)
@body = Request::Body.new(opts[:body])
@deflate = opts[:auto_deflate]
@version = opts[:version] || "1.1"
@headers = HTTP::Headers.coerce(opts[:headers] || {})

Expand All @@ -100,18 +101,20 @@ def redirect(uri, verb = @verb)
headers.delete(Headers::HOST)

self.class.new(
:verb => verb,
:uri => @uri.join(uri),
:headers => headers,
:proxy => proxy,
:body => body,
:version => version
:verb => verb,
:uri => @uri.join(uri),
:headers => headers,
:proxy => proxy,
:body => body.source,
:auto_deflate => @deflate,
:version => version
)
end

# Stream the request to a socket
def stream(socket)
include_proxy_headers if using_proxy? && !@uri.https?
body = @deflate ? @deflate.deflated_body(self.body) : self.body
Request::Writer.new(socket, body, headers, headline).stream
end

Expand Down Expand Up @@ -186,13 +189,6 @@ def socket_port

private

# Transforms body to an object suitable for streaming.
def request_body(body, opts)
body = Request::Body.new(body) unless body.is_a?(Request::Body)
body = opts[:auto_deflate].deflated_body(body) if opts[:auto_deflate]
body
end

# @!attribute [r] host
# @return [String]
def_delegator :@uri, :host
Expand Down
51 changes: 29 additions & 22 deletions lib/http/request/body.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,57 @@
module HTTP
class Request
class Body
def initialize(body)
@body = body
attr_reader :source

validate_body_type!
def initialize(source)
@source = source

validate_source_type!
end

# Returns size which should be used for the "Content-Length" header.
#
# @return [Integer]
def size
if @body.is_a?(String)
@body.bytesize
elsif @body.respond_to?(:read)
raise RequestError, "IO object must respond to #size" unless @body.respond_to?(:size)
@body.size
elsif @body.nil?
if @source.is_a?(String)
@source.bytesize
elsif @source.respond_to?(:read)
raise RequestError, "IO object must respond to #size" unless @source.respond_to?(:size)
@source.size
elsif @source.nil?
0
else
raise RequestError, "cannot determine size of body: #{@body.inspect}"
raise RequestError, "cannot determine size of body: #{@source.inspect}"
end
end

# Yields chunks of content to be streamed to the request body.
#
# @yieldparam [String]
def each(&block)
if @body.is_a?(String)
yield @body
elsif @body.respond_to?(:read)
IO.copy_stream(@body, ProcIO.new(block))
elsif @body.is_a?(Enumerable)
@body.each(&block)
if @source.is_a?(String)
yield @source
elsif @source.respond_to?(:read)
IO.copy_stream(@source, ProcIO.new(block))
elsif @source.is_a?(Enumerable)
@source.each(&block)
end
end

# Request bodies are equivalent when they have the same source.
def ==(other)
self.class == other.class && self.source == other.source # rubocop:disable Style/RedundantSelf
end

private

def validate_body_type!
return if @body.is_a?(String)
return if @body.respond_to?(:read)
return if @body.is_a?(Enumerable)
return if @body.nil?
def validate_source_type!
return if @source.is_a?(String)
return if @source.respond_to?(:read)
return if @source.is_a?(Enumerable)
return if @source.nil?

raise RequestError, "body of wrong type: #{@body.class}"
raise RequestError, "body of wrong type: #{@source.class}"
end

# This class provides a "writable IO" wrapper around a proc object, with
Expand Down