Metadata-Version: 2.5
Name: neva-asgi
Version: 0.1.1
Summary: ASGI middleware for the Neva framework.
Requires-Python: >=3.12
Requires-Dist: pyinstrument>=5.1.1
Requires-Dist: python-neva>=3.6.0
Requires-Dist: starlette>=0.41
Requires-Dist: structlog>=25.5.0
Provides-Extra: testing
Requires-Dist: httpx>=0.27; extra == 'testing'
Requires-Dist: pytest>=9.0.2; extra == 'testing'
Description-Content-Type: text/markdown

# neva-asgi

ASGI middleware for the [Neva](https://pypi.org/project/python-neva/) framework.

`python-neva` is the framework-agnostic core: it must not import an ASGI
framework. This package holds the middleware that used to live in
`neva.obs.middleware`, so that boundary holds.

It sits below the protocol integrations rather than inside one — `neva-fastapi`
and `neva-faststream` (in its ASGI mode) can both consume it without depending
on each other.

## Install

```bash
uv add neva-asgi
```

## Middleware

### `CorrelationMiddleware`

Assigns a correlation ID to every HTTP and WebSocket request, reusing an
inbound `X-Request-ID` or `X-Correlation-ID` when it is a valid UUID and
generating one otherwise. The ID is published on `scope["state"]["correlation_id"]`
and echoed on the response. It is also bound into structlog's context, so every
log line emitted while handling the request carries `correlation_id` without the
caller threading it through — structlog's default processor chain merges
contextvars, so this needs no logging configuration.

```python
from neva.asgi import CorrelationMiddleware

app.add_middleware(CorrelationMiddleware, header_name="X-Request-ID")
```

`generator` and `validator` are both injectable, so a service that uses ULIDs or
a non-UUID scheme can swap them.

### `ProfilerMiddleware`

Profiles each HTTP request with [pyinstrument](https://pyinstrument.readthedocs.io)
and writes an HTML report per request. It names the file after the correlation
ID when `CorrelationMiddleware` runs ahead of it, and falls back to a timestamp.

```python
from neva.asgi import ProfilerMiddleware

app.add_middleware(ProfilerMiddleware, path="./profiles", interval=0.001)
```

Intended for local and staging use: it profiles every request and writes a file
per request.

## Develop

```bash
uv sync --all-extras
poe lint && poe fmt && poe tc && poe test
```

Commits follow Conventional Commits with gitmoji via `cz commit`; releases are
cut with `cz bump`.
