Async::HTTPSourceAsyncHTTPBodyHijack

class Hijack

A body which is designed for hijacked server responses - a response which uses a block to read and write the request and response bodies respectively.

Definitions

def self.response(request, status, headers, &block)

Create a response with this hijacked body.

Signature

parameter request Protocol::HTTP::Request

The request to hijack.

parameter status Integer

The HTTP status code.

parameter headers Hash

The response headers.

returns Protocol::HTTP::Response

The response with the hijacked body.

Implementation

def self.response(request, status, headers, &block)
	::Protocol::HTTP::Response[status, headers, self.wrap(request, &block)]
end

def self.wrap(request = nil, &block)

Wrap a request body with a hijacked body.

Signature

parameter request Protocol::HTTP::Request | Nil

The request to hijack.

returns Hijack

The hijacked body instance.

Implementation

def self.wrap(request = nil, &block)
	self.new(block, request&.body)
end

def initialize(block, input = nil)

Initialize the hijacked body.

Signature

parameter block Proc

The block to call with the stream.

parameter input Protocol::HTTP::Body::Readable | Nil

The input body to read from.

Implementation

def initialize(block, input = nil)
	@block = block
	@input = input
	
	@task = nil
	@stream = nil
	@output = nil
end

def stream?

We prefer streaming directly as it's the lowest overhead.

Implementation

def stream?
	true
end

def call(stream)

Invoke the block with the given stream for bidirectional communication.

Signature

parameter stream Protocol::HTTP::Body::Stream

The stream to pass to the block.

Implementation

def call(stream)
	@block.call(stream)
end

def empty?

Has the producer called #finish and has the reader consumed the nil token?

Implementation

def empty?
	@output&.empty?
end

def ready?

Whether the body has output ready to be read.

Signature

returns Boolean | Nil

Implementation

def ready?
	@output&.ready?
end

def read

Read the next available chunk.

Implementation

def read
	unless @output
		@output = Writable.new
		@stream = ::Protocol::HTTP::Body::Stream.new(@input, @output)
		
		@task = Task.current.async do |task|
			task.annotate "Streaming hijacked body."
			
			@block.call(@stream)
		end
	end
	
	return @output.read
end

def inspect

Signature

returns String

A detailed representation of this body.

Implementation

def inspect
	"\#<#{self.class} #{@block.inspect}>"
end

def to_s

Signature

returns String

A short summary of this body.

Implementation

def to_s
	"<Hijack #{@block.class}>"
end