Skip to content

Commit 6ade38f

Browse files
committed
Update README now that we have a real manual
1 parent 870ae7f commit 6ade38f

File tree

1 file changed

+29
-152
lines changed

1 file changed

+29
-152
lines changed

README.rst

Lines changed: 29 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,30 @@ h11
22
===
33

44
.. image:: https://travis-ci.org/njsmith/h11.svg?branch=master
5-
:target: https://travis-ci.org/njsmith/h11
5+
:target: https://travis-ci.org/njsmith/h11
6+
:alt: Automated test status
67

78
.. image:: https://codecov.io/gh/njsmith/h11/branch/master/graph/badge.svg
8-
:target: https://codecov.io/gh/njsmith/h11
9+
:target: https://codecov.io/gh/njsmith/h11
10+
:alt: Test coverage
11+
12+
.. image:: https://readthedocs.org/projects/h11/badge/?version=latest
13+
:target: http://h11.readthedocs.io/en/latest/?badge=latest
14+
:alt: Documentation Status
915

1016
This is a little HTTP/1.1 library written from scratch in Python,
1117
heavily inspired by `hyper-h2 <https://hyper-h2.readthedocs.io/>`_.
1218

13-
This is a pure protocol library; like h2, it contains no IO code
14-
whatsoever. This means you can hook h11 up to your favorite network
15-
API, and that could be anything you want: synchronous, threaded,
16-
asynchronous, or your own implementation of `RFC 6214
19+
This is a "bring-your-own-I/O" library; like h2, it contains no IO
20+
code whatsoever. This means you can hook h11 up to your favorite
21+
network API, and that could be anything you want: synchronous,
22+
threaded, asynchronous, or your own implementation of `RFC 6214
1723
<https://tools.ietf.org/html/rfc6214>`_ -- h11 won't judge you.
1824
(Compare this to the current state of the art, where every time a `new
1925
network API <https://curio.readthedocs.io/>`_ comes along then someone
2026
gets to start over reimplementing the entire HTTP protocol from
21-
scratch.) Cory Benfield made an `excellent blog post describing this
22-
"bring-your-own I/O" approach
27+
scratch.) Cory Benfield made an `excellent blog post describing the
28+
benefits of this approach
2329
<https://lukasa.co.uk/2015/10/The_New_Hyper/>`_.
2430

2531
This also means that h11 is not immediately useful out of the box:
@@ -57,35 +63,27 @@ the ones that you receive as a server and vice-versa.
5763
`Here's an example of a tiny HTTP client
5864
<https://github.com/njsmith/h11/blob/master/tiny-client-demo.py>`_
5965

66+
It also has `a fine manual <https://h11.readthedocs.io/>`_.
6067

6168
FAQ
6269
---
6370

6471
*Whyyyyy?*
6572

66-
NIH is fun! Also I got mildly annoyed at some trivial and probably
67-
easily fixable issues in `aiohttp <https://aiohttp.readthedocs.io/>`_,
68-
so rather than spend a few hours debugging them I spent a few days
69-
writing my own HTTP stack from scratch.
70-
71-
*...that's a terrible reason.*
72-
73-
Well, ok... I also wanted to play with `Curio
73+
I wanted to play with HTTP in `Curio
7474
<https://curio.readthedocs.io/en/latest/tutorial.html>`_, which has no
75-
HTTP library, and I was feeling inspired by Curio's elegantly
76-
featureful minimalism and Cory's call-to-arms blog-post.
77-
78-
And, most importantly, I was sick and needed a gloriously pointless
79-
yak-shaving project to distract me from all the things I should have
80-
been doing instead. Perhaps it won't turn out to be quite as pointless
81-
as all that, but either way at least I learned some stuff.
75+
HTTP library. So I thought, no big deal, Python has, like, a dozen
76+
different implementations of HTTP, surely I can find one that's
77+
reusable. I didn't find one, but I did find Cory's call-to-arms
78+
blog-post. So I figured, well, fine, if I have to implement HTTP from
79+
scratch, at least I can make sure no-one *else* has to ever again.
8280

8381
*Should I use it?*
8482

8583
Maybe. You should be aware that it's a very young project. But, it's
86-
feature complete and has an exhaustive test-suite, so the next step is
87-
for people to try using it and see how it goes :-). If you do then
88-
please do report back!
84+
feature complete and has an exhaustive test-suite and complete docs,
85+
so the next step is for people to try using it and see how it goes
86+
:-). If you do then please do report back!
8987

9088
*What are the features/limitations?*
9189

@@ -110,9 +108,10 @@ library.
110108
It has a test suite with 100.0% coverage for both statements and
111109
branches.
112110

113-
Currently it only supports Python 3.5, though it wouldn't be hard to
114-
expand this to support other versions, including 2.7. (Originally it
115-
had a Cython wrapper for `http-parser
111+
Currently it only supports Python 3 (testing on 3.3-3.5), though it
112+
wouldn't be hard to expand add Python 2.7 support too, I just haven't
113+
gotten around to it. Feel free to submit a PR. (Originally it had a
114+
Cython wrapper for `http-parser
116115
<https://github.com/nodejs/http-parser>`_ and a beautiful nested state
117116
machine implemented with ``yield from`` to postprocess the output. But
118117
I had to take these out -- the new *parser* needs fewer lines-of-code
@@ -139,11 +138,6 @@ is now quite small and simple, I'm still annoyed that I haven't
139138
figured out how to make it even smaller and simpler. (Unfortunately,
140139
HTTP does not lend itself to simplicity.)
141140

142-
At a more concrete, roadmappy kind of level, my current todo list is:
143-
144-
* Write a manual
145-
* Try using it for some real things
146-
147141
The API is ~feature complete and I don't expect the general outlines
148142
to change much, but you can't judge an API's ergonomics until you
149143
actually document and use it, so I'd expect some changes in the
@@ -155,127 +149,10 @@ There's no setup.py or anything yet. I'd start with::
155149

156150
$ git clone git@github.com:njsmith/h11
157151
$ cd h11
158-
$ python35 tiny-client-demo.py
152+
$ python3 tiny-client-demo.py
159153

160154
and go from there.
161155

162156
*License?*
163157

164158
MIT
165-
166-
167-
Some technical minutia for HTTP nerds
168-
-------------------------------------
169-
170-
Of the headers defined in RFC 7230, the ones h11 knows and has some
171-
special-case logic to care about are: ``Connection:``,
172-
``Transfer-Encoding:``, ``Content-Length:``, ``Host:``, ``Upgrade:``,
173-
and ``Expect:`` (which is really from `RFC 7231
174-
<https://tools.ietf.org/html/rfc7231#section-5.1.1>`_ but
175-
whatever). The other headers in RFC 7230 are ``TE:``, ``Trailer:``,
176-
and ``Via:``; h11 also supports these in the sense that it ignores
177-
them and that's really all it should be doing.
178-
179-
Transfer-Encoding support: we only know ``chunked``, not ``gzip`` or
180-
``deflate``. We're in good company in this: node.js at least doesn't
181-
handle anything besides ``chunked`` either. So I'm not too worried
182-
about this being a problem in practice. But I'm not majorly opposed to
183-
adding support for more features here either.
184-
185-
When parsing chunked encoding, we parse but discard "chunk
186-
extensions". This is an extremely obscure feature that allows
187-
arbitrary metadata to be interleaved into a chunked transfer
188-
stream. This metadata has no standard uses, and proxies are allowed to
189-
strip it out. I don't think anyone will notice this lack, but it could
190-
be added if someone really wants it; I just ran out of energy for
191-
implementing weirdo features no-one uses.
192-
193-
Protocol changing/upgrading: h11 has has full support for
194-
transitioning to a new protocol, via either Upgrade: headers (e.g.,
195-
``Upgrade: websocket``) or the ``CONNECT`` method. Note that this
196-
*doesn't* mean that h11 actually *implements* the WebSocket protocol
197-
-- though a bring-your-own-I/O WebSocket library would indeed be
198-
pretty sweet, someone should definitely implement that. It just means
199-
that h11 has the hooks needed to let you implement hand-off to a
200-
different protocol.
201-
202-
Currently we implement support for "obsolete line folding" when
203-
reading HTTP headers. This is an optional part of the spec --
204-
conforming HTTP/1.1 implementations MUST NOT send continuation lines,
205-
and conforming HTTP/1.1 servers MAY send 400 Bad Request responses
206-
back at clients who do send them (`ref
207-
<https://tools.ietf.org/html/rfc7230#section-3.2.4>`_). I'm tempted to
208-
remove it, since it adds some complicated and ugly code right at the
209-
center of the request/response parsing loop, and I'm not sure whether
210-
anyone actually needs it. Unfortunately a few major implementations
211-
that I spot-checked (node.js, go) do still seem to support it, so it
212-
might or might not be obsolete in practice -- it's hard to know.
213-
214-
Cute trick: we also support ``sendfile``. Or at least, we give you the
215-
tools you need to support ``sendfile``. Specifically, the payload of a
216-
``Data`` event can be any object that has a ``__len__``, and we'll
217-
pass it back out unchanged at the appropriate place in the output
218-
stream. So this is useful for e.g. if you want to use ``os.sendfile``
219-
to send some data: pass in a placeholder object like
220-
``conn.send(Data(data=placeholder), combine=False)`` and you'll get
221-
back a list of things-to-send, which will be a mixture ``bytes``-like
222-
objects containing any framing stuff + your original object. Then your
223-
write loop can be like::
224-
225-
for piece in data_pieces:
226-
if isinstance(piece, FilePlaceholder):
227-
sock.sendfile(*piece.sendfile_args())
228-
else:
229-
sock.sendall(piece)
230-
231-
232-
Connection lifecycle
233-
....................
234-
235-
We fully support HTTP/1.1 keep-alive.
236-
237-
We have a little bit of support for HTTP/1.1 pipelining -- basically
238-
the minimum that's required by the standard. In server mode we can
239-
handle pipelined requests in a serial manner, responding completely to
240-
each request before reading the next (and our API is designed to make
241-
it easy for servers to keep this straight). Client mode doesn't
242-
support pipelining at all. As far as I can tell, this matches the
243-
state of the art in all the major HTTP implementations: the consensus
244-
seems to be that HTTP/1.1 pipelining was a nice try but unworkable in
245-
practice, and if you really need pipelining to work then instead of
246-
trying to fix HTTP/1.1 you should switch to HTTP/2.0. (Now that I know
247-
more about how HTTP works internally I'm inclined to agree.)
248-
249-
The HTTP/1.0 Connection: keep-alive pseudo-standard is currently not
250-
supported. (Note that this only affects h11 as a server, because h11
251-
as a client always speaks HTTP/1.1.) Supporting this would be
252-
possible, but it's fragile and finicky and I'm suspicious that if we
253-
leave it out then no-one will notice or care. HTTP/1.1 is now almost
254-
old enough to vote in United States elections. I get that people
255-
sometimes write HTTP/1.0 clients because they don't want to deal with
256-
annoying stuff like chunked encoding, and I completely sympathize with
257-
that, but I'm guessing that you're not going to find too many people
258-
these days who care desperately about keep-alive *and at the same
259-
time* are too lazy to implement Transfer-Encoding: chunked. Still,
260-
this would be my bet as to the missing feature that people are most
261-
likely to eventually complain about...
262-
263-
264-
Trippy state machine diagrams
265-
.............................
266-
267-
We model the state of an HTTP/1.1 connection as a pair of linked state
268-
machines, one for each of the peers. Blue is an "event" sent by that
269-
peer, green is a transition triggered by the (client state, server
270-
state) tuple taking on a particular value, and purple is special
271-
cases. (NB these are slightly out of date. TODO: make the doc build
272-
automatically re-run the code that regenerates these from the
273-
source. Once we have a doc build...)
274-
275-
Client side:
276-
277-
.. image:: https://vorpus.org/~njs/tmp/h11-client-2016-05-04.svg
278-
279-
Server side:
280-
281-
.. image:: https://vorpus.org/~njs/tmp/h11-server-2016-05-04.svg

0 commit comments

Comments
 (0)