HTTP/2 Support

New in version 2.1.0.

Kyoukai comes with built in support for HTTP/2, thanks to to the H2 library.

Enabling HTTP2 requires:

  • TLS/SSL to be enabled
  • h2 to be installed
  • The http2 key in the config to be True, or manual switching to be enabled

Automatic switching

Kyoukai supports automatically upgrading to HTTP/2 via ALPN/NPN protocols (the default for making new connections over TLS) or with plain old h2c.

To enable automatic upgrade, add the http2 key to your config file, under the kyoukai component, like so:

# Enables automatic HTTP/2 connection switching.
# This will switch to the HTTP/2 protocol parser when a connection is created.
http2: true

Now, when connecting over TLS (or HTTP/1.1 with h2c) the connection will be automatically upgraded to a HTTP/2 connection.

Manual switching

It is possible to enforce HTTP/2 only, or otherwise manual switching, with the usage of H2KyoukaiProtocol.

To switch to this component, change KyoukaiComponent to H2KyoukaiComponent in your application component container like so:

self.add_component('kyoukai', H2KyoukaiComponent, ip="127.0.0.1", port=4444,
                app=app)

API Ref

class kyoukai.backends.http2.H2KyoukaiComponent(app, ssl_keyfile: str, ssl_certfile: str, *, ip: str = '127.0.0.1', 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.

get_server_name()
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.

raw_write(data)[source]

Writes to the underlying transport.

connection_made(transport)[source]

Called when a connection is made.

Parameters:transport (WriteTransport) – The transport made by the connection.
data_received(data)[source]

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.

request_received(event)[source]

Called when a request has been received.

window_opened(event)[source]

Called when a control flow window has opened again.

receive_data(event)[source]

Called when a request has data that has been received.

stream_complete(event)[source]

Called when a stream is complete.

This will invoke Kyoukai, which will handle the request.

close(error_code=0)[source]

Called to terminate the connection for some reason.

This will close the underlying transport.

eof_received()

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.

pause_writing()

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).

resume_writing()

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

See pause_writing() for details.

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.

insert_data(data)[source]

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.
read(size=-1)[source]

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

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

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.

get_response_headers()[source]

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