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
1016This is a little HTTP/1.1 library written from scratch in Python,
1117heavily 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
1925network API <https://curio.readthedocs.io/> `_ comes along then someone
2026gets 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
2531This 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
6168FAQ
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
8583Maybe. 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.
110108It has a test suite with 100.0% coverage for both statements and
111109branches.
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
117116machine implemented with ``yield from `` to postprocess the output. But
118117I 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
139138figured out how to make it even smaller and simpler. (Unfortunately,
140139HTTP 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-
147141The API is ~feature complete and I don't expect the general outlines
148142to change much, but you can't judge an API's ergonomics until you
149143actually 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
160154and go from there.
161155
162156*License? *
163157
164158MIT
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