Welcome to uvhttp’s documentation!¶
uvhttp is an extremely fast HTTP client written in Python. It uses uvloop and outperforms all known production-quality Python HTTP clients.
Benchmarks¶
All benchmarks running with 8 cores, see bencher.
uvhttp benchmark:
➜ uvhttp git:(master) ✗ ./uvhttp.py
100000 HTTP requests in 3.35 seconds, 29836.38 rps
➜ uvhttp git:(master) ✗
asyncio with aiohttp:
➜ bencher git:(master) ✗ python3 http_test_asyncio_aiohttp.py
10000 HTTP requests in 1.67 seconds, 5991.36 rps
➜ bencher git:(master) ✗
uvloop with aiohttp is still not great:
➜ bencher git:(master) ✗ python3 http_test_uvloop_aiohttp.py
10000 HTTP requests in 1.97 seconds, 5065.03 rps
➜ bencher git:(master) ✗
gevent is even worse:
➜ bencher git:(master) ✗ python3 http_test_gevent.py
10000 HTTP requests in 6.93 seconds, 1443.02 rps
➜ bencher git:(master) ✗
We are striving for go performance:
http_test.go:53: 100000 HTTP requests in 2.274069869 seconds, 43974.02268206211 rps
Installation¶
uvhttp requires Python 3.5 or greater and can be installed from pip:
pip install uvhttp
Usage¶
HTTP requests can be made with a Session object.
-
class
uvhttp.http.
Session
(conn_limit, loop, resolver=None)[source]¶ A Session is an HTTP request pool that allows up to request_limit requests in flight at once, with up to conn_limit connections per ip/port:
from uvhttp.utils import start_loop import uvhttp.http NUM_CONNS_PER_HOST = 10 @start_loop async def main(loop): session = uvhttp.http.Session(NUM_CONNS_PER_HOST, loop) for _ in range(6): response = await session.get(b'http://www.google.com/', headers={ b'User-Agent': b'fast-af' }) print(response.text) if __name__ == '__main__': main()
The module is designed to send HTTP requests very quickly, so all methods require
bytes
objects instead of strings.-
request
(method, url, headers=None, data=None, ssl=None)[source]¶ Make a new HTTP request in the pool.
headers
can be passed as a dictionary ofbyte
(notstr
).data
is a byte array of data to include in the request.ssl
can be assl.SSLContext
or True and must match the schema in the URL.
-
The Session
object will return an HTTPRequest
:
-
class
uvhttp.http.
HTTPRequest
(connection)[source]¶ An HTTP request instantiated from a
Session
. HTTP requests are returned by the HTTP session once they are sent and contain all information about the request and response.-
close
()[source]¶ Closes the request, signalling that we’re done with the request. The connection is kept open and released back to the pool for re-use.
-
gzipped
¶ Return true if the response is gzipped.
-
headers
¶ Return the headers from the request in a case-insensitive dictionary.
-
send
(method, host, path, headers=None, data=None)[source]¶ Send the request (usually called by the Session object).
-
text
¶ The string representation of the response body. It will be ungzipped and encoded as a unicode string.
-
You can also pass a Resolver
to the Session
:
-
class
uvhttp.dns.
Resolver
(loop, ipv6=True, nameservers=None)[source]¶ Caching DNS resolver wrapper for aiodns.
-
add_to_cache
(host, host_port, ip, ttl, port=80, overwrite=True)[source]¶ Add the address pair
host
andhost_port
to the DNS cache pointing toip
andport
.The result will be cached for
ttl
(or forever ifttl
is 0).If
overwrite
is true, the result will overwrite any previous entries, otherwise it will be appended.
-
Tests¶
It also provides a wrapper around Sanic that makes it easier to use in writing unit tests for uvhttp.
-
class
uvhttp.utils.
HttpServer
(host=None, port=None, https_host=None, https_port=None)[source]¶ An HTTP server that uses Sanic in the backend to help write unit tests.
-
add_routes
()[source]¶ A function for adding all of the routes you need. Implement this in your inherited class to add your endpoints.
-
https_url
¶ Return the HTTPS URL of the started server.
-
url
¶ Return the URL of the started server.
-
An example of the usage is:
import uvhttp.http
from uvhttp.utils import http_server, HttpServer
from nose.tools import assert_equal
@http_server(HttpServer)
async def test_test_server(server, loop):
session = uvhttp.http.Session(10, loop)
response = await session.get(server.url + b'echo')
assert_equal(response.json()['url'], 'http://127.0.0.1/echo')