A HTTP/2 interface to Kyoukai.

This uses as a reference and a base. Massive thanks to the authors of this page.

This server has some notable pitfalls:

  • It ignores any priority data that is sent by the client.
  • It is not paticularly fast (unbenchmarked, but it can be assumed to be slower than the httptools backend.)
  • It does not fully implement all events.

Additionally, this server is untested - it can and probably will fail horribly in production. Use with caution :)


create_wsgi_environment(r) Creates a new WSGI environment from the RequestData provided.
get_header(headers, name) Gets a header from the list of headers, or None if it doesn’t exist.


H2KyoukaiComponent(app, ssl_keyfile: str, …) A component subclass that creates H2KyoukaiProtocol instances.
H2KyoukaiProtocol(component, …) The base protocol for Kyoukai, using H2.
H2State(headers: list, stream_id, …) A temporary class that is used to store request data for a HTTP/2 connection.
kyoukai.backends.http2.get_header(headers, name)[source]

Gets a header from the list of headers, or None if it doesn’t exist.

Return type:str

Creates a new WSGI environment from the RequestData provided.

Return type:MultiDict
class kyoukai.backends.http2.H2State(headers: list, stream_id, protocol: kyoukai.backends.http2.H2KyoukaiProtocol)[source]

Bases: object

A temporary class that is used to store request data for a HTTP/2 connection.

This is also passed to the Werkzeug request to emit data.


Writes data from the stream into the body.

coroutine read_async(to_end=True)[source]

There’s no good way to do this - WSGI isn’t async, after all.

However, you can use read_async on the Werkzeug request (which we subclass) to wait until the request has finished streaming.

Parameters:to_end – If to_end is specified, then read until the end of the request. Otherwise, it will read one data chunk.

Reads data from the request until it’s all done.

Parameters:size (int) – The maximum amount of data to receive.
Return type:bytes

Gets a chunk of data from the queue.

Return type:bytes
start_response(status, headers, exc_info=None)[source]

The start_response callable that is plugged into a Werkzeug response.


Called by the protocol once the Response is writable to submit the request to the HTTP/2 state machine.

class kyoukai.backends.http2.H2KyoukaiComponent(app, ssl_keyfile: str, ssl_certfile: str, *, ip: str = '', port: int = 4444)[source]

Bases: kyoukai.asphalt.KyoukaiBaseComponent

A component subclass that creates H2KyoukaiProtocol instances.

Creates a new HTTP/2 SSL-based context.

This will use the HTTP/2 protocol, disabling HTTP/1.1 support for this port. It is possible to run two servers side-by-side, one HTTP/2 and one HTTP/1.1, if you run them on different ports.

Returns:The server name of this app.
class kyoukai.backends.http2.H2KyoukaiProtocol(component, parent_context: asphalt.core.context.Context)[source]

Bases: asyncio.protocols.Protocol

The base protocol for Kyoukai, using H2.


Writes to the underlying transport.


Called when a connection is made.

Parameters:transport (WriteTransport) – The transport made by the connection.

Called when data is received from the underlying socket.

_processing_done(environ, stream_id)[source]

Callback for when processing is done on a request.

coroutine sending_loop(stream_id)[source]

This loop continues sending data to the client as it comes off of the queue.


Called when a request has been received.


Called when a control flow window has opened again.


Called when a request has data that has been received.


Called when a stream is complete.

This will invoke Kyoukai, which will handle the request.


Called to terminate the connection for some reason.

This will close the underlying transport.


Called when the other end calls write_eof() or equivalent.

If this returns a false value (including None), the transport will close itself. If it returns a true value, closing the transport is up to the protocol.


Called when the transport’s buffer goes over the high-water mark.

Pause and resume calls are paired – pause_writing() is called once when the buffer goes strictly over the high-water mark (even if subsequent writes increases the buffer size even more), and eventually resume_writing() is called once when the buffer size reaches the low-water mark.

Note that if the buffer size equals the high-water mark, pause_writing() is not called – it must go strictly over. Conversely, resume_writing() is called when the buffer size is equal or lower than the low-water mark. These end conditions are important to ensure that things go as expected when either mark is zero.

NOTE: This is the only Protocol callback that is not called through EventLoop.call_soon() – if it were, it would have no effect when it’s most needed (when the app keeps writing without yielding until pause_writing() is called).


Called when the transport’s buffer drains below the low-water mark.

See pause_writing() for details.