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.

delete(*args, **kwargs)[source]

Make an HTTP DELETE request to url, see request().

get(*args, **kwargs)[source]

Make an HTTP GET request to url, see request().

head(*args, **kwargs)[source]

Make an HTTP HEAD request to url, see head().

post(*args, **kwargs)[source]

Make an HTTP POST request to url, see request().

put(*args, **kwargs)[source]

Make an HTTP PUT request to url, see request().

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 of byte (not str).

data is a byte array of data to include in the request.

ssl can be a ssl.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.

json()[source]

Return the JSON decoded version of the body.

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 and host_port to the DNS cache pointing to ip and port.

The result will be cached for ttl (or forever if ttl is 0).

If overwrite is true, the result will overwrite any previous entries, otherwise it will be appended.

fetch_from_cache(host, host_port)[source]

Retrieve the cached entry for the host and host_port address pair. Returns None if there are no cached entries.

filter_expired(addr_pair)[source]

Remove expired entries from a cached address pair.

resolve(host, port)[source]

Resolve host and port to its IP and port.

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.

echo(request)[source]

An echo endpoint that returns all of the data about the request.

https_url

Return the HTTPS URL of the started server.

start()[source]

Start the server.

stop()[source]

Stop the 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')

Indices and tables