Rename 'hyper-h2' to simply 'h2' (#1246)

This commit is contained in:
Seth Michael Larson
2021-02-23 15:33:13 -06:00
committed by GitHub
parent 5bfbb6742a
commit 94b89b88ed
24 changed files with 137 additions and 135 deletions
+3
View File
@@ -4,6 +4,9 @@ Release History
dev
---
**Note:** The GitHub repository has been renamed to ``python-hyper/h2``, previously
was ``python-hyper/hyper-h2``. **The name of the package on PyPI is unchanged**
**API Changes (Backward Incompatible)**
-
+15 -14
View File
@@ -1,15 +1,15 @@
===============================
hyper-h2: HTTP/2 Protocol Stack
===============================
=========================
h2: HTTP/2 Protocol Stack
=========================
.. image:: https://github.com/python-hyper/hyper-h2/workflows/CI/badge.svg
:target: https://github.com/python-hyper/hyper-h2/actions
.. image:: https://github.com/python-hyper/h2/workflows/CI/badge.svg
:target: https://github.com/python-hyper/h2/actions
:alt: Build Status
.. image:: https://codecov.io/gh/python-hyper/hyper-h2/branch/master/graph/badge.svg
:target: https://codecov.io/gh/python-hyper/hyper-h2
.. image:: https://codecov.io/gh/python-hyper/h2/branch/master/graph/badge.svg
:target: https://codecov.io/gh/python-hyper/h2
:alt: Code Coverage
.. image:: https://readthedocs.org/projects/hyper-h2/badge/?version=latest
:target: https://hyper-h2.readthedocs.io/en/latest/
.. image:: https://readthedocs.org/projects/h2/badge/?version=latest
:target: https://h2.readthedocs.io
:alt: Documentation Status
.. image:: https://img.shields.io/badge/chat-join_now-brightgreen.svg
:target: https://gitter.im/python-hyper/community
@@ -45,17 +45,17 @@ To install it, just run:
.. code-block:: console
$ pip install h2
$ python -m pip install h2
Documentation
=============
Documentation is available at https://hyper-h2.readthedocs.io/ .
Documentation is available at https://h2.readthedocs.io .
Contributing
============
``hyper-h2`` welcomes contributions from anyone! Unlike many other projects we
``h2`` welcomes contributions from anyone! Unlike many other projects we
are happy to accept cosmetic contributions and small contributions, in addition
to large feature requests and changes.
@@ -67,10 +67,11 @@ please `read the contribution guidelines`_.
License
=======
``hyper-h2`` is made available under the MIT License. For more details, see the
``h2`` is made available under the MIT License. For more details, see the
``LICENSE`` file in the repository.
Authors
=======
``hyper-h2`` is maintained by Cory Benfield, with contributions from others.
``h2`` was authored by Cory Benfield and is maintained
by the members of `python-hyper <https://github.com/orgs/python-hyper/people>`_.
+16 -16
View File
@@ -10,7 +10,7 @@ Priority
build a HTTP/2 priority tree, and the effect that should have on sending data
from a server.
Hyper-h2 does not enforce any priority logic by default for servers. This is
h2 does not enforce any priority logic by default for servers. This is
because scheduling data sends is outside the scope of this library, as it
likely requires fairly substantial understanding of the scheduler being used.
@@ -26,7 +26,7 @@ Related Events
.. versionadded:: 2.4.0
In the 2.4.0 release hyper-h2 added support for signaling "related events".
In the 2.4.0 release h2 added support for signaling "related events".
These are a HTTP/2-only construct that exist because certain HTTP/2 events can
occur simultaneously: that is, one HTTP/2 frame can cause multiple state
transitions to occur at the same time. One example of this is a HEADERS frame
@@ -35,17 +35,17 @@ cause three events to fire (one of the various request/response received
events, a :class:`PriorityUpdated <h2.events.PriorityUpdated>` event, and a
:class:`StreamEnded <h2.events.StreamEnded>` event).
Ordinarily hyper-h2's logic will emit those events to you one at a time. This
Ordinarily h2's logic will emit those events to you one at a time. This
means that you may attempt to process, for example, a
:class:`DataReceived <h2.events.DataReceived>` event, not knowing that the next
event out will be a :class:`StreamEnded <h2.events.StreamEnded>` event.
hyper-h2 *does* know this, however, and so will forbid you from taking certain
h2 *does* know this, however, and so will forbid you from taking certain
actions that are a violation of the HTTP/2 protocol.
To avoid this asymmetry of information, events that can occur simultaneously
now carry properties for their "related events". These allow users to find the
events that can have occurred simultaneously with each other before the event
is emitted by hyper-h2. The following objects have "related events":
is emitted by h2. The following objects have "related events":
- :class:`RequestReceived <h2.events.RequestReceived>`:
@@ -96,7 +96,7 @@ is emitted by hyper-h2. The following objects have "related events":
same time as receiving this data.
.. warning:: hyper-h2 does not know if you are looking for related events or
.. warning:: h2 does not know if you are looking for related events or
expecting to find events in the event stream. Therefore, it will
always emit "related events" in the event stream. If you are using
the "related events" event pattern, you will want to be careful to
@@ -167,11 +167,11 @@ When To Send
~~~~~~~~~~~~
In addition to knowing how much data to send (see :ref:`advanced-sending-data`)
it is important to know when to send data. For hyper-h2, this amounts to
it is important to know when to send data. For h2, this amounts to
knowing when to call :meth:`data_to_send
<h2.connection.H2Connection.data_to_send>`.
Hyper-h2 may write data into its send buffer at two times. The first is
h2 may write data into its send buffer at two times. The first is
whenever :meth:`receive_data <h2.connection.H2Connection.receive_data>` is
called. This data is sent in response to some control frames that require no
user input: for example, responding to PING frames. The second time is in
@@ -179,7 +179,7 @@ response to user action: whenever a user calls a method like
:meth:`send_headers <h2.connection.H2Connection.send_headers>`, data may be
written into the buffer.
In a standard design for a hyper-h2 consumer, then, that means there are two
In a standard design for a h2 consumer, then, that means there are two
places where you'll potentially want to send data. The first is in your
"receive data" loop. This is where you take the data you receive, pass it into
:meth:`receive_data <h2.connection.H2Connection.receive_data>`, and then
@@ -240,16 +240,16 @@ Working With Flow Control
~~~~~~~~~~~~~~~~~~~~~~~~~
The amount of flow control window a ``DATA`` frame consumes is the sum of both
its contained application data *and* the amount of padding used. hyper-h2 shows
its contained application data *and* the amount of padding used. h2 shows
this to the user in a :class:`DataReceived <h2.events.DataReceived>` event by
using the :data:`flow_controlled_length
<h2.events.DataReceived.flow_controlled_length>` field. When working with flow
control in hyper-h2, users *must* use this field: simply using
control in h2, users *must* use this field: simply using
``len(datareceived.data)`` can eventually lead to deadlock.
When data has been received and given to the user in a :class:`DataReceived
<h2.events.DataReceived>`, it is the responsibility of the user to re-open the
flow control window when the user is ready for more data. hyper-h2 does not do
flow control window when the user is ready for more data. h2 does not do
this automatically to avoid flooding the user with data: if we did, the remote
peer could send unbounded amounts of data that the user would need to buffer
before processing.
@@ -258,7 +258,7 @@ To re-open the flow control window, then, the user must call
:meth:`increment_flow_control_window
<h2.connection.H2Connection.increment_flow_control_window>` with the
:data:`flow_controlled_length <h2.events.DataReceived.flow_controlled_length>`
of the received data. hyper-h2 requires that you manage both the connection
of the received data. h2 requires that you manage both the connection
and the stream flow control windows separately, so you may need to increment
both the stream the data was received on and stream ``0``.
@@ -269,10 +269,10 @@ flow control windows. You can find out how much data you can send on a given
stream by using the :meth:`local_flow_control_window
<h2.connection.H2Connection.local_flow_control_window>` method, which will do
all of these calculations for you. If you attempt to send more than this amount
of data on a stream, hyper-h2 will throw a :class:`ProtocolError
of data on a stream, h2 will throw a :class:`ProtocolError
<h2.exceptions.ProtocolError>` and refuse to send the data.
In hyper-h2, receiving a ``WINDOW_UPDATE`` frame causes a :class:`WindowUpdated
In h2, receiving a ``WINDOW_UPDATE`` frame causes a :class:`WindowUpdated
<h2.events.WindowUpdated>` event to fire. This will notify you that there is
potentially more room in a flow control window. Note that, just because an
increment of a given size was received *does not* mean that that much more data
@@ -301,7 +301,7 @@ control strategies. While particular high performance or specific-use-case
applications may gain value from directly controlling the emission of
``WINDOW_UPDATE`` frames, the average application can use a
lowest-common-denominator strategy to emit those frames. As of version 2.5.0,
hyper-h2 now provides this automatic strategy for users, if they want to use
h2 now provides this automatic strategy for users, if they want to use
it.
This automatic strategy is built around a single method:
+5 -5
View File
@@ -1,15 +1,15 @@
Hyper-h2 API
============
h2 API
======
This document details the API of Hyper-h2.
This document details the API of h2.
Semantic Versioning
-------------------
Hyper-h2 follows semantic versioning for its public API. Please note that the
h2 follows semantic versioning for its public API. Please note that the
guarantees of semantic versioning apply only to the API that is *documented
here*. Simply because a method or data field is not prefaced by an underscore
does not make it part of Hyper-h2's public API. Anything not documented here is
does not make it part of h2's public API. Anything not documented here is
subject to change at any time.
Connection
+27 -27
View File
@@ -2,7 +2,7 @@ Getting Started: Writing Your Own HTTP/2 Server
===============================================
This document explains how to get started writing fully-fledged HTTP/2
implementations using Hyper-h2 as the underlying protocol stack. It covers the
implementations using h2 as the underlying protocol stack. It covers the
basic concepts you need to understand, and talks you through writing a very
simple HTTP/2 server.
@@ -17,10 +17,10 @@ return to this documentation.
Connections
-----------
Hyper-h2's core object is the
h2's core object is the
:class:`H2Connection <h2.connection.H2Connection>` object. This object is an
abstract representation of the state of a single HTTP/2 connection, and holds
all the important protocol state. When using Hyper-h2, this object will be the
all the important protocol state. When using h2, this object will be the
first thing you create and the object that does most of the heavy lifting.
The interface to this object is relatively simple. For sending data, you
@@ -54,7 +54,7 @@ this document, we'll do just that.
Some important subtleties of ``H2Connection`` objects are covered in
:doc:`advanced-usage`: see :ref:`h2-connection-advanced` for more information.
However, one subtlety should be covered, and that is this: Hyper-h2's
However, one subtlety should be covered, and that is this: h2's
``H2Connection`` object doesn't do I/O. Let's talk briefly about why.
I/O
@@ -74,19 +74,19 @@ into bytes to send. So there's no reason to have lots of different versions of
this core protocol code: one for Twisted, one for gevent, one for threading,
and one for synchronous code.
This is why we said at the top that Hyper-h2 is a *HTTP/2 Protocol Stack*, not
a *fully-fledged implementation*. Hyper-h2 knows how to transform bytes into
This is why we said at the top that h2 is a *HTTP/2 Protocol Stack*, not
a *fully-fledged implementation*. h2 knows how to transform bytes into
events and back, but that's it. The I/O and smarts might be different, but
the core HTTP/2 logic is the same: that's what Hyper-h2 provides.
the core HTTP/2 logic is the same: that's what h2 provides.
Not doing I/O makes Hyper-h2 general, and also relatively simple. It has an
Not doing I/O makes h2 general, and also relatively simple. It has an
easy-to-understand performance envelope, it's easy to test (and as a result
easy to get correct behaviour out of), and it behaves in a reproducible way.
These are all great traits to have in a library that is doing something quite
complex.
This document will talk you through how to build a relatively simple HTTP/2
implementation using Hyper-h2, to give you an understanding of where it fits in
implementation using h2, to give you an understanding of where it fits in
your software.
@@ -99,7 +99,7 @@ When writing a HTTP/2 implementation it's important to know what the remote
peer is doing: if you didn't care, writing networked programs would be a lot
easier!
Hyper-h2 encodes the actions of the remote peer in the form of *events*. When
h2 encodes the actions of the remote peer in the form of *events*. When
you receive data from the remote peer and pass it into your ``H2Connection``
object (see :ref:`h2-connection-basic`), the ``H2Connection`` returns a list
of objects, each one representing a single event that has occurred. Each
@@ -112,11 +112,11 @@ concept, not just a HTTP/2 one. Other events are extremely HTTP/2-specific:
for example, :class:`PushedStreamReceived <h2.events.PushedStreamReceived>`
refers to Server Push, a very HTTP/2-specific concept.
The reason these events exist is that Hyper-h2 is intended to be very general.
This means that, in many cases, Hyper-h2 does not know exactly what to do in
The reason these events exist is that h2 is intended to be very general.
This means that, in many cases, h2 does not know exactly what to do in
response to an event. Your code will need to handle these events, and make
decisions about what to do. That's the major role of any HTTP/2 implementation
built on top of Hyper-h2.
built on top of h2.
A full list of events is available in :ref:`h2-events-api`. For the purposes
of this example, we will handle only a small set of events.
@@ -129,7 +129,7 @@ Armed with the knowledge you just obtained, we're going to write a very simple
HTTP/2 web server. The goal of this server is to write a server that can handle
a HTTP GET, and that returns the headers sent by the client, encoded in JSON.
Basically, something a lot like `httpbin.org/get`_. Nothing fancy, but this is
a good way to get a handle on how you should interact with Hyper-h2.
a good way to get a handle on how you should interact with h2.
For the sake of simplicity, we're going to write this using the Python standard
library, in Python 3. In reality, you'll probably want to use an asynchronous
@@ -137,7 +137,7 @@ framework of some kind: see the `examples directory`_ in the repository for
some examples of how you'd do that.
Before we start, create a new file called ``h2server.py``: we'll use that as
our workspace. Additionally, you should install Hyper-h2: follow the
our workspace. Additionally, you should install h2: follow the
instructions in :doc:`installation`.
Step 1: Sockets
@@ -324,7 +324,7 @@ Let's do that next.
Step 3: Sending the Preamble
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Hyper-h2 makes doing connection setup really easy. All you need to do is call
h2 makes doing connection setup really easy. All you need to do is call
the
:meth:`initiate_connection <h2.connection.H2Connection.initiate_connection>`
method, and then send the corresponding data. Let's update our ``handle``
@@ -348,7 +348,7 @@ new method in there:
:meth:`data_to_send <h2.connection.H2Connection.data_to_send>`.
When you make function calls on your ``H2Connection`` object, these will often
want to cause HTTP/2 data to be written out to the network. But Hyper-h2
want to cause HTTP/2 data to be written out to the network. But h2
doesn't do any I/O, so it can't do that itself. Instead, it writes it to an
internal buffer. You can retrieve data from this buffer using the
``data_to_send`` method. There are some subtleties about that method, but we
@@ -477,17 +477,17 @@ there: ``:status``. This is a HTTP/2-specific header, and it's used to hold the
HTTP status code that used to go at the top of a HTTP response. Here, we're
saying the response is ``200 OK``, which is successful.
To send headers in Hyper-h2, you use the
To send headers in h2, you use the
:meth:`send_headers <h2.connection.H2Connection.send_headers>` function.
Next, we want to send the body data. To do that, we use the
:meth:`send_data <h2.connection.H2Connection.send_data>` function. This also
takes a stream ID. Note that the data is binary: Hyper-h2 does not work with
takes a stream ID. Note that the data is binary: h2 does not work with
unicode strings, so you *must* pass bytestrings to the ``H2Connection``. The
one exception is headers: Hyper-h2 will automatically encode those into UTF-8.
one exception is headers: h2 will automatically encode those into UTF-8.
The last thing to note is that on our call to ``send_data``, we set
``end_stream`` to ``True``. This tells Hyper-h2 (and the remote peer) that
``end_stream`` to ``True``. This tells h2 (and the remote peer) that
we're done with sending data: the response is over. Because we know that
``hyper`` will have ended its side of the stream, when we end ours the stream
will be totally done with.
@@ -703,7 +703,7 @@ see something like the following output from ``hyper``:
Here you can see the HTTP/2 request 'special headers' that ``hyper`` sends.
These are similar to the ``:status`` header we have to send on our response:
they encode important parts of the HTTP request in a clearly-defined way. If
you were writing a client stack using Hyper-h2, you'd need to make sure you
you were writing a client stack using h2, you'd need to make sure you
were sending those headers.
Congratulations!
@@ -737,10 +737,10 @@ it, there are a few directions you could investigate:
.. _event loop: https://en.wikipedia.org/wiki/Event_loop
.. _httpbin.org/get: https://httpbin.org/get
.. _examples directory: https://github.com/python-hyper/hyper-h2/tree/master/examples
.. _standard library's socket module: https://docs.python.org/3.5/library/socket.html
.. _examples directory: https://github.com/python-hyper/h2/tree/master/examples
.. _standard library's socket module: https://docs.python.org/3/library/socket.html
.. _Application Layer Protocol Negotiation: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation
.. _get your certificate here: https://raw.githubusercontent.com/python-hyper/hyper-h2/master/examples/twisted/server.crt
.. _get your private key here: https://raw.githubusercontent.com/python-hyper/hyper-h2/master/examples/twisted/server.key
.. _get your certificate here: https://raw.githubusercontent.com/python-hyper/h2/master/examples/twisted/server.crt
.. _get your private key here: https://raw.githubusercontent.com/python-hyper/h2/master/examples/twisted/server.key
.. _PyOpenSSL: http://pyopenssl.readthedocs.org/
.. _Eventlet example: https://github.com/python-hyper/hyper-h2/blob/master/examples/eventlet/eventlet-server.py
.. _Eventlet example: https://github.com/python-hyper/h2/blob/master/examples/eventlet/eventlet-server.py
+1 -1
View File
@@ -6,7 +6,7 @@ example of how to build a concurrent networking framework using Python 3.5's
new ``async``/``await`` syntax.
This example is notable for demonstrating the correct use of HTTP/2 flow
control with Hyper-h2. It is also a good example of the brand new syntax.
control with h2. It is also a good example of the brand new syntax.
.. literalinclude:: ../../examples/curio/curio-server.py
:language: python
+1 -1
View File
@@ -3,7 +3,7 @@ Code Examples
This section of the documentation contains long-form code examples. These are
intended as references for developers that would like to get an understanding
of how Hyper-h2 fits in with various Python I/O frameworks.
of how h2 fits in with various Python I/O frameworks.
Example Servers
---------------
+1 -1
View File
@@ -7,7 +7,7 @@ to provide a high-level synchronous API on top of the `libev`_ or `libuv`_
event loop.
This example is inspired by the curio one and also demonstrates the correct use
of HTTP/2 flow control with Hyper-h2 and how gevent can be simple to use.
of HTTP/2 flow control with h2 and how gevent can be simple to use.
.. literalinclude:: ../../examples/gevent/gevent-server.py
:language: python
+5 -5
View File
@@ -3,14 +3,14 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Hyper-h2: A pure-Python HTTP/2 protocol stack
=============================================
h2: A pure-Python HTTP/2 protocol stack
=======================================
Hyper-h2 is a HTTP/2 protocol stack, written entirely in Python. The goal of
Hyper-h2 is to be a common HTTP/2 stack for the Python ecosystem,
h2 is a HTTP/2 protocol stack, written entirely in Python. The goal of
h2 is to be a common HTTP/2 stack for the Python ecosystem,
usable in all programs regardless of concurrency model or environment.
To achieve this, Hyper-h2 is entirely self-contained: it does no I/O of any
To achieve this, h2 is entirely self-contained: it does no I/O of any
kind, leaving that up to a wrapper library to control. This ensures that it can
seamlessly work in all kinds of environments, from single-threaded code to
Twisted.
+3 -3
View File
@@ -1,12 +1,12 @@
Installation
============
Hyper-h2 is a pure-python project. This means installing it is extremely
h2 is a pure-python project. This means installing it is extremely
simple. To get the latest release from PyPI, simply run:
.. code-block:: console
$ pip install h2
$ python -m pip install h2
Alternatively, feel free to download one of the release tarballs from
`our GitHub page`_, extract it to your favourite directory, and then run
@@ -15,4 +15,4 @@ Alternatively, feel free to download one of the release tarballs from
$ python setup.py install
.. _our GitHub page: https://github.com/python-hyper/hyper-h2
.. _our GitHub page: https://github.com/python-hyper/h2
+10 -10
View File
@@ -2,16 +2,16 @@ Low-Level Details
=================
.. warning:: This section of the documentation covers low-level implementation
details of hyper-h2. This is most likely to be of use to hyper-h2
details of h2. This is most likely to be of use to h2
developers and to other HTTP/2 implementers, though it could well
be of general interest. Feel free to peruse it, but if you're
looking for information about how to *use* hyper-h2 you should
looking for information about how to *use* h2 you should
consider looking elsewhere.
State Machines
--------------
hyper-h2 is fundamentally built on top of a pair of interacting Finite State
h2 is fundamentally built on top of a pair of interacting Finite State
Machines. One of these FSMs manages per-connection state, and another manages
per-stream state. Almost without exception (see :ref:`priority` for more
details) every single frame is unconditionally translated into events for
@@ -96,7 +96,7 @@ The other action taken by the side-effect functions defined here is returning
:ref:`events <h2-events-basic>`. Most of these events are returned directly to
the user, and reflect the specific state transition that has taken place, but
some of the events are purely *internal*: they are used to signal to other
parts of the hyper-h2 codebase what action has been taken.
parts of the h2 codebase what action has been taken.
The major use of the internal events functionality at this time is for
validating header blocks: there are different rules for request headers than
@@ -105,7 +105,7 @@ internal events are used to determine *exactly what* kind of data the user is
attempting to send, and using that information to do the correct kind of
validation. This approach ensures that the final source of truth about what's
happening at the protocol level lives inside the FSM, which is an extremely
important design principle we want to continue to enshrine in hyper-h2.
important design principle we want to continue to enshrine in h2.
A visual representation of this FSM is shown below:
@@ -139,20 +139,20 @@ situation where it is invalid to receive a ``PRIORITY`` frame. This means that
including it in the stream FSM would require that we allow ``SEND_PRIORITY``
and ``RECV_PRIORITY`` in all states.
This is not a totally onerous task: however, another key note is that hyper-h2
This is not a totally onerous task: however, another key note is that h2
uses the *absence* of a stream state machine to flag a closed stream. This is
primarily for memory conservation reasons: if we needed to keep around an FSM
for every stream we've ever seen, that would cause long-lived HTTP/2
connections to consume increasingly large amounts of memory. On top of this,
it would require us to create a stream FSM each time we received a ``PRIORITY``
frame for a given stream, giving a malicious peer an easy route to force a
hyper-h2 user to allocate nearly unbounded amounts of memory.
h2 user to allocate nearly unbounded amounts of memory.
For this reason, hyper-h2 circumvents the stream FSM entirely for ``PRIORITY``
For this reason, h2 circumvents the stream FSM entirely for ``PRIORITY``
frames. Instead, these frames are treated as being connection-level frames that
*just happen* to identify a specific stream. They do not bring streams into
being, or in any sense interact with hyper-h2's view of streams. Their stream
details are treated as strictly metadata that hyper-h2 is not interested in
being, or in any sense interact with h2's view of streams. Their stream
details are treated as strictly metadata that h2 is not interested in
beyond being able to parse it out.
+7 -7
View File
@@ -1,7 +1,7 @@
Negotiating HTTP/2
==================
`RFC 7540`_ specifies three methods of negotiating HTTP/2 connections. This document outlines how to use Hyper-h2 with each one.
`RFC 7540`_ specifies three methods of negotiating HTTP/2 connections. This document outlines how to use h2 with each one.
.. _starting-alpn:
@@ -10,12 +10,12 @@ HTTPS URLs (ALPN)
Starting HTTP/2 for HTTPS URLs is outlined in `RFC 7540 Section 3.3`_. In this case, the client and server use a TLS extension to negotiate HTTP/2: `ALPN`_. How to use ALPN is currently not covered in this document: please consult the documentation for either the :mod:`ssl module <python:ssl>` in the standard library, or the :mod:`PyOpenSSL <pyopenssl:OpenSSL.SSL>` third-party modules, for more on this topic.
This method is the simplest to use once the TLS connection is established. To use it with Hyper-h2, after you've established the connection and confirmed that HTTP/2 has been negotiated with `ALPN`_, create a :class:`H2Connection <h2.connection.H2Connection>` object and call :meth:`H2Connection.initiate_connection <h2.connection.H2Connection.initiate_connection>`. This will ensure that the appropriate preamble data is placed in the data buffer. You should then immediately send the data returned by :meth:`H2Connection.data_to_send <h2.connection.H2Connection.data_to_send>` on your TLS connection.
This method is the simplest to use once the TLS connection is established. To use it with h2, after you've established the connection and confirmed that HTTP/2 has been negotiated with `ALPN`_, create a :class:`H2Connection <h2.connection.H2Connection>` object and call :meth:`H2Connection.initiate_connection <h2.connection.H2Connection.initiate_connection>`. This will ensure that the appropriate preamble data is placed in the data buffer. You should then immediately send the data returned by :meth:`H2Connection.data_to_send <h2.connection.H2Connection.data_to_send>` on your TLS connection.
At this point, you're free to use all the HTTP/2 functionality provided by Hyper-h2.
At this point, you're free to use all the HTTP/2 functionality provided by h2.
.. note::
Although Hyper-h2 is not concerned with negotiating protocol versions, it is important to note that support for `ALPN`_ is not available in the standard library of Python versions < 2.7.9.
Although h2 is not concerned with negotiating protocol versions, it is important to note that support for `ALPN`_ is not available in the standard library of Python versions < 2.7.9.
As a consequence, clients may encounter various errors due to protocol versions mismatch.
Server Setup Example
@@ -47,18 +47,18 @@ HTTP URLs (Upgrade)
Starting HTTP/2 for HTTP URLs is outlined in `RFC 7540 Section 3.2`_. In this case, the client and server use the HTTP Upgrade mechanism originally described in `RFC 7230 Section 6.7`_. The client sends its initial HTTP/1.1 request with two extra headers. The first is ``Upgrade: h2c``, which requests upgrade to cleartext HTTP/2. The second is a ``HTTP2-Settings`` header, which contains a specially formatted string that encodes a HTTP/2 Settings frame.
To do this with Hyper-h2 you have two slightly different flows: one for clients, one for servers.
To do this with h2 you have two slightly different flows: one for clients, one for servers.
Clients
~~~~~~~
For a client, when sending the first request you should manually add your ``Upgrade`` header. You should then create a :class:`H2Connection <h2.connection.H2Connection>` object and call :meth:`H2Connection.initiate_upgrade_connection <h2.connection.H2Connection.initiate_upgrade_connection>` with no arguments. This method will return a bytestring to use as the value of your ``HTTP2-Settings`` header.
If the server returns a ``101`` status code, it has accepted the upgrade, and you should immediately send the data returned by :meth:`H2Connection.data_to_send <h2.connection.H2Connection.data_to_send>`. Now you should consume the entire ``101`` header block. All data after the ``101`` header block is HTTP/2 data that should be fed directly to :meth:`H2Connection.receive_data <h2.connection.H2Connection.receive_data>` and handled as normal with Hyper-h2.
If the server returns a ``101`` status code, it has accepted the upgrade, and you should immediately send the data returned by :meth:`H2Connection.data_to_send <h2.connection.H2Connection.data_to_send>`. Now you should consume the entire ``101`` header block. All data after the ``101`` header block is HTTP/2 data that should be fed directly to :meth:`H2Connection.receive_data <h2.connection.H2Connection.receive_data>` and handled as normal with h2.
If the server does not return a ``101`` status code then it is not upgrading. Continue with HTTP/1.1 as normal: you may throw away your :class:`H2Connection <h2.connection.H2Connection>` object, as it is of no further use.
The server will respond to your original request in HTTP/2. Please pay attention to the events received from Hyper-h2, as they will define the server's response.
The server will respond to your original request in HTTP/2. Please pay attention to the events received from h2, as they will define the server's response.
Client Example
^^^^^^^^^^^^^^
+5 -5
View File
@@ -1,15 +1,15 @@
Release Process
===============
Because of Hyper-h2's place at the bottom of the dependency tree, it is
Because of h2's place at the bottom of the dependency tree, it is
extremely important that the project maintains a diligent release schedule.
This document outlines our process for managing releases.
Versioning
----------
Hyper-h2 follows `semantic versioning`_ of its public API when it comes to
numbering releases. The public API of Hyper-h2 is strictly limited to the
h2 follows `semantic versioning`_ of its public API when it comes to
numbering releases. The public API of h2 is strictly limited to the
entities listed in the :doc:`api` documentation: anything not mentioned in that
document is not considered part of the public API and is not covered by the
versioning guarantees given by semantic versioning.
@@ -17,7 +17,7 @@ versioning guarantees given by semantic versioning.
Maintenance
-----------
Hyper-h2 has the notion of a "release series", given by a major and minor
h2 has the notion of a "release series", given by a major and minor
version number: for example, there is the 2.1 release series. When each minor
release is made and a release series is born, a branch is made off the release
tag: for example, for the 2.1 release series, the 2.1.X branch.
@@ -32,7 +32,7 @@ backported.
Supported Release Series'
-------------------------
The developers of Hyper-h2 commit to supporting the following release series:
The developers of h2 commit to supporting the following release series:
- The most recent, as identified by the first two numbers in the highest
version currently released.
+1 -1
View File
@@ -10,7 +10,7 @@ shortcuts have been taken to ensure ease of implementation and understanding.
The main advantages of this example are:
1. It properly demonstrates HTTP/2 flow control management.
2. It demonstrates how to plug hyper-h2 into a larger, more complex
2. It demonstrates how to plug h2 into a larger, more complex
application.
+2 -2
View File
@@ -3,13 +3,13 @@
asyncio-server.py
~~~~~~~~~~~~~~~~~
A fully-functional WSGI server, written using hyper-h2. Requires asyncio.
A fully-functional WSGI server, written using h2. Requires asyncio.
To test it, try installing httpbin from pip (``pip install httpbin``) and then
running the server (``python asyncio-server.py httpbin:app``).
This server does not support HTTP/1.1: it is a HTTP/2-only WSGI server. The
purpose of this code is to demonstrate how to integrate hyper-h2 into a more
purpose of this code is to demonstrate how to integrate h2 into a more
complex application, and to demonstrate several principles of concurrent
programming.
-1
View File
@@ -94,7 +94,6 @@ class H2Protocol(Protocol):
(':authority', AUTHORITY),
(':scheme', 'https'),
(':path', PATH),
('user-agent', 'hyper-h2/1.0.0'),
]
self.conn.send_headers(1, request_headers, end_stream=True)
self.request_made = True
-1
View File
@@ -174,7 +174,6 @@ class H2Protocol(Protocol):
(':authority', AUTHORITY),
(':scheme', 'https'),
(':path', PATH),
('user-agent', 'hyper-h2/1.0.0'),
('content-length', str(self.file_size)),
]
+1 -1
View File
@@ -30,7 +30,7 @@ setup(
long_description_content_type='text/x-rst',
author='Cory Benfield',
author_email='cory@lukasa.co.uk',
url='https://github.com/python-hyper/hyper-h2',
url='https://github.com/python-hyper/h2',
packages=find_packages(where="src"),
package_data={'': ['LICENSE', 'README.rst', 'CHANGELOG.rst']},
package_dir={'': 'src'},
+1 -1
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""
hyper-h2
h2
~~
A HTTP/2 implementation.
+2 -2
View File
@@ -30,7 +30,7 @@ class DummyLogger:
An Logger object that does not actual logging, hence a DummyLogger.
For the class the log operation is merely a no-op. The intent is to avoid
conditionals being sprinkled throughout the hyper-h2 code for calls to
conditionals being sprinkled throughout the h2 code for calls to
logging functions when no logger is passed into the corresponding object.
"""
def __init__(self, *vargs):
@@ -101,7 +101,7 @@ class H2Configuration:
:param normalize_inbound_headers: Controls whether the headers received by
this object are normalized according to the rules of RFC 7540.
Disabling this setting may lead to hyper-h2 emitting header blocks that
Disabling this setting may lead to h2 emitting header blocks that
some RFCs forbid, e.g. with multiple cookie fields.
.. versionadded:: 3.0.0
+12 -12
View File
@@ -806,8 +806,8 @@ class H2Connection:
:class:`FrameTooLargeError <h2.exceptions.FrameTooLargeError>` will be
raised.
Hyper-h2 does this to avoid buffering the data internally. If the user
has more data to send than hyper-h2 will allow, consider breaking it up
h2 does this to avoid buffering the data internally. If the user
has more data to send than h2 will allow, consider breaking it up
and buffering it externally.
:param stream_id: The ID of the stream on which to send the data.
@@ -1097,10 +1097,10 @@ class H2Connection:
The explicit method of advertising can be done as long as the
connection is active. The implicit method can only be done after the
client has sent the request headers and before the server has sent the
response headers: outside of those points, Hyper-h2 will forbid sending
response headers: outside of those points, h2 will forbid sending
the Alternative Service advertisement by raising a ProtocolError.
The ``field_value`` parameter is specified in RFC 7838. Hyper-h2 does
The ``field_value`` parameter is specified in RFC 7838. h2 does
not validate or introspect this argument: the user is required to
ensure that it's well-formed. ``field_value`` corresponds to RFC 7838's
"Alternative Service Field Value".
@@ -1109,13 +1109,13 @@ class H2Connection:
advertising Alternative Services. The implicit method of
advertising Alternative Services has a number of subtleties
and can lead to inconsistencies between the server and
client. Hyper-h2 allows both mechanisms, but caution is
client. h2 allows both mechanisms, but caution is
strongly advised.
.. versionadded:: 2.3.0
:param field_value: The RFC 7838 Alternative Service Field Value. This
argument is not introspected by Hyper-h2: the user is responsible
argument is not introspected by h2: the user is responsible
for ensuring that it is well-formed.
:type field_value: ``bytes``
@@ -1173,17 +1173,17 @@ class H2Connection:
stream is closed.
.. warning:: RFC 7540 allows for servers to change the priority of
streams. However, hyper-h2 **does not** allow server
streams. However, h2 **does not** allow server
stacks to do this. This is because most clients do not
adequately know how to respond when provided conflicting
priority information, and relatively little utility is
provided by making that functionality available.
.. note:: hyper-h2 **does not** maintain any information about the
RFC 7540 priority tree. That means that hyper-h2 does not
.. note:: h2 **does not** maintain any information about the
RFC 7540 priority tree. That means that h2 does not
prevent incautious users from creating invalid priority
trees, particularly by creating priority loops. While some
basic error checking is provided by hyper-h2, users are
basic error checking is provided by h2, users are
strongly recommended to understand their prioritisation
strategies before using the priority tools here.
@@ -2028,9 +2028,9 @@ def _add_frame_priority(frame, weight=None, depends_on=None, exclusive=None):
def _decode_headers(decoder, encoded_header_block):
"""
Decode a HPACK-encoded header block, translating HPACK exceptions into
sensible hyper-h2 errors.
sensible h2 errors.
This only ever returns bytestring headers: hyper-h2 may emit them as
This only ever returns bytestring headers: h2 may emit them as
unicode later, but internally it processes them as bytestrings only.
"""
try:
+11 -11
View File
@@ -311,7 +311,7 @@ class RemoteSettingsChanged(Event):
its settings. It contains a complete inventory of changed settings,
including their previous values.
In HTTP/2, settings changes need to be acknowledged. hyper-h2 automatically
In HTTP/2, settings changes need to be acknowledged. h2 automatically
acknowledges settings changes for efficiency. However, it is possible that
the caller may not be happy with the changed setting.
@@ -322,7 +322,7 @@ class RemoteSettingsChanged(Event):
.. versionchanged:: 2.0.0
Prior to this version the user needed to acknowledge settings changes.
This is no longer the case: hyper-h2 now automatically acknowledges
This is no longer the case: h2 now automatically acknowledges
them.
"""
def __init__(self):
@@ -414,10 +414,10 @@ class StreamReset(Event):
The StreamReset event is fired in two situations. The first is when the
remote party forcefully resets the stream. The second is when the remote
party has made a protocol error which only affects a single stream. In this
case, Hyper-h2 will terminate the stream early and return this event.
case, h2 will terminate the stream early and return this event.
.. versionchanged:: 2.0.0
This event is now fired when Hyper-h2 automatically resets a stream.
This event is now fired when h2 automatically resets a stream.
"""
def __init__(self):
#: The Stream ID of the stream that was reset.
@@ -561,12 +561,12 @@ class AlternativeServiceAvailable(Event):
This event always carries the origin to which the ALTSVC information
applies. That origin is either supplied by the server directly, or inferred
by hyper-h2 from the ``:authority`` pseudo-header field that was sent by
by h2 from the ``:authority`` pseudo-header field that was sent by
the user when initiating a given stream.
This event also carries what RFC 7838 calls the "Alternative Service Field
Value", which is formatted like a HTTP header field and contains the
relevant alternative service information. Hyper-h2 does not parse or in any
relevant alternative service information. h2 does not parse or in any
way modify that information: the user is required to do that.
This event can only be fired on the client end of a connection.
@@ -576,13 +576,13 @@ class AlternativeServiceAvailable(Event):
def __init__(self):
#: The origin to which the alternative service field value applies.
#: This field is either supplied by the server directly, or inferred by
#: hyper-h2 from the ``:authority`` pseudo-header field that was sent
#: h2 from the ``:authority`` pseudo-header field that was sent
#: by the user when initiating the stream on which the frame was
#: received.
self.origin = None
#: The ALTSVC field value. This contains information about the HTTP
#: alternative service being advertised by the server. Hyper-h2 does
#: alternative service being advertised by the server. h2 does
#: not parse this field: it is left exactly as sent by the server. The
#: structure of the data in this field is given by `RFC 7838 Section 3
#: <https://tools.ietf.org/html/rfc7838#section-3>`_.
@@ -600,11 +600,11 @@ class AlternativeServiceAvailable(Event):
class UnknownFrameReceived(Event):
"""
The UnknownFrameReceived event is fired when the remote peer sends a frame
that hyper-h2 does not understand. This occurs primarily when the remote
peer is employing HTTP/2 extensions that hyper-h2 doesn't know anything
that h2 does not understand. This occurs primarily when the remote
peer is employing HTTP/2 extensions that h2 doesn't know anything
about.
RFC 7540 requires that HTTP/2 implementations ignore these frames. hyper-h2
RFC 7540 requires that HTTP/2 implementations ignore these frames. h2
does so. However, this event is fired to allow implementations to perform
special processing on those frames if needed (e.g. if the implementation
is capable of handling the frame itself).
+1 -1
View File
@@ -528,7 +528,7 @@ class H2StreamStateMachine:
# For this reason, our state machine implementation below allows for
# PUSH_PROMISE frames both in the IDLE state (as in the diagram), but also
# in the OPEN, HALF_CLOSED_LOCAL, and HALF_CLOSED_REMOTE states.
# Essentially, for hyper-h2, PUSH_PROMISE frames are effectively sent on
# Essentially, for h2, PUSH_PROMISE frames are effectively sent on
# two streams.
#
# The _transitions dictionary contains a mapping of tuples of
+7 -7
View File
@@ -4,17 +4,17 @@ State Machine Visualizer
~~~~~~~~~~~~~~~~~~~~~~~~
This code provides a module that can use graphviz to visualise the state
machines included in hyper-h2. These visualisations can be used as part of the
documentation of hyper-h2, and as a reference material to understand how the
machines included in h2. These visualisations can be used as part of the
documentation of h2, and as a reference material to understand how the
state machines function.
The code in this module is heavily inspired by code in Automat, which can be
found here: https://github.com/glyph/automat. For details on the licensing of
Automat, please see the NOTICES.visualizer file in this folder.
This module is very deliberately not shipped with the rest of hyper-h2. This is
because it is of minimal value to users who are installing hyper-h2: its use
is only really for the developers of hyper-h2.
This module is very deliberately not shipped with the rest of h2. This is
because it is of minimal value to users who are installing h2: its use
is only really for the developers of h2.
"""
import argparse
import collections
@@ -200,13 +200,13 @@ def build_digraph(state_machine):
def main():
"""
Renders all the state machines in hyper-h2 into images.
Renders all the state machines in h2 into images.
"""
program_name = sys.argv[0]
argv = sys.argv[1:]
description = """
Visualize hyper-h2 state machines as graphs.
Visualize h2 state machines as graphs.
"""
epilog = """
You must have the graphviz tool suite installed. Please visit