Protocol::HTTPSourceProtocolHTTPBodyWritable

class Writable

A dynamic body which you can write to and read from.

Nested

Definitions

def initialize(length = nil, queue: Thread::Queue.new)

Initialize the writable body.

Signature

parameter length Integer

The length of the response body if known.

parameter queue Thread::Queue

Specify a different queue implementation, e.g. Thread::SizedQueue to enable back-pressure.

Implementation

def initialize(length = nil, queue: Thread::Queue.new)
	@length = length
	@queue = queue
	@count = 0
	@error = nil
end

attr :length

Signature

attribute Integer

The length of the response body if known.

def close(error = nil)

Stop generating output; cause the next call to write to fail with the given error. Does not prevent existing chunks from being read. In other words, this indicates both that no more data will be or should be written to the body.

Signature

parameter error Exception

The error that caused this body to be closed, if any. Will be raised on the next call to Protocol::HTTP::Body::Writable#read.

Implementation

def close(error = nil)
	@error ||= error
	
	@queue.clear
	@queue.close
	
	super
end

def closed?

Whether the body is closed. A closed body can not be written to or read from.

Signature

returns Boolean

Whether the body is closed.

Implementation

def closed?
	@queue.closed?
end

def ready?

Signature

returns Boolean

Whether the body is ready to be read from, without blocking.

Implementation

def ready?
	!@queue.empty? || @queue.closed?
end

def empty?

Indicates whether the body is empty. This can occur if the body has been closed, or if the producer has invoked Protocol::HTTP::Body::Writable#close_write and the reader has consumed all available chunks.

Signature

returns Boolean

Whether the body is empty.

Implementation

def empty?
	@queue.empty? && @queue.closed?
end

def read

Read the next available chunk.

Signature

returns String | Nil

The next chunk, or nil if the body is finished.

raises Exception

If the body was closed due to an error.

Implementation

def read
	if @error
		raise @error
	end
	
	# This operation may result in @error being set.
	chunk = @queue.pop
	
	if @error
		raise @error
	end
	
	return chunk
end

def write(chunk)

Write a single chunk to the body. Signal completion by calling Protocol::HTTP::Body::Writable#close_write.

Signature

parameter chunk String

The chunk to write.

raises Closed

If the body has been closed without error.

raises Exception

If the body has been closed due to an error.

Implementation

def write(chunk)
	if @queue.closed?
		raise(@error || Closed)
	end
	
	@queue.push(chunk)
	@count += 1
end

def close_write(error = nil)

Signal that no more data will be written to the body.

Signature

parameter error Exception

The error that caused this body to be closed, if any.

Implementation

def close_write(error = nil)
	@error ||= error
	@queue.close
end

def output

Create an output wrapper which can be used to write chunks to the body.

If a block is given, and the block raises an error, the error will used to close the body by invoking Protocol::HTTP::Body::Writable#close with the error.

Signature

yields {|output| ...}

if a block is given.

parameter output Output

The output wrapper.

returns Output

The output wrapper.

Implementation

def output
	output = Output.new(self)
	
	unless block_given?
		return output
	end
	
	begin
		yield output
	rescue => error
		raise error
	ensure
		output.close(error)
	end
end

def inspect

Inspect the body.

Signature

returns String

A string representation of the body.

Implementation

def inspect
	if @error
		"\#<#{self.class} #{@count} chunks written, #{status}, error=#{@error}>"
	else
		"\#<#{self.class} #{@count} chunks written, #{status}>"
	end
end

def status

Signature

returns String

A string representation of the body's status.

Implementation

def status
	if @queue.empty?
		if @queue.closed?
			"closed"
		else
			"waiting"
		end
	else
		if @queue.closed?
			"closing"
		else
			"ready"
		end
	end
end