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
requestProtocol::HTTP::Request The request to hijack.
-
parameter
statusInteger The HTTP status code.
-
parameter
headersHash 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
requestProtocol::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
blockProc The block to call with the stream.
-
parameter
inputProtocol::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
streamProtocol::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