An opinionated HTTP/WebSocket router for without-asgi: trie matching, typed path params, 405-vs-404, mounting, and OpenAPI.
Project description
without-web
An opinionated HTTP and WebSocket router for
without-asgi. without-asgi deliberately ships no router,
only the unopinionated boundary and composition tools. without-web is the
opinionated layer on top: t-string patterns with typed parameters, typed request
extraction, 405-vs-404, mounting, scoped middleware, exception handlers, and
OpenAPI.
It snaps onto the boundary through nothing but the existing HttpRouter type:
Router.dispatch is an HttpRouter[T], so make_asgi_app(http=router.dispatch)
just works, and bring-your-own (or no router at all) stays first-class.
import json
from without_asgi import Response, make_asgi_app
from without_web import INT, Router, get, path_param
uid = path_param("id", INT) # one token: a pattern segment AND a typed read
@get(t"/users/{uid}", uid) # t-string pattern; `@get` returns a Route value
async def show_user(state, user_id: int): # user_id is an int, no `assert isinstance`
body = json.dumps({"id": user_id}).encode()
return Response(status=200, headers=((b"content-type", b"application/json"),), body=body)
router = Router(routes=(show_user,), fallback=not_found)
app = make_asgi_app(lifespan, http=router.dispatch)
Matching is a pure walk of an immutable trie, so precedence, 405-vs-404, and
mounting fall out of the structure. Converters and extractors parse, they don't
validate: a path param arrives already typed, and OpenAPI is a merge of the
self-descriptions each layer recovers from structure rather than a blob declared
by hand. Encoding stays the app's choice, so the router ships no
json_response-style helper.
See the
without-web guide
(with the API reference)
for the full surface: patterns, extractors, streaming input, mounting,
middleware, exception handlers, OpenAPI, and WebSocket routing.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file without_web-0.0.1.tar.gz.
File metadata
- Download URL: without_web-0.0.1.tar.gz
- Upload date:
- Size: 20.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88482eb55ff6c57c75f56e281a44a3a94392443654418939b5aa9728803c39fc
|
|
| MD5 |
9ecec9bc3072fff6b213d58c0bf672a8
|
|
| BLAKE2b-256 |
5ff9000e8ec3ffe54333288dfd66a45aaaaa92fa968bc3a78a070068d9d3bc4a
|
File details
Details for the file without_web-0.0.1-py3-none-any.whl.
File metadata
- Download URL: without_web-0.0.1-py3-none-any.whl
- Upload date:
- Size: 26.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3813916df67a3aceb239210924f62eef55fc0c77d1980de60142684787bef4d9
|
|
| MD5 |
aa433dc77178452f475f111405c6e169
|
|
| BLAKE2b-256 |
cd1114f529b219192f4a2877a2867232eed3ee5f651018340354c6a999fbde97
|