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 — validates your ASGI application against the ASGI specification at runtime. Catches protocol violations, state machine errors, and event schema mismatches before they become production bugs.

Zero runtime dependencies. Python 3.12+.

Quickstart

Python API

pip install asgion
from asgion import inspect

app = inspect(app)  # wrap any ASGI app — zero config

Use Inspector when you need to access violations after driving the app:

from asgion import Inspector

inspector = Inspector(app)
# ... drive the app (httpx, TestClient, etc.) ...
assert inspector.violations == []

Use with any ASGI server:

import uvicorn

uvicorn.run(inspect(app), host="127.0.0.1", port=8000)

CLI

pip install asgion[cli]
asgion check myapp:app

What It Catches

164 rules across 12 layers — scope fields, event schemas, state machines, extensions, and semantic checks for HTTP, WebSocket, and Lifespan.

[G-005]  error    Message must be a dict
[HE-012] error    response.body 'body' must be bytes, got str
[HF-003] error    Duplicate http.response.start
[WE-008] warning  websocket.send has both 'bytes' and 'text' set

Every rule has an ID, severity, summary, and hint. See the full list: docs/rules.md

CLI Reference

asgion check

asgion check APP_PATH [OPTIONS]

Check an ASGI app for protocol violations.

Option Description
APP_PATH Module:attribute path (e.g. myapp:app)
--path PATH Paths to check (repeatable, default /). Prefix with protocol to set scope type: http:/path, https:/path, ws:/path, wss:/path
--strict Exit 1 on any violations
--format text|json Output format (default text)
--exclude-rules IDS Comma-separated rule IDs to skip
--min-severity LEVEL Minimum severity: perf, info, warning, error
--config FILE Path to .asgion.toml or pyproject.toml
--profile PROFILE Rule filter profile: strict, recommended, minimal, or a user-defined profile from config
--no-color Disable ANSI colors (also respects NO_COLOR env)
--no-lifespan Skip lifespan startup/shutdown checks
asgion check myapp:app --path /api/users           # HTTP (default)
asgion check myapp:app --path ws:/ws/chat          # WebSocket
asgion check myapp:app --path /api --path ws:/ws   # both

Exit codes: 0 = clean, 1 = violations (with --strict), 2 = runtime error.

asgion rules

asgion rules [OPTIONS]

List all validation rules.

Option Description
--format text|json Output format (default text)
--layer LAYER Filter by layer: general, http, websocket, lifespan
--severity LEVEL Filter by severity: perf, info, warning, error
--no-color Disable ANSI colors

asgion --version

Print version and exit.

Python API

from asgion import AsgionConfig, inspect

cfg = AsgionConfig(
    min_severity="warning",                # skip perf/info rules
    exclude_rules={"HE-012", "G-008"},     # suppress specific rules
    ttfb_threshold=2.0,                    # custom TTFB threshold (seconds)
)

wrapped = inspect(
    app,
    config=cfg,
    strict=False,                          # True to raise on violations
    on_violation=lambda v: print(v),       # real-time callback
    exclude_paths=["/health", "/metrics"], # skip these paths
)

Or select a built-in profile:

from asgion import BUILTIN_PROFILES, inspect

app = inspect(app, config=BUILTIN_PROFILES["recommended"])  # warning+ only

Parameters

Parameter Type Default Description
app ASGIApp required The ASGI application to wrap
config AsgionConfig None Rule filter settings and thresholds
strict bool False Raise ASGIProtocolError on any violation
on_violation callback None Called with each Violation in real-time
exclude_paths list[str] None Paths to skip validation
exclude_rules set[str] None Rule IDs to suppress (additive to config)
registry ValidatorRegistry None Custom validator registry

AsgionConfig

Can also be loaded from pyproject.toml or .asgion.toml:

[tool.asgion]
profile = "recommended"       # base profile: strict / recommended / minimal / user-defined
exclude_rules = ["SEM-006"]   # suppress specific rules (supports globs: "SEM-*")
include_rules = ["HF-*"]      # allowlist — only these rules fire
categories = ["http"]         # filter by layer prefix ("http" matches http.fsm, http.semantic, …)
ttfb_threshold = 2.0          # SEM-006: TTFB limit (seconds)
lifecycle_threshold = 30.0    # SEM-007: total connection time (seconds)
body_size_threshold = 10485760  # SEM-008: response size (bytes)

# User-defined profiles
[tool.asgion.profiles.ci]
min_severity = "error"
categories = ["http.fsm", "ws.fsm"]

Violation

@dataclass(frozen=True, slots=True)
class Violation:
    rule_id: str       # "HF-001", "G-010"
    severity: Severity # error, warning, info, perf
    message: str       # human-readable description
    hint: str          # suggestion for fixing
    scope_type: str    # "http", "websocket", "lifespan"
    path: str          # "/api/users"
    method: str        # "GET"

pytest Plugin

pip install asgion[pytest]
async def test_my_app(asgi_inspect):
    app = asgi_inspect(my_app)
    async with httpx.AsyncClient(transport=ASGITransport(app)) as client:
        resp = await client.get("/users")
    assert app.violations == []

Auto-check violations with a marker:

@pytest.mark.asgi_validate(min_severity="error")
async def test_strict(asgi_inspect):
    app = asgi_inspect(my_app)
    # ... drive the app — violations checked automatically at teardown

Or enable globally for all tests using asgi_inspect:

pytest --asgi-strict
pytest --asgi-strict --asgi-min-severity warning

Comparison

Feature asgion asgiref.testing Manual testing
Scope validation 71 rules basic none
Event schema checks 43 rules none manual
State machine (FSM) 34 rules none none
Semantic checks 13 rules none none
Extension validation 3 rules none none
pytest plugin yes no n/a
Real-time callbacks yes no n/a
CLI tool yes no no
Zero dependencies yes no (asgiref) n/a
Rule suppression per-rule no n/a

Contributing

git clone https://github.com/ack1d/asgion.git
cd asgion
uv sync --group dev
uv run pytest              # run tests
uv run ruff check src/     # lint
uv run mypy src/           # type check

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.4.0.tar.gz (34.6 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.4.0-py3-none-any.whl (49.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for asgion-0.4.0.tar.gz
Algorithm Hash digest
SHA256 f3010ca5b0c3162b59fc7294aa2ae084f5edb67854a17ddd250f7f683a143f05
MD5 c2ffc8c18854133da3bd27a9c4f7e4a7
BLAKE2b-256 490a992d2b84075bccaa759e1f2a144927b6a80db8b564ba73a717406c166e3d

See more details on using hashes here.

Provenance

The following attestation bundles were made for asgion-0.4.0.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.4.0-py3-none-any.whl.

File metadata

  • Download URL: asgion-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 49.0 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.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e8ea9a0a15820fd3a5d5e18af7a4b081ea96a6367db38ffa611ab8604822a413
MD5 51615bd71103b577be8969885fda78b8
BLAKE2b-256 03c580daa8c86ed3b125860510e7192e6463060f68beafdf21ba40131fb597d7

See more details on using hashes here.

Provenance

The following attestation bundles were made for asgion-0.4.0-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