Skip to main content

ASGI protocol inspector — validates, traces, and analyzes your ASGI app

Project description

asgion

CI Coverage PyPI Python License

ASGI protocol inspector and trace engine. Catch subtle protocol violations your tests miss — before they hit production.

Why asgion?

ASGI apps can pass all tests while still violating the protocol:

  • Sending response body before http.response.start
  • Writing to a closed WebSocket connection
  • Exiting without completing a streaming response
  • Returning malformed event payloads

Frameworks catch some of this. asgion validates the full ASGI contract — state machines, event schemas, scope fields, and semantic constraints across HTTP, WebSocket, and Lifespan.

Highlights

  • Full ASGI contract validation — 164 rules across HTTP, WebSocket, and Lifespan
  • Trace engine — record every receive()/send() with nanosecond timestamps and inline violation markers
  • CI-ready — deterministic exit codes and JSON output
  • CLI, Python API, pytest plugin — fits any workflow
  • Zero runtime dependencies — pure Python 3.12+
  • O(1) per message — safe for hot paths, no overhead when tracing is off

Works with any ASGI app: FastAPI, Starlette, Litestar, Django (ASGI), or bare ASGI handlers.

Quickstart

Get started in under a minute:

pip install asgion[cli]

Given a buggy app that sends body before http.response.start:

# myapp.py
async def app(scope, receive, send):
    if scope["type"] == "http":
        await send({"type": "http.response.body", "body": b"oops"})       # wrong order
        await send({"type": "http.response.start", "status": 200, "headers": []})
        await send({"type": "http.response.body", "body": b"hello"})

Check finds protocol violations:

asgion check myapp:app
CHECK  myapp:app

── GET / ─────────────────────────────────────────────────────────
  [HF-002] error: http.response.body sent without preceding http.response.start
    hint: Send http.response.start before any http.response.body
  [SEM-002] info: No Content-Type header on 2xx response
    hint: Responses with a body should include a Content-Type header

2 violations (1 error, 1 info)

What is HF-002? Look up any rule directly:

asgion rules HF-002
RULE  [HF-002] error
  http.response.body sent without preceding http.response.start
    hint: Send http.response.start before any http.response.body

  layer: http.fsm
  applies to: http

Trace shows the full event timeline for the same app:

asgion trace myapp:app
TRACE  GET / (0.063ms, TTFB 0.035ms)

     0.016ms  send     http.response.body  4 bytes  ← HF-002 (error)
     0.035ms  send     http.response.start  200  (+0.019ms)  ← SEM-002 (info)
     0.052ms  send     http.response.body  5 bytes  (+0.016ms)

  Events: 3  |  Violations: 2 (1 error, 1 info)
asgion trace myapp:app --min-severity error   # only error-level markers
asgion trace myapp:app --out ./traces/        # save as JSON files

Exit codes: 0 = clean, 1 = violations (--strict), 2 = runtime error. See asgion check --help.

See the full rule list for all available rules and their descriptions.

Python API

from asgion import Inspector

inspector = Inspector(app)
# ... drive the app via httpx, TestClient, etc. ...
assert inspector.violations == []  # fails if any protocol violation occurred

With tracing:

inspector = Inspector(app, trace=True)
async with httpx.AsyncClient(transport=ASGITransport(inspector)) as client:
    await client.get("/api/users")

record = inspector.traces[0]
record.scope.method      # "GET"
record.scope.path        # "/api/users"
record.summary.ttfb_ns   # time to first byte (ns)

As middleware:

from asgion import inspect

uvicorn.run(inspect(app))

Pytest Plugin

Integrate protocol validation directly into your test suite:

pip install asgion[pytest]
async def test_my_app(asgi_inspect):
    inspector = asgi_inspect(my_app)
    async with httpx.AsyncClient(transport=ASGITransport(inspector)) as client:
        await client.get("/users")
    assert inspector.violations == []
pytest --asgi-strict   # auto-check all tests

Configuration

Via pyproject.toml, .asgion.toml, or Python API. See configuration docs and full rule list.

[tool.asgion]
profile = "recommended"
exclude_rules = ["SEM-006"]

Contributing

git clone https://github.com/ack1d/asgion.git
cd asgion
uv sync --group dev
uv run pytest

If you have Task installed: task check runs lint, typecheck, and tests.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

asgion-0.5.1.tar.gz (43.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

asgion-0.5.1-py3-none-any.whl (60.4 kB view details)

Uploaded Python 3

File details

Details for the file asgion-0.5.1.tar.gz.

File metadata

  • Download URL: asgion-0.5.1.tar.gz
  • Upload date:
  • Size: 43.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for asgion-0.5.1.tar.gz
Algorithm Hash digest
SHA256 7700f73087619546c62ae00b447c7a3de636de6b525b28ca95acdefb23e39ae6
MD5 e9b130332f20f5e05a586a3b4f15c45a
BLAKE2b-256 8313476a43ae08302d205945b9c456a686423446e98d45c763f8f93d8028a564

See more details on using hashes here.

Provenance

The following attestation bundles were made for asgion-0.5.1.tar.gz:

Publisher: publish.yml on ack1d/asgion

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file asgion-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: asgion-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 60.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for asgion-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 116c6b3948e02f6ccbfc0a8dc4925e2026fe7a34fbe9c31ad7a2e93918dcfbef
MD5 59ceeab6f51fae7d22da51d7eebce24e
BLAKE2b-256 d97e4a5f6373bbb99b93d9e3b756fd301f960ca558b819c541bb8f62fc89e009

See more details on using hashes here.

Provenance

The following attestation bundles were made for asgion-0.5.1-py3-none-any.whl:

Publisher: publish.yml on ack1d/asgion

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page