new
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
Priority: A HTTP/2 Priority Implementation
|
||||
==========================================
|
||||
|
||||
Priority is a pure-Python implementation of the priority logic for HTTP/2, set
|
||||
out in `RFC 7540 Section 5.3 (Stream Priority)`_. This logic allows for clients
|
||||
to express a preference for how the server allocates its (limited) resources to
|
||||
the many outstanding HTTP requests that may be running over a single HTTP/2
|
||||
connection.
|
||||
|
||||
Specifically, this Python implementation uses a variant of the implementation
|
||||
used in the excellent `H2O`_ project. This original implementation is also the
|
||||
inspiration for `nghttp2's`_ priority implementation, and generally produces a
|
||||
very clean and even priority stream. The only notable changes from H2O's
|
||||
implementation are small modifications to allow the priority implementation to
|
||||
work cleanly as a separate implementation, rather than being embedded in a
|
||||
HTTP/2 stack directly.
|
||||
|
||||
While priority information in HTTP/2 is only a suggestion, rather than an
|
||||
enforceable constraint, where possible servers should respect the priority
|
||||
requests of their clients.
|
||||
|
||||
Using Priority
|
||||
--------------
|
||||
|
||||
Priority has a simple API. Streams are inserted into the tree: when they are
|
||||
inserted, they may optionally have a weight, depend on another stream, or
|
||||
become an exclusive dependent of another stream.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> p = priority.PriorityTree()
|
||||
>>> p.insert_stream(stream_id=1)
|
||||
>>> p.insert_stream(stream_id=3)
|
||||
>>> p.insert_stream(stream_id=5, depends_on=1)
|
||||
>>> p.insert_stream(stream_id=7, weight=32)
|
||||
>>> p.insert_stream(stream_id=9, depends_on=7, weight=8)
|
||||
>>> p.insert_stream(stream_id=11, depends_on=7, exclusive=True)
|
||||
|
||||
Once streams are inserted, the stream priorities can be requested. This allows
|
||||
the server to make decisions about how to allocate resources.
|
||||
|
||||
Iterating The Tree
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The tree in this algorithm acts as a gate. Its goal is to allow one stream
|
||||
"through" at a time, in such a manner that all the active streams are served as
|
||||
evenly as possible in proportion to their weights.
|
||||
|
||||
This is handled in Priority by iterating over the tree. The tree itself is an
|
||||
iterator, and each time it is advanced it will yield a stream ID. This is the
|
||||
ID of the stream that should next send data.
|
||||
|
||||
This looks like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> for stream_id in p:
|
||||
... send_data(stream_id)
|
||||
|
||||
If each stream only sends when it is 'ungated' by this mechanism, the server
|
||||
will automatically be emitting stream data in conformance to RFC 7540.
|
||||
|
||||
Updating The Tree
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
If for any reason a stream is unable to proceed (for example, it is blocked on
|
||||
HTTP/2 flow control, or it is waiting for more data from another service), that
|
||||
stream is *blocked*. The ``PriorityTree`` should be informed that the stream is
|
||||
blocked so that other dependent streams get a chance to proceed. This can be
|
||||
done by calling the ``block`` method of the tree with the stream ID that is
|
||||
currently unable to proceed. This will automatically update the tree, and it
|
||||
will adjust on the fly to correctly allow any streams that were dependent on
|
||||
the blocked one to progress.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> for stream_id in p:
|
||||
... send_data(stream_id)
|
||||
... if blocked(stream_id):
|
||||
... p.block(stream_id)
|
||||
|
||||
When a stream goes from being blocked to being unblocked, call the ``unblock``
|
||||
method to place it back into the sequence. Both the ``block`` and ``unblock``
|
||||
methods are idempotent and safe to call repeatedly.
|
||||
|
||||
Additionally, the priority of a stream may change. When it does, the
|
||||
``reprioritize`` method can be used to update the tree in the wake of that
|
||||
change. ``reprioritize`` has the same signature as ``insert_stream``, but
|
||||
applies only to streams already in the tree.
|
||||
|
||||
Removing Streams
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
A stream can be entirely removed from the tree by calling ``remove_stream``.
|
||||
Note that this is not idempotent. Further, calling ``remove_stream`` and then
|
||||
re-adding it *may* cause a substantial change in the shape of the priority
|
||||
tree, and *will* cause the iteration order to change.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Priority is made available under the MIT License. For more details, see the
|
||||
LICENSE file in the repository.
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
Priority is maintained by Cory Benfield, with contributions from others. For
|
||||
more details about the contributors, please see CONTRIBUTORS.rst in the
|
||||
repository.
|
||||
|
||||
|
||||
.. _RFC 7540 Section 5.3 (Stream Priority): https://tools.ietf.org/html/rfc7540#section-5.3
|
||||
.. _nghttp2's: https://nghttp2.org/blog/2015/11/11/stream-scheduling-utilizing-http2-priority/
|
||||
.. _H2O: https://h2o.examp1e.net/
|
||||
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
1.3.0 (2017-01-27)
|
||||
------------------
|
||||
|
||||
**API Changes**
|
||||
|
||||
- Throw ``PriorityLoop`` when inserting or reprioritising a stream that
|
||||
depends on itself.
|
||||
- Throw ``BadWeightError`` when creating or reprioritising a stream with a
|
||||
weight that is not an integer between 1 and 256, inclusive.
|
||||
- Throw ``PseudoStreamError`` when trying to reprioritise, remove, block or
|
||||
unblock stream 0.
|
||||
- Add a new ``PriorityError`` parent class for the exceptions that can be
|
||||
thrown by priority.
|
||||
|
||||
1.2.2 (2016-11-11)
|
||||
------------------
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- Allow ``insert_stream`` to be called with ``exclusive=True`` but no explicit
|
||||
``depends_on`` value.
|
||||
|
||||
1.2.1 (2016-10-26)
|
||||
------------------
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- Allow insertion of streams that have parents in the idle or closed states.
|
||||
This would previously raise a KeyError.
|
||||
|
||||
1.2.0 (2016-08-04)
|
||||
------------------
|
||||
|
||||
**Security Fixes**
|
||||
|
||||
- CVE-2016-6580: All versions of this library prior to 1.2.0 are vulnerable to
|
||||
a denial of service attack whereby a remote peer can cause a user to insert
|
||||
an unbounded number of streams into the priority tree, eventually consuming
|
||||
all available memory.
|
||||
|
||||
This version adds a ``TooManyStreamsError`` exception that is raised when
|
||||
too many streams are inserted into the priority tree. It also adds a keyword
|
||||
argument to the priority tree, ``maximum_streams``, which limits how many
|
||||
streams may be inserted. By default, this number is set to 1000.
|
||||
Implementations should strongly consider whether they can set this value
|
||||
lower.
|
||||
|
||||
1.1.1 (2016-05-28)
|
||||
------------------
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- 2.5x performance improvement by swapping from ``queue.PriorityQueue`` to
|
||||
``heapq``.
|
||||
|
||||
1.1.0 (2016-01-08)
|
||||
------------------
|
||||
|
||||
**API Changes**
|
||||
|
||||
- Throw ``DuplicateStreamError`` when inserting a stream that is already in the
|
||||
tree.
|
||||
- Throw ``MissingStreamError`` when reprioritising a stream that is not in the
|
||||
tree.
|
||||
|
||||
1.0.0 (2015-12-07)
|
||||
------------------
|
||||
|
||||
- Initial release.
|
||||
|
||||
|
@@ -0,0 +1 @@
|
||||
pip
|
@@ -0,0 +1,216 @@
|
||||
Metadata-Version: 2.0
|
||||
Name: priority
|
||||
Version: 1.3.0
|
||||
Summary: A pure-Python implementation of the HTTP/2 priority tree
|
||||
Home-page: http://python-hyper.org/priority/
|
||||
Author: Cory Benfield
|
||||
Author-email: cory@lukasa.co.uk
|
||||
License: MIT License
|
||||
Platform: UNKNOWN
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 2
|
||||
Classifier: Programming Language :: Python :: 2.7
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.3
|
||||
Classifier: Programming Language :: Python :: 3.4
|
||||
Classifier: Programming Language :: Python :: 3.5
|
||||
Classifier: Programming Language :: Python :: 3.6
|
||||
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||
|
||||
Priority: A HTTP/2 Priority Implementation
|
||||
==========================================
|
||||
|
||||
Priority is a pure-Python implementation of the priority logic for HTTP/2, set
|
||||
out in `RFC 7540 Section 5.3 (Stream Priority)`_. This logic allows for clients
|
||||
to express a preference for how the server allocates its (limited) resources to
|
||||
the many outstanding HTTP requests that may be running over a single HTTP/2
|
||||
connection.
|
||||
|
||||
Specifically, this Python implementation uses a variant of the implementation
|
||||
used in the excellent `H2O`_ project. This original implementation is also the
|
||||
inspiration for `nghttp2's`_ priority implementation, and generally produces a
|
||||
very clean and even priority stream. The only notable changes from H2O's
|
||||
implementation are small modifications to allow the priority implementation to
|
||||
work cleanly as a separate implementation, rather than being embedded in a
|
||||
HTTP/2 stack directly.
|
||||
|
||||
While priority information in HTTP/2 is only a suggestion, rather than an
|
||||
enforceable constraint, where possible servers should respect the priority
|
||||
requests of their clients.
|
||||
|
||||
Using Priority
|
||||
--------------
|
||||
|
||||
Priority has a simple API. Streams are inserted into the tree: when they are
|
||||
inserted, they may optionally have a weight, depend on another stream, or
|
||||
become an exclusive dependent of another stream.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> p = priority.PriorityTree()
|
||||
>>> p.insert_stream(stream_id=1)
|
||||
>>> p.insert_stream(stream_id=3)
|
||||
>>> p.insert_stream(stream_id=5, depends_on=1)
|
||||
>>> p.insert_stream(stream_id=7, weight=32)
|
||||
>>> p.insert_stream(stream_id=9, depends_on=7, weight=8)
|
||||
>>> p.insert_stream(stream_id=11, depends_on=7, exclusive=True)
|
||||
|
||||
Once streams are inserted, the stream priorities can be requested. This allows
|
||||
the server to make decisions about how to allocate resources.
|
||||
|
||||
Iterating The Tree
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The tree in this algorithm acts as a gate. Its goal is to allow one stream
|
||||
"through" at a time, in such a manner that all the active streams are served as
|
||||
evenly as possible in proportion to their weights.
|
||||
|
||||
This is handled in Priority by iterating over the tree. The tree itself is an
|
||||
iterator, and each time it is advanced it will yield a stream ID. This is the
|
||||
ID of the stream that should next send data.
|
||||
|
||||
This looks like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> for stream_id in p:
|
||||
... send_data(stream_id)
|
||||
|
||||
If each stream only sends when it is 'ungated' by this mechanism, the server
|
||||
will automatically be emitting stream data in conformance to RFC 7540.
|
||||
|
||||
Updating The Tree
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
If for any reason a stream is unable to proceed (for example, it is blocked on
|
||||
HTTP/2 flow control, or it is waiting for more data from another service), that
|
||||
stream is *blocked*. The ``PriorityTree`` should be informed that the stream is
|
||||
blocked so that other dependent streams get a chance to proceed. This can be
|
||||
done by calling the ``block`` method of the tree with the stream ID that is
|
||||
currently unable to proceed. This will automatically update the tree, and it
|
||||
will adjust on the fly to correctly allow any streams that were dependent on
|
||||
the blocked one to progress.
|
||||
|
||||
For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> for stream_id in p:
|
||||
... send_data(stream_id)
|
||||
... if blocked(stream_id):
|
||||
... p.block(stream_id)
|
||||
|
||||
When a stream goes from being blocked to being unblocked, call the ``unblock``
|
||||
method to place it back into the sequence. Both the ``block`` and ``unblock``
|
||||
methods are idempotent and safe to call repeatedly.
|
||||
|
||||
Additionally, the priority of a stream may change. When it does, the
|
||||
``reprioritize`` method can be used to update the tree in the wake of that
|
||||
change. ``reprioritize`` has the same signature as ``insert_stream``, but
|
||||
applies only to streams already in the tree.
|
||||
|
||||
Removing Streams
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
A stream can be entirely removed from the tree by calling ``remove_stream``.
|
||||
Note that this is not idempotent. Further, calling ``remove_stream`` and then
|
||||
re-adding it *may* cause a substantial change in the shape of the priority
|
||||
tree, and *will* cause the iteration order to change.
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
Priority is made available under the MIT License. For more details, see the
|
||||
LICENSE file in the repository.
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
Priority is maintained by Cory Benfield, with contributions from others. For
|
||||
more details about the contributors, please see CONTRIBUTORS.rst in the
|
||||
repository.
|
||||
|
||||
|
||||
.. _RFC 7540 Section 5.3 (Stream Priority): https://tools.ietf.org/html/rfc7540#section-5.3
|
||||
.. _nghttp2's: https://nghttp2.org/blog/2015/11/11/stream-scheduling-utilizing-http2-priority/
|
||||
.. _H2O: https://h2o.examp1e.net/
|
||||
|
||||
|
||||
Changelog
|
||||
=========
|
||||
|
||||
1.3.0 (2017-01-27)
|
||||
------------------
|
||||
|
||||
**API Changes**
|
||||
|
||||
- Throw ``PriorityLoop`` when inserting or reprioritising a stream that
|
||||
depends on itself.
|
||||
- Throw ``BadWeightError`` when creating or reprioritising a stream with a
|
||||
weight that is not an integer between 1 and 256, inclusive.
|
||||
- Throw ``PseudoStreamError`` when trying to reprioritise, remove, block or
|
||||
unblock stream 0.
|
||||
- Add a new ``PriorityError`` parent class for the exceptions that can be
|
||||
thrown by priority.
|
||||
|
||||
1.2.2 (2016-11-11)
|
||||
------------------
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- Allow ``insert_stream`` to be called with ``exclusive=True`` but no explicit
|
||||
``depends_on`` value.
|
||||
|
||||
1.2.1 (2016-10-26)
|
||||
------------------
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- Allow insertion of streams that have parents in the idle or closed states.
|
||||
This would previously raise a KeyError.
|
||||
|
||||
1.2.0 (2016-08-04)
|
||||
------------------
|
||||
|
||||
**Security Fixes**
|
||||
|
||||
- CVE-2016-6580: All versions of this library prior to 1.2.0 are vulnerable to
|
||||
a denial of service attack whereby a remote peer can cause a user to insert
|
||||
an unbounded number of streams into the priority tree, eventually consuming
|
||||
all available memory.
|
||||
|
||||
This version adds a ``TooManyStreamsError`` exception that is raised when
|
||||
too many streams are inserted into the priority tree. It also adds a keyword
|
||||
argument to the priority tree, ``maximum_streams``, which limits how many
|
||||
streams may be inserted. By default, this number is set to 1000.
|
||||
Implementations should strongly consider whether they can set this value
|
||||
lower.
|
||||
|
||||
1.1.1 (2016-05-28)
|
||||
------------------
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
- 2.5x performance improvement by swapping from ``queue.PriorityQueue`` to
|
||||
``heapq``.
|
||||
|
||||
1.1.0 (2016-01-08)
|
||||
------------------
|
||||
|
||||
**API Changes**
|
||||
|
||||
- Throw ``DuplicateStreamError`` when inserting a stream that is already in the
|
||||
tree.
|
||||
- Throw ``MissingStreamError`` when reprioritising a stream that is not in the
|
||||
tree.
|
||||
|
||||
1.0.0 (2015-12-07)
|
||||
------------------
|
||||
|
||||
- Initial release.
|
||||
|
||||
|
@@ -0,0 +1,11 @@
|
||||
priority-1.3.0.dist-info/DESCRIPTION.rst,sha256=LlPtJuAdYo4q_tp3zBdwDjDyBsFug-xg8j29O-TX8bg,6594
|
||||
priority-1.3.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
priority-1.3.0.dist-info/METADATA,sha256=K3MqasNfs5c2SVswdew1HpGKljGDqG8ad9AbqDR8ZG8,7532
|
||||
priority-1.3.0.dist-info/RECORD,,
|
||||
priority-1.3.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110
|
||||
priority-1.3.0.dist-info/metadata.json,sha256=iA7oRWd5GkhNs7owcXCTR-ttgIqX9DBApAY35SlWbFc,1024
|
||||
priority-1.3.0.dist-info/top_level.txt,sha256=h3tSuUixZwbNNnmCDpCI-prFqZAqquWlneJge51DLkQ,9
|
||||
priority/__init__.py,sha256=3FnazZrRZWFvTwZHrBdSc1L1CgsrjvoUnbWE7QngznQ,274
|
||||
priority/__pycache__/__init__.cpython-39.pyc,,
|
||||
priority/__pycache__/priority.cpython-39.pyc,,
|
||||
priority/priority.py,sha256=hwNWSffjNjUw-mXCAeXUhVEz2Wu5azKyCrXbXH_tk3w,15271
|
@@ -0,0 +1,6 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: bdist_wheel (0.29.0)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py2-none-any
|
||||
Tag: py3-none-any
|
||||
|
@@ -0,0 +1 @@
|
||||
{"classifiers": ["Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy"], "extensions": {"python.details": {"contacts": [{"email": "cory@lukasa.co.uk", "name": "Cory Benfield", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://python-hyper.org/priority/"}}}, "generator": "bdist_wheel (0.29.0)", "license": "MIT License", "metadata_version": "2.0", "name": "priority", "summary": "A pure-Python implementation of the HTTP/2 priority tree", "version": "1.3.0"}
|
@@ -0,0 +1 @@
|
||||
priority
|
Reference in New Issue
Block a user