class Server
An HTTP/2 server connection that receives requests and sends responses.
Definitions
def initialize(stream)
Initialize the HTTP/2 server with an IO stream.
Signature
-
parameter
streamIO::Stream The underlying stream.
Implementation
def initialize(stream)
# Used by some generic methods in Connetion:
@stream = stream
framer = ::Protocol::HTTP2::Framer.new(stream)
super(framer)
@requests = Async::Queue.new
end
def accept_stream(stream_id)
Accept a new stream from a client.
Signature
-
parameter
stream_idInteger The stream ID assigned by the client.
Implementation
def accept_stream(stream_id)
super do
Request::Stream.create(self, stream_id)
end
end
def close(error = nil)
Close the server connection and stop accepting requests.
Implementation
def close(error = nil)
if @requests
# Stop the request loop:
@requests.enqueue(nil)
@requests = nil
end
super
end
def each(task: Task.current)
Enumerate incoming requests, yielding each one for processing.
Signature
-
yields
{|request| ...} Each incoming request.
-
parameter
requestRequest The incoming HTTP/2 request.
-
parameter
Implementation
def each(task: Task.current)
task.annotate("Reading #{version} requests for #{self.class}.")
# It's possible the connection has died before we get here...
@requests&.async do |task, request|
task.annotate("Incoming request: #{request.method} #{request.path.inspect}.")
response = nil
task.defer_stop do
response = yield(request)
rescue
# We need to close the stream if the user code blows up while generating a response:
request.stream.send_reset_stream(::Protocol::HTTP2::INTERNAL_ERROR)
raise
else
request.send_response(response)
# If send response is successful, we clear it so that we don't close it below.
response = nil
ensure
# If some failure occurs and we didn't send the response correctly, ensure that it's closed:
response&.close
end
end
# Maybe we should add some synchronisation here - i.e. only exit once all requests are finished.
end