Protocol::HTTPSourceProtocolHTTPBodyStream

class Stream

The input stream is an IO-like object which contains the raw HTTP POST data. When applicable, its external encoding must be “ASCII-8BIT” and it must be opened in binary mode, for Ruby 1.9 compatibility. The input stream must respond to gets, each, read and rewind.

Nested

Definitions

NEWLINE = "\n"

The default line separator, used by gets.

def initialize(input = nil, output = Buffered.new)

Initialize the stream with the given input and output.

Signature

parameter input Readable

The input stream.

parameter output Writable

The output stream.

Implementation

def initialize(input = nil, output = Buffered.new)
	@input = input
	@output = output
	
	raise ArgumentError, "Non-writable output!" unless output.respond_to?(:write)
	
	# Will hold remaining data in `#read`.
	@buffer = nil
	
	@closed = false
	@closed_read = false
end

attr :input

Signature

attribute Readable

The input stream.

attr :output

Signature

attribute Writable

The output stream.

def write(buffer)

Write data to the underlying stream.

Signature

parameter buffer String

The data to write.

raises IOError

If the stream is not writable.

returns Integer

The number of bytes written.

Implementation

def write(buffer)
	if @output
		@output.write(buffer)
		return buffer.bytesize
	else
		raise IOError, "Stream is not writable, output has been closed!"
	end
end

def write_nonblock(buffer, exception: nil)

Write data to the stream using Protocol::HTTP::Body::Stream#write.

Provided for compatibility with IO-like objects.

Signature

parameter buffer String

The data to write.

parameter exception Boolean

Whether to raise an exception if the write would block, currently ignored.

returns Integer

The number of bytes written.

Implementation

def write_nonblock(buffer, exception: nil)
	write(buffer)
end

def <<(buffer)

Write data to the stream using Protocol::HTTP::Body::Stream#write.

Implementation

def <<(buffer)
	write(buffer)
end

def puts(*arguments, separator: NEWLINE)

Write lines to the stream.

The current implementation buffers the lines and writes them in a single operation.

Signature

parameter arguments Array(String)

The lines to write.

parameter separator String

The line separator, defaults to \n.

Implementation

def puts(*arguments, separator: NEWLINE)
	buffer = ::String.new
	
	arguments.each do |argument|
		buffer << argument << separator
	end
	
	write(buffer)
end

def flush

Flush the output stream.

This is currently a no-op.

Implementation

def flush
end

def close_read(error = nil)

Close the input body.

If, while processing the data that was read from this stream, an error is encountered, it should be passed to this method.

Signature

parameter error Exception | Nil

The error that was encountered, if any.

Implementation

def close_read(error = nil)
	if input = @input
		@input = nil
		@closed_read = true
		@buffer = nil
		
		input.close(error)
	end
end

def close_write(error = nil)

Close the output body.

If, while generating the data that is written to this stream, an error is encountered, it should be passed to this method.

Signature

parameter error Exception | Nil

The error that was encountered, if any.

Implementation

def close_write(error = nil)
	if output = @output
		@output = nil
		
		output.close_write(error)
	end
end

def close(error = nil)

Close the input and output bodies.

Signature

parameter error Exception | Nil

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

Implementation

def close(error = nil)
	self.close_read(error)
	self.close_write(error)
	
	return nil
ensure
	@closed = true
end

def closed?

Signature

returns Boolean

Whether the stream has been closed.

Implementation

def closed?
	@closed
end

def empty?

Signature

returns Boolean

Whether there are any output chunks remaining.

Implementation

def empty?
	@output.empty?
end

def read_next

Read the next chunk of data from the input stream.

Signature

returns String

The next chunk of data.

raises IOError

If the input stream was explicitly closed.

Implementation

def read_next
	if @input
		return @input.read
	elsif @closed_read
		raise IOError, "Stream is not readable, input has been closed!"
	end
end