Metadata-Version: 2.4
Name: without-http
Version: 0.0.1
Summary: A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets.
Author: Josh Karpel
Author-email: Josh Karpel <josh.karpel@gmail.com>
License-Expression: MIT
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Dist: without-core==0.0.1
Requires-Dist: without-asgi==0.0.1
Requires-Dist: h11>=0.16
Requires-Dist: h2>=4.1
Requires-Dist: wsproto>=1.2
Requires-Python: >=3.14
Description-Content-Type: text/markdown

# without-http

A sans-IO-backed ASGI **server** and **HTTP client** for `without`. Where
[`without-asgi`](../without-asgi) is the *app* side of the ASGI boundary (it turns
a server's `receive`/`send` into typed streams), `without-http` is the *server*
side: it owns the socket and the HTTP wire protocol, and drives any ASGI app via
`app(scope, receive, send)`.

The wire-protocol state machines are themselves sans-IO libraries:
[`h11`](https://h11.readthedocs.io/) for HTTP/1.1,
[`h2`](https://python-hyper.org/projects/h2/) for HTTP/2, and
[`wsproto`](https://python-hyper.org/projects/wsproto/) for WebSockets.
`without-http` reads and writes socket bytes with `asyncio`, feeds them through
those state machines, and uses `without-asgi`'s server-direction codecs to
translate between typed events and the ASGI dicts an app expects.

```python
from without import sleep_forever
from without_asgi import make_asgi_app
from without_http import ConnectionPool, serving

app = make_asgi_app(lifespan, http=router.dispatch, websocket=sockets.dispatch)

async with serving(app, host="127.0.0.1", port=8000):
    await sleep_forever()   # run until cancelled

async with ConnectionPool() as pool:
    async with pool.request("GET", "http://127.0.0.1:8000/items") as (head, body):
        assert head.status == 200
        data = await body.read()
```

Because `without-http` speaks plain ASGI to the app, *any* ASGI app runs over it,
interchangeably with uvicorn. The server handles TLS, HTTP/2 (by ALPN or prior
knowledge), keep-alive, WebSockets over the HTTP/1.1 upgrade, per-handler
isolation, and flow control. The client is a `ConnectionPool` with a `(head,
body)` response split, buffered and streaming bodies in both directions,
opt-in trailers, HTTP/2 multiplexing, and `stack`-composed middleware.

See the
[`without-http` guide](https://without.help/guides/without-http/)
(with the [API reference](https://without.help/reference/without_http/))
for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3,
duplex).
