{ "info": { "author": "Nathaniel J. Smith", "author_email": "njs@pobox.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Internet :: WWW/HTTP", "Topic :: System :: Networking" ], "description": "h11\n===\n\n.. image:: https://travis-ci.org/python-hyper/h11.svg?branch=master\n :target: https://travis-ci.org/python-hyper/h11\n :alt: Automated test status\n\n.. image:: https://codecov.io/gh/python-hyper/h11/branch/master/graph/badge.svg\n :target: https://codecov.io/gh/python-hyper/h11\n :alt: Test coverage\n\n.. image:: https://readthedocs.org/projects/h11/badge/?version=latest\n :target: http://h11.readthedocs.io/en/latest/?badge=latest\n :alt: Documentation Status\n\nThis is a little HTTP/1.1 library written from scratch in Python,\nheavily inspired by `hyper-h2 `_.\n\nIt's a \"bring-your-own-I/O\" library; h11 contains no IO code\nwhatsoever. This means you can hook h11 up to your favorite network\nAPI, and that could be anything you want: synchronous, threaded,\nasynchronous, or your own implementation of `RFC 6214\n`_ -- h11 won't judge you.\n(Compare this to the current state of the art, where every time a `new\nnetwork API `_ comes along then someone\ngets to start over reimplementing the entire HTTP protocol from\nscratch.) Cory Benfield made an `excellent blog post describing the\nbenefits of this approach\n`_, or if you like video\nthen here's his `PyCon 2016 talk on the same theme\n`_.\n\nThis also means that h11 is not immediately useful out of the box:\nit's a toolkit for building programs that speak HTTP, not something\nthat could directly replace ``requests`` or ``twisted.web`` or\nwhatever. But h11 makes it much easier to implement something like\n``requests`` or ``twisted.web``.\n\nAt a high level, working with h11 goes like this:\n\n1) First, create an ``h11.Connection`` object to track the state of a\n single HTTP/1.1 connection.\n\n2) When you read data off the network, pass it to\n ``conn.receive_data(...)``; you'll get back a list of objects\n representing high-level HTTP \"events\".\n\n3) When you want to send a high-level HTTP event, create the\n corresponding \"event\" object and pass it to ``conn.send(...)``;\n this will give you back some bytes that you can then push out\n through the network.\n\nFor example, a client might instantiate and then send a\n``h11.Request`` object, then zero or more ``h11.Data`` objects for the\nrequest body (e.g., if this is a POST), and then a\n``h11.EndOfMessage`` to indicate the end of the message. Then the\nserver would then send back a ``h11.Response``, some ``h11.Data``, and\nits own ``h11.EndOfMessage``. If either side violates the protocol,\nyou'll get a ``h11.ProtocolError`` exception.\n\nh11 is suitable for implementing both servers and clients, and has a\npleasantly symmetric API: the events you send as a client are exactly\nthe ones that you receive as a server and vice-versa.\n\n`Here's an example of a tiny HTTP client\n`_\n\nIt also has `a fine manual `_.\n\nFAQ\n---\n\n*Whyyyyy?*\n\nI wanted to play with HTTP in `Curio\n`__ and `Trio\n`__, which at the time didn't have any\nHTTP libraries. So I thought, no big deal, Python has, like, a dozen\ndifferent implementations of HTTP, surely I can find one that's\nreusable. I didn't find one, but I did find Cory's call-to-arms\nblog-post. So I figured, well, fine, if I have to implement HTTP from\nscratch, at least I can make sure no-one *else* has to ever again.\n\n*Should I use it?*\n\nMaybe. You should be aware that it's a very young project. But, it's\nfeature complete and has an exhaustive test-suite and complete docs,\nso the next step is for people to try using it and see how it goes\n:-). If you do then please let us know -- if nothing else we'll want\nto talk to you before making any incompatible changes!\n\n*What are the features/limitations?*\n\nRoughly speaking, it's trying to be a robust, complete, and non-hacky\nimplementation of the first \"chapter\" of the HTTP/1.1 spec: `RFC 7230:\nHTTP/1.1 Message Syntax and Routing\n`_. That is, it mostly focuses on\nimplementing HTTP at the level of taking bytes on and off the wire,\nand the headers related to that, and tries to be anal about spec\nconformance. It doesn't know about higher-level concerns like URL\nrouting, conditional GETs, cross-origin cookie policies, or content\nnegotiation. But it does know how to take care of framing,\ncross-version differences in keep-alive handling, and the \"obsolete\nline folding\" rule, so you can focus your energies on the hard /\ninteresting parts for your application, and it tries to support the\nfull specification in the sense that any useful HTTP/1.1 conformant\napplication should be able to use h11.\n\nIt's pure Python, and has no dependencies outside of the standard\nlibrary.\n\nIt has a test suite with 100.0% coverage for both statements and\nbranches.\n\nCurrently it supports Python 3 (testing on 3.4-3.7), Python 2.7, and PyPy.\n(Originally it had a Cython wrapper for `http-parser\n`_ and a beautiful nested state\nmachine implemented with ``yield from`` to postprocess the output. But\nI had to take these out -- the new *parser* needs fewer lines-of-code\nthan the old *parser wrapper*, is written in pure Python, uses no\nexotic language syntax, and has more features. It's sad, really; that\nold state machine was really slick. I just need a few sentences here\nto mourn that.)\n\nI don't know how fast it is. I haven't benchmarked or profiled it yet,\nso it's probably got a few pointless hot spots, and I've been trying\nto err on the side of simplicity and robustness instead of\nmicro-optimization. But at the architectural level I tried hard to\navoid fundamentally bad decisions, e.g., I believe that all the\nparsing algorithms remain linear-time even in the face of pathological\ninput like slowloris, and there are no byte-by-byte loops. (I also\nbelieve that it maintains bounded memory usage in the face of\narbitrary/pathological input.)\n\nThe whole library is ~800 lines-of-code. You can read and understand\nthe whole thing in less than an hour. Most of the energy invested in\nthis so far has been spent on trying to keep things simple by\nminimizing special-cases and ad hoc state manipulation; even though it\nis now quite small and simple, I'm still annoyed that I haven't\nfigured out how to make it even smaller and simpler. (Unfortunately,\nHTTP does not lend itself to simplicity.)\n\nThe API is ~feature complete and I don't expect the general outlines\nto change much, but you can't judge an API's ergonomics until you\nactually document and use it, so I'd expect some changes in the\ndetails.\n\n*How do I try it?*\n\n.. code-block:: sh\n\n $ pip install h11\n $ git clone git@github.com:python-hyper/h11\n $ cd h11/examples\n $ python basic-client.py\n\nand go from there.\n\n*License?*\n\nMIT\n\n*Code of conduct?*\n\nContributors are requested to follow our `code of conduct\n`_ in\nall project spaces.\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/python-hyper/h11", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "h11", "package_url": "https://pypi.org/project/h11/", "platform": "", "project_url": "https://pypi.org/project/h11/", "project_urls": { "Homepage": "https://github.com/python-hyper/h11" }, "release_url": "https://pypi.org/project/h11/0.9.0/", "requires_dist": null, "requires_python": "", "summary": "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1", "version": "0.9.0" }, "last_serial": 5273841, "releases": { "0.0.1": [], "0.5.0": [ { "comment_text": "", "digests": { "md5": "4fb8f5e1c06226e65abb651f91bcaeea", "sha256": "7f8029fc4120b6b89a3c70622fab7d02df3b0795f70839d390aeb8670099c2f7" }, "downloads": -1, "filename": "h11-0.5.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4fb8f5e1c06226e65abb651f91bcaeea", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 50781, "upload_time": "2016-05-14T01:29:43", "url": "https://files.pythonhosted.org/packages/12/98/ffc43bd13b8eba5845d0af8af29168114806c723973d2975f1a40b209b10/h11-0.5.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5b19142044cf95da41c2561b5bd843b0", "sha256": "02d6d33e63ee81ccd0f6e6860cfa54920f93eda3086ef1e5c0db4a0c727ae4cd" }, "downloads": -1, "filename": "h11-0.5.0.zip", "has_sig": false, "md5_digest": "5b19142044cf95da41c2561b5bd843b0", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 99841, "upload_time": "2016-05-14T01:29:48", "url": "https://files.pythonhosted.org/packages/12/ff/44ed346ee21204c096e7ee6cce0af452af2d55a79005d8a11e83ff158f48/h11-0.5.0.zip" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "7235729bba460dee201f98b4345632bd", "sha256": "130f8336c1c308e95d4fa6726c1884cc0d754d9919e066704ad35c80fd8284d0" }, "downloads": -1, "filename": "h11-0.6.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7235729bba460dee201f98b4345632bd", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 52610, "upload_time": "2016-10-25T03:47:17", "url": "https://files.pythonhosted.org/packages/ce/3e/bbfc1d314ed17e47892912d6007118b85d8eaf6d22516011c52936133ae1/h11-0.6.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "9f24a88434f229b28719ef36f6d8a8a6", "sha256": "497c7c0369e88fcdd6146461a19df89238a8290a210d40a3e40095e6d4eb1e0f" }, "downloads": -1, "filename": "h11-0.6.0.zip", "has_sig": false, "md5_digest": "9f24a88434f229b28719ef36f6d8a8a6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 103525, "upload_time": "2016-10-25T03:47:20", "url": "https://files.pythonhosted.org/packages/8c/25/1ee4ef3a44506f3b2d8438eba6b0179a3fcc07579c1f94e5960aa41bef48/h11-0.6.0.zip" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "e54ee61f768f89ba6f4e78782f621bf2", "sha256": "af77d5d82fa027c032650fb8afdef3cd0a3735ba01480bee908cddad9be1bdce" }, "downloads": -1, "filename": "h11-0.7.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "e54ee61f768f89ba6f4e78782f621bf2", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 53542, "upload_time": "2016-11-26T05:18:50", "url": "https://files.pythonhosted.org/packages/97/57/c0734cec5a9344d1feab295046011edbc6ba8e877ce1b822373257acdb61/h11-0.7.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e411d454aa515cf9cbd43cd12999b3d2", "sha256": "1c0fbb1cba6f809fe3e6b27f8f6d517ca171f848922708871403636143d530d9" }, "downloads": -1, "filename": "h11-0.7.0.zip", "has_sig": false, "md5_digest": "e411d454aa515cf9cbd43cd12999b3d2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 105979, "upload_time": "2016-11-26T05:18:54", "url": "https://files.pythonhosted.org/packages/50/13/954a4bd263857262a0b07155b47f5494a02b97984a5bcc6263bf89f12586/h11-0.7.0.zip" } ], "0.8.0": [ { "comment_text": "", "digests": { "md5": "f4a3619cd7e227c5ec103da8e7f88811", "sha256": "26cd7ca4c34c8f37def8d1fa22e6ad807fcd9757cf391ad20b0313b6202ce76c" }, "downloads": -1, "filename": "h11-0.8.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f4a3619cd7e227c5ec103da8e7f88811", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 55576, "upload_time": "2018-03-20T08:01:08", "url": "https://files.pythonhosted.org/packages/ee/fe/1456cd63075491d0e9b64af9599921c2233d9cbd07cabc0f45346477a97f/h11-0.8.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "589bf660aab8dda26a72a9e459dd4792", "sha256": "2b291009a34d8a3dd496f2c3ff1947d59ee2c3e88991adea84232d13c7be1acb" }, "downloads": -1, "filename": "h11-0.8.0.tar.gz", "has_sig": false, "md5_digest": "589bf660aab8dda26a72a9e459dd4792", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 92722, "upload_time": "2018-03-20T08:01:11", "url": "https://files.pythonhosted.org/packages/12/47/4cb52caa281cffc1fce515d7fdc4727935f2606ab1c5a76d8fe3ba510133/h11-0.8.0.tar.gz" } ], "0.8.1": [ { "comment_text": "", "digests": { "md5": "7be73466fcb1af2961122acb7fc890e2", "sha256": "f2b1ca39bfed357d1f19ac732913d5f9faa54a5062eca7d2ec3a916cfb7ae4c7" }, "downloads": -1, "filename": "h11-0.8.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "7be73466fcb1af2961122acb7fc890e2", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 55828, "upload_time": "2018-04-15T05:15:32", "url": "https://files.pythonhosted.org/packages/f9/f3/8e4cf5fa1a3d8bda942a0b1cf92f87815494216fd439f82eb99073141ba0/h11-0.8.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "979d784feea6d576582558ac742005ad", "sha256": "acca6a44cb52a32ab442b1779adf0875c443c689e9e028f8d831a3769f9c5208" }, "downloads": -1, "filename": "h11-0.8.1.tar.gz", "has_sig": false, "md5_digest": "979d784feea6d576582558ac742005ad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 94009, "upload_time": "2018-04-15T05:15:34", "url": "https://files.pythonhosted.org/packages/cd/de/1ea0125d32541f33e59d59bcad9260cf110c150c3db6fdea0e55159ba26d/h11-0.8.1.tar.gz" } ], "0.9.0": [ { "comment_text": "", "digests": { "md5": "f7675187149dddb56659c3eced72781b", "sha256": "4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1" }, "downloads": -1, "filename": "h11-0.9.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f7675187149dddb56659c3eced72781b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 53607, "upload_time": "2019-05-15T18:43:45", "url": "https://files.pythonhosted.org/packages/5a/fd/3dad730b0f95e78aeeb742f96fa7bbecbdd56a58e405d3da440d5bfb90c6/h11-0.9.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "53affae306153388512040e038519fa3", "sha256": "33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1" }, "downloads": -1, "filename": "h11-0.9.0.tar.gz", "has_sig": false, "md5_digest": "53affae306153388512040e038519fa3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 93331, "upload_time": "2019-05-15T18:43:47", "url": "https://files.pythonhosted.org/packages/34/5a/abaa557d20b210117d8c3e6b0b817ce9b329b2e81f87612e60102a924323/h11-0.9.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "f7675187149dddb56659c3eced72781b", "sha256": "4bc6d6a1238b7615b266ada57e0618568066f57dd6fa967d1290ec9309b2f2f1" }, "downloads": -1, "filename": "h11-0.9.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f7675187149dddb56659c3eced72781b", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 53607, "upload_time": "2019-05-15T18:43:45", "url": "https://files.pythonhosted.org/packages/5a/fd/3dad730b0f95e78aeeb742f96fa7bbecbdd56a58e405d3da440d5bfb90c6/h11-0.9.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "53affae306153388512040e038519fa3", "sha256": "33d4bca7be0fa039f4e84d50ab00531047e53d6ee8ffbc83501ea602c169cae1" }, "downloads": -1, "filename": "h11-0.9.0.tar.gz", "has_sig": false, "md5_digest": "53affae306153388512040e038519fa3", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 93331, "upload_time": "2019-05-15T18:43:47", "url": "https://files.pythonhosted.org/packages/34/5a/abaa557d20b210117d8c3e6b0b817ce9b329b2e81f87612e60102a924323/h11-0.9.0.tar.gz" } ] }