Skip to main content

github status PyPI version Documentation Status

aiosonic - lightweight Python asyncio HTTP/WebSocket client

A very fast, lightweight Python asyncio HTTP/1.1, HTTP/2, and WebSocket client.

The repository is hosted on GitHub.

For full documentation, please see aiosonic docs.

Features

  • Keepalive support and smart pool of connections
  • Multipart file uploads
  • Handling of chunked responses and requests
  • Connection timeouts and automatic decompression
  • Automatic redirect following
  • Fully type-annotated
  • WebSocket support
  • HTTP proxy support
  • Sessions with cookie persistence
  • Elegant key/value cookies
  • (Nearly) 100% test coverage
  • HTTP/2 (enabled with a flag)

Requirements

  • Python >= 3.10 (or PyPy 3.11+)

Installation

pip install aiosonic

Getting Started

Below is an example demonstrating basic HTTP client usage:

import asyncio
import aiosonic
import json

async def run():
    client = aiosonic.HTTPClient()

    # Sample GET request
    response = await client.get('https://www.google.com/')
    assert response.status_code == 200
    assert 'Google' in (await response.text())

    # POST data as multipart form
    url = "https://postman-echo.com/post"
    posted_data = {'foo': 'bar'}
    response = await client.post(url, data=posted_data)
    assert response.status_code == 200
    data = json.loads(await response.content())
    assert data['form'] == posted_data

    # POST data as JSON
    response = await client.post(url, json=posted_data)
    assert response.status_code == 200
    data = json.loads(await response.content())
    assert data['json'] == posted_data

    # GET request with timeouts
    from aiosonic.timeout import Timeouts
    timeouts = Timeouts(sock_read=10, sock_connect=3)
    response = await client.get('https://www.google.com/', timeouts=timeouts)
    assert response.status_code == 200
    assert 'Google' in (await response.text())

    print('HTTP client success')

if __name__ == '__main__':
    asyncio.run(run())

WebSocket Usage

Below is an example demonstrating how to use aiosonic's WebSocket support:

import asyncio
from aiosonic import WebSocketClient

async def main():
    # Replace with your WebSocket server URL
    ws_url = "ws://localhost:8080"
    async with WebSocketClient() as client:
        async with await client.connect(ws_url) as ws:
            # Send a text message
            await ws.send_text("Hello WebSocket")
            
            # Receive an echo response
            response = await ws.receive_text()
            print("Received:", response)
            
            # Send a ping and wait for the pong
            await ws.ping(b"keep-alive")
            pong = await ws.receive_pong()
            print("Pong received:", pong)

            # You can have a "reader" task like this:
            async def ws_reader(conn):
                async for msg in conn:
                    # handle the message...
                    # msg is an instance of aiosonic.web_socket_client.Message dataclass.
                    pass

            asyncio.create_task(ws_reader(ws))
            
            # Gracefully close the connection (optional)
            await ws.close(code=1000, reason="Normal closure")

if __name__ == "__main__":
    asyncio.run(main())

HTTP/2 Usage

HTTP/2 requires HTTPS. Enable it at the client level or per-request.

Client-level (all requests use HTTP/2):

import asyncio
import aiosonic

async def run():
    client = aiosonic.HTTPClient(http2=True)
    response = await client.get("https://http2.golang.org/reqinfo")
    assert response.status_code == 200
    print(await response.text())

asyncio.run(run())

Per-request (opt in for a single call):

import asyncio
import aiosonic

async def run():
    client = aiosonic.HTTPClient()
    response = await client.get("https://http2.golang.org/reqinfo", http2=True)
    assert response.status_code == 200
    print(await response.text())

asyncio.run(run())

Api Wrapping

You can easily wrap APIs with BaseClient and override its hooks to customize the response handling.

import asyncio
import json
from aiosonic import BaseClient

class GitHubAPI(BaseClient):
    base_url = "https://api.github.com"
    default_headers = {
        "Accept": "application/vnd.github+json",
        "X-GitHub-Api-Version": "2022-11-28",
        # "Authorization": "Bearer YOUR_GITHUB_TOKEN",
    }

    async def process_response(self, response):
        body = await response.text()
        return json.loads(body)

    async def users(self, username: str, **kwargs):
        return await self.get(f"/users/{username}", **kwargs)
    
    async def update_repo(self, owner: str, repo: str, description: str):
        data = {
            "name": repo,
            "description": description,
        }
        return await self.put(f"/repos/{owner}/{repo}", json=data)


async def main():
    # You can pass an existing aiosonic.HTTPClient() instance in the constructor.
    # If not provided, BaseClient will create a new instance automatically.
    github = GitHubAPI()
    # Call the custom 'users' method to get data for user "sonic182"
    user_data = await github.users("sonic182")
    print(json.dumps(user_data, indent=2))


if __name__ == '__main__':
    asyncio.run(main())

Note: You may wanna do a singleton of your clients implementations in order to reuse the internal HTTPClient instance, and it's pool of connections (efficient usage of the client), an example:

class SingletonMixin:
    _instances = {}

    def __new__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__new__(cls)
        return cls._instances[cls]

class GitHubAPI(BaseClient, SingletonMixin):
    base_url = "https://api.github.com"
    # ... the rest of the code

# now, each instance of the class will be the first created
gh = GitHubAPI()
g2 = GitHubAPI()

gh == gh2

Benchmarks

A simple performance benchmark script is included in the tests folder. For example:

python scripts/performance.py

Example output:

{
  "aiohttp": "5000 requests in 558.31 ms",
  "aiosonic": "5000 requests in 563.95 ms",
  "requests": "5000 requests in 10306.90 ms",
  "aiosonic_cyclic": "5000 requests in 642.15 ms",
  "httpx": "5000 requests in 7920.04 ms"
}

aiosonic is 1457.99% faster than requests aiosonic is -1.38% faster than aiosonic cyclic

Note:
These benchmarks are basic and machine-dependent. They are intended as a rough comparison.

HTTP/2 Known Limitations

  • Server push not supported — push promise frames are silently ignored (PushPromiseReceived, PushedStreamReset, PushedStreamClosed).
  • No cleartext HTTP/2 (h2c) — HTTP/2 requires TLS. This matches RFC 7540 §3.3 browser requirements and is intentional.

TODO's

  • Better documentation
  • International domains and URLs (IDNA + cache)
  • Basic/Digest authentication

Development

Install development dependencies with Poetry:

poetry install

It is recommended to install Poetry in a separate virtual environment (via apt, pacman, etc.) rather than in your development environment. You can configure Poetry to use an in-project virtual environment by running:

poetry config virtualenvs.in-project true

Running Tests

poetry run pytest

Contributing

  1. Fork the repository.
  2. Create a branch named feature/your_feature.
  3. Commit your changes, push, and submit a pull request.

Thanks for contributing!

Contributors

Contributors

Release files for aiosonic 1.0.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for aiosonic 1.0.6
File Size Uploaded
aiosonic-1.0.6.tar.gz 42.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for aiosonic 1.0.6
File Interpreter ABI Platform
aiosonic-1.0.6-py3-none-any.whl Python 3 none any Details

Total release size: 89.5 kB

Release files / aiosonic-1.0.6.tar.gz

Download URL aiosonic-1.0.6.tar.gz
Size 42.1 kB
Tags Source
SHA-256 checksum
How to use checksums
36c1db8514558de993728f64010660fd6e82597e00dc1ad6fd03b463aded98b6
BLAKE2b-256 checksum
How to use checksums
dcda0bd5e619cd2196cf9fb32f76badc6f23bdc744fbffc6d31845d22f01393c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / aiosonic-1.0.6-py3-none-any.whl

Download URL aiosonic-1.0.6-py3-none-any.whl
Size 47.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0e5d8a085a53fbb3c6a25dbb0d6c6407d4a97d991f0e9f037864225825290271
BLAKE2b-256 checksum
How to use checksums
2280277e82c78055ae9b999e3e6160c08370def5bccbb6b32390eafa9e219408
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

1.0.6 This release

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.31.1

2 release files

0.31.0

2 release files

0.30.1

2 release files

0.30.0

2 release files

0.29.0

2 release files

0.28.0

2 release files

0.26.0

2 release files

0.25.0

2 release files

0.24.0

2 release files

0.23.1

2 release files

0.23.0

2 release files

0.22.3

2 release files

0.22.2

2 release files

0.22.0

2 release files

0.21.0

2 release files

0.19.0

2 release files

0.18.1

2 release files

0.18.0

1 release file

0.17.1

1 release file

0.17.0

1 release file

0.16.2

1 release file

0.16.1

1 release file

0.16.0

1 release file

0.15.1

1 release file

0.15.0

1 release file

0.14.1

1 release file

0.14.0

1 release file

0.13.1

1 release file

0.13.0

1 release file

0.12.0

1 release file

0.11.3

1 release file

0.11.2

1 release file

0.11.1

1 release file

0.11.0

1 release file

0.10.1

1 release file

0.10.0

1 release file

0.9.7

1 release file

0.9.6

1 release file

0.9.5

1 release file

0.9.4

1 release file

0.9.3

1 release file

0.9.2

1 release file

0.9.1

1 release file

0.9.0

1 release file

0.8.1

1 release file

0.8.0

2 release files

0.7.2

1 release file

0.7.1

1 release file

0.7.0

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page