A rudimentary HTTP client using :mod:`asyncio`

async def _asyncio_send(loop, req, *, timeout=10, max_redirects=10):
    """A rudimentary HTTP client using :mod:`asyncio`"""
    if not any(h.lower() == 'user-agent' for h in req.headers):
        req = req.with_headers({'User-Agent': _ASYNCIO_USER_AGENT})
    url = urllib.parse.urlsplit(
        req.url + '?' + urllib.parse.urlencode(req.params))
    open_ = partial(asyncio.open_connection, url.hostname, loop=loop)
    connect = open_(443, ssl=True) if url.scheme == 'https' else open_(80)
    reader, writer = await connect
    try:
        headers = '\r\n'.join([
            '{} {} HTTP/1.1'.format(req.method, url.path + '?' + url.query),
            'Host: ' + url.hostname,
            'Connection: close',
            'Content-Length: {}'.format(len(req.content or b'')),
            '\r\n'.join(starmap('{}: {}'.format, req.headers.items())),
        ])
        writer.write(b'\r\n'.join([headers.encode('latin-1'),
                                   b'', req.content or b'']))
        response_bytes = BytesIO(
            await asyncio.wait_for(reader.read(), timeout=timeout))
    finally:
        writer.close()
    resp = HTTPResponse(_SocketAdaptor(response_bytes),
                        method=req.method, url=req.url)
    resp.begin()
    status = resp.getcode()
    if 300 <= status < 400 and 'Location' in resp.headers and max_redirects:
        new_url = urllib.parse.urljoin(req.url, resp.headers['Location'])
        return await _asyncio_send(
            loop, req.replace(url=new_url),
            timeout=timeout,
            max_redirects=max_redirects-1)
    return Response(status, content=resp.read(), headers=resp.headers)