About half an hour ago I pushed the latest release of
hyper, v0.1.0. This marks the
first release of hyper since early March! This delay is not because I’ve been
resting on my laurels. In fact, a quick check of the
git repository shows
that there were almost as many commits between v0.0.4 and v0.1.0 as there were
in total up to v0.0.4.
Why the delay? What have I been working on? Why wasn’t I releasing
incrementally? This post acts as a long form explanation to bring you up to
speed with what’s going on in
hyper. If you’re just interested in the
highlights, feel free to consult
the changelog directly.
First, the bad stuff. This release of
hyper abandons support for Python 3.3,
instead supporting only Python 3.4. Why did I do this?
Simple: Python 3.3’s
ssl module is not good enough to support HTTP/2. I need
features that it does not have: specifically, I need to limit TLS negotiation
to TLS v1.2 only. When Python 3.4 came out with that support we immediately
moved to add it, expecting that
PyOpenSSL would be able to fill the gap for
PyOpenSSL was missing NPN support. At the end of March I
pull request on
added NPN support. I also opened two others needed for
hyper, one adding
support for ALPN and one adding support for the socket
recv_into method. I
then blocked my next release of
PyOpenSSL merging my NPN pull
request and shipping a new release.
As of now this has not happened.
PyOpenSSL has fallen into a form of
development hell where there does not appear to be sufficient resources to fix
a major underlying problem that
PyOpenSSL’s next release. Until this gets resolved there are unlikely
to be future releases of
A second problem stemming from this is that I no longer get to be excited about
hyper’s planned marquee features for this release. The truly excellent
Alek Storm added support for both CPython 2.7
and PyPy to
hyper in March. This support remains in the library, but without
PyOpenSSL is unusable.
hyper continues to have its test suite run on PyPy, CPython 2.7, and CPython
3.3, so when
PyOpenSSL is eventually updated it should be a trivial job to
re-add support for those Python distributions. I’ll make a big deal of it when
it finally happens.
If you want more details, check out issue #37.
Major New Features
Onto the good stuff! Each feature has a link to its tracking issue (where applicable) directly after the header if you want more details or to see the code that added it.
HTTP/2-14 and HPACK-9
The development version of
hyper has been keeping pace with the HPACK and
HTTP/2 draft versions as they appeared. Version 0.1.0 contains support for
HTTP/2-14 and HPACK-9. These versions are the current interop drafts, and also
represent the Working Group Last Call documents. This means they’ll be kept
unchanged for a while so that distributions can get interop experience.
This feature alone makes it a perfect time to download
hyper and give it a
Back when I wrote my
original blog post announcing
hyper I had the following to say about Server Push:
I don’t believe it’s possible to write a pleasant API that correctly handles Server Push without using either an event loop or having hyper spawn its own background threads. Until asyncio becomes a standard, I don’t think hyper should force you to do the first, and it’s obnoxious for a library to spawn its own threads. This means that, for the moment, hyper does not support Server Push.
I’m delighted to say that this is no longer true! Once again, Alek Storm did
the heavy lifting here and deserves huge congratulations. The upshot is that
hyper now supports Server Push and has it turned on by default. Check out
for usage examples.
Buffered Socket To Avoid Overhead
One of the bits of feedback I got in response to my investigation of hyper’s performance was that I could avoid the overhead of making many syscalls by buffering socket data in userspace.
I’ve now gone ahead and done that:
hyper maintains a 64kB buffer in memory
for each connection to ameliorate some of the performance costs. It also avoids
copying data for much longer, saving some overheads involved in unnecessarily
copying memory around. Both of these changes should cause performance
For those interested in borrowing the implementation, the buffered socket can
You are welcome to use it in your own projects under the same license as
Nghttp2: If You Can’t Beat ‘Em, Join ‘Em
hyper by default uses its built-in pure-Python HPACK encoder and decoder,
which is reasonably quick and fairly efficient. However, the awesome
nghttp2 project contains a C implementation of HPACK
that achieves astonishing compression faster than
hyper does, while using
If you’re concerned about performance, you can now use nghttp2’s encoder and
hyper! Simple install nghttp2 with the Python bindings, and
hyper will prefer nghttp2’s encoder and decoder to its own.
This allows the best of both worlds: zero dependency installation, with optional performance improvements for those who want them.
In future, I’ll probably approach nghttp2’s maintainers to suggest that they replace the Python bindings with a CFFI-based Python module to allow PyPy users to also use nghttp2.
Discussed in part in Issue #71.
I’ve also taken my first step into adding features that are not supported in
httplib, by adding support for HTTP trailers. These are headers sent
after a chunk-encoded body, containing metadata that was not known before the
request was sent. This is often things like
httplib does not support trailers transparently, but
hyper does. See
this section of the docs
for the relevant methods.
I’m aware that many people will not be able to use this method for fear of
needing to switch back to vanilla
httplib, which does not have it. I plan
to start work on the abstraction layer soon, which should help ameliorate these
Bugfixes and Minor Features
We also added a number of smaller features. These are listed below, click on their issue links to see more information.
HTTP20Responseobjects are context managers. Issue #24
- Pluggable window managers are now correctly informed about the document size. Issue #26
- Header blocks don’t get corrupted if read in a different order to the one in which they were sent. Issue #39
- Default window manager is now smarter about sending WINDOWUPDATE frames. Issue #41 and Issue #52
- Fixed inverted window sizes. Issue #27
- Correctly reply to PING frames. Issue #48
- Added a universal wheel. Issue #46
- HPACK encoder correctly encodes header lists with duplicate headers. Issue #50
Progress Is Being Made
This is still an exciting time to be working on
hyper. We’ve got lots of open
issues and plans for the future. This means there’s really no better time for
you to download it and try it out. Give it a go!