A HTTP/2 interface to Kyoukai.
This uses https://python-hyper.org/projects/h2/en/stable/asyncio-example.html 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 :)
Functions
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. |
urlsplit(url[, scheme, allow_fragments]) |
Parse a URL into 5 components: <scheme>://<netloc>/<path>?<query>#<fragment> Return a 5-tuple: (scheme, netloc, path, query, fragment). |
Classes
Context([parent, default_timeout]) |
Contexts give request handlers and callbacks access to resources. |
DataReceived() |
The DataReceived event is fired whenever data is received on a stream from the remote peer. |
ErrorCodes |
All known HTTP/2 error codes. |
H2Connection([config]) |
A low-level HTTP/2 connection object. |
H2KyoukaiComponent(app, ssl_keyfile, ...[, ...]) |
A component subclass that creates H2KyoukaiProtocol instances. |
H2KyoukaiProtocol(component, parent_context) |
The base protocol for Kyoukai, using H2. |
H2State(headers, stream_id, protocol) |
A temporary class that is used to store request data for a HTTP/2 connection. |
KyoukaiBaseComponent(app[, ip, port]) |
The base class for any component used by Kyoukai. |
MultiDict([mapping]) |
A MultiDict is a dictionary subclass customized to deal with multiple values for the same key which is for example used by the parsing functions in the wrappers. |
Request(environ[, populate_request, shallow]) |
Full featured request object implementing the following mixins: |
RequestReceived() |
The RequestReceived event is fired whenever request headers are received. |
Response([response, status, headers, ...]) |
Full featured response object implementing the following mixins: |
StreamEnded() |
The StreamEnded event is fired whenever a stream is ended by a remote party. |
StreamReset() |
The StreamReset event is fired in two situations. |
WindowUpdated() |
The WindowUpdated event is fired whenever a flow control window changes size. |
partial |
partial(func, *args, **keywords) - new function with partial application |
Exceptions
ProtocolError |
An action was attempted in violation of the HTTP/2 protocol. |
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 |
|---|
kyoukai.backends.http2.create_wsgi_environment(r)[source]¶Creates a new WSGI environment from the RequestData provided.
| Return type: | MultiDict |
|---|
kyoukai.backends.http2.H2State(headers, stream_id, protocol)[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.
read_async(self, 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 |
kyoukai.backends.http2.H2KyoukaiComponent(app, ssl_keyfile, ssl_certfile, *, ip='127.0.0.1', port=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. |
|---|
kyoukai.backends.http2.H2KyoukaiProtocol(component, parent_context)[source]¶Bases: asyncio.protocols.Protocol
The base protocol for Kyoukai, using H2.
connection_made(transport)[source]¶Called when a connection is made.
| Parameters: | transport (WriteTransport) – The transport made by the connection. |
|---|
sending_loop(self, stream_id)[source]¶This loop continues sending data to the client as it comes off of the queue.
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.