without-http 0.0.0__tar.gz → 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: without-http
3
+ Version: 0.0.2
4
+ Summary: A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets.
5
+ Author: Josh Karpel
6
+ Author-email: Josh Karpel <josh.karpel@gmail.com>
7
+ License-Expression: MIT
8
+ Classifier: Development Status :: 2 - Pre-Alpha
9
+ Classifier: Framework :: AsyncIO
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Topic :: Internet :: WWW/HTTP
16
+ Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
17
+ Classifier: Topic :: Software Development :: Libraries
18
+ Classifier: Typing :: Typed
19
+ Requires-Dist: without-core==0.0.2
20
+ Requires-Dist: without-asgi==0.0.2
21
+ Requires-Dist: h11>=0.16
22
+ Requires-Dist: h2>=4.1
23
+ Requires-Dist: wsproto>=1.2
24
+ Requires-Python: >=3.14
25
+ Description-Content-Type: text/markdown
26
+
27
+ # without-http
28
+
29
+ A sans-IO-backed ASGI **server** and **HTTP client** for `without`. Where
30
+ [`without-asgi`](../without-asgi) is the *app* side of the ASGI boundary (it turns
31
+ a server's `receive`/`send` into typed streams), `without-http` is the *server*
32
+ side: it owns the socket and the HTTP wire protocol, and drives any ASGI app via
33
+ `app(scope, receive, send)`.
34
+
35
+ The wire-protocol state machines are themselves sans-IO libraries:
36
+ [`h11`](https://h11.readthedocs.io/) for HTTP/1.1,
37
+ [`h2`](https://python-hyper.org/projects/h2/) for HTTP/2, and
38
+ [`wsproto`](https://python-hyper.org/projects/wsproto/) for WebSockets.
39
+ `without-http` reads and writes socket bytes with `asyncio`, feeds them through
40
+ those state machines, and uses `without-asgi`'s server-direction codecs to
41
+ translate between typed events and the ASGI dicts an app expects.
42
+
43
+ ```python
44
+ from without import sleep_forever
45
+ from without_asgi import make_asgi_app
46
+ from without_http import ConnectionPool, serving
47
+
48
+ app = make_asgi_app(lifespan, http=router.dispatch, websocket=sockets.dispatch)
49
+
50
+ async with serving(app, host="127.0.0.1", port=8000):
51
+ await sleep_forever() # run until cancelled
52
+
53
+ async with ConnectionPool() as pool:
54
+ async with pool.request("GET", "http://127.0.0.1:8000/items") as (head, body):
55
+ assert head.status == 200
56
+ data = await body.read()
57
+ ```
58
+
59
+ Because `without-http` speaks plain ASGI to the app, *any* ASGI app runs over it,
60
+ interchangeably with uvicorn. The server handles TLS, HTTP/2 (by ALPN or prior
61
+ knowledge), keep-alive, WebSockets over the HTTP/1.1 upgrade, per-handler
62
+ isolation, and flow control. The client is a `ConnectionPool` with a `(head,
63
+ body)` response split, buffered and streaming bodies in both directions,
64
+ opt-in trailers, HTTP/2 multiplexing, per-host connection bounds, per-phase
65
+ request timeouts, consumer-driven duplex (with bidirectional streaming over
66
+ HTTP/2), and `stack`-composed middleware.
67
+
68
+ See the
69
+ [`without-http` guide](https://without.help/without-http/)
70
+ (with the [API reference](https://without.help/reference/without_http/))
71
+ for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3).
@@ -0,0 +1,45 @@
1
+ # without-http
2
+
3
+ A sans-IO-backed ASGI **server** and **HTTP client** for `without`. Where
4
+ [`without-asgi`](../without-asgi) is the *app* side of the ASGI boundary (it turns
5
+ a server's `receive`/`send` into typed streams), `without-http` is the *server*
6
+ side: it owns the socket and the HTTP wire protocol, and drives any ASGI app via
7
+ `app(scope, receive, send)`.
8
+
9
+ The wire-protocol state machines are themselves sans-IO libraries:
10
+ [`h11`](https://h11.readthedocs.io/) for HTTP/1.1,
11
+ [`h2`](https://python-hyper.org/projects/h2/) for HTTP/2, and
12
+ [`wsproto`](https://python-hyper.org/projects/wsproto/) for WebSockets.
13
+ `without-http` reads and writes socket bytes with `asyncio`, feeds them through
14
+ those state machines, and uses `without-asgi`'s server-direction codecs to
15
+ translate between typed events and the ASGI dicts an app expects.
16
+
17
+ ```python
18
+ from without import sleep_forever
19
+ from without_asgi import make_asgi_app
20
+ from without_http import ConnectionPool, serving
21
+
22
+ app = make_asgi_app(lifespan, http=router.dispatch, websocket=sockets.dispatch)
23
+
24
+ async with serving(app, host="127.0.0.1", port=8000):
25
+ await sleep_forever() # run until cancelled
26
+
27
+ async with ConnectionPool() as pool:
28
+ async with pool.request("GET", "http://127.0.0.1:8000/items") as (head, body):
29
+ assert head.status == 200
30
+ data = await body.read()
31
+ ```
32
+
33
+ Because `without-http` speaks plain ASGI to the app, *any* ASGI app runs over it,
34
+ interchangeably with uvicorn. The server handles TLS, HTTP/2 (by ALPN or prior
35
+ knowledge), keep-alive, WebSockets over the HTTP/1.1 upgrade, per-handler
36
+ isolation, and flow control. The client is a `ConnectionPool` with a `(head,
37
+ body)` response split, buffered and streaming bodies in both directions,
38
+ opt-in trailers, HTTP/2 multiplexing, per-host connection bounds, per-phase
39
+ request timeouts, consumer-driven duplex (with bidirectional streaming over
40
+ HTTP/2), and `stack`-composed middleware.
41
+
42
+ See the
43
+ [`without-http` guide](https://without.help/without-http/)
44
+ (with the [API reference](https://without.help/reference/without_http/))
45
+ for the full surface, including the deferred work (WebSockets over HTTP/2, HTTP/3).
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11.32,<0.12"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "without-http"
7
+ version = "0.0.2"
8
+ description = "A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.14"
12
+ classifiers = [
13
+ "Development Status :: 2 - Pre-Alpha",
14
+ "Framework :: AsyncIO",
15
+ "Intended Audience :: Developers",
16
+ "Operating System :: OS Independent",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3 :: Only",
19
+ "Programming Language :: Python :: 3.14",
20
+ "Topic :: Internet :: WWW/HTTP",
21
+ "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
22
+ "Topic :: Software Development :: Libraries",
23
+ "Typing :: Typed",
24
+ ]
25
+ dependencies = [
26
+ "without-core==0.0.2",
27
+ "without-asgi==0.0.2",
28
+ "h11>=0.16",
29
+ "h2>=4.1",
30
+ "wsproto>=1.2",
31
+ ]
32
+
33
+ [[project.authors]]
34
+ name = "Josh Karpel"
35
+ email = "josh.karpel@gmail.com"
36
+
37
+ [tool.uv.sources.without-core]
38
+ workspace = true
39
+
40
+ [tool.uv.sources.without-asgi]
41
+ workspace = true
@@ -0,0 +1,38 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11.32,<0.12"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "without-http"
7
+ version = "0.0.2"
8
+ description = "A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ authors = [
12
+ { name = "Josh Karpel", email = "josh.karpel@gmail.com" },
13
+ ]
14
+ requires-python = ">=3.14"
15
+ classifiers = [
16
+ "Development Status :: 2 - Pre-Alpha",
17
+ "Framework :: AsyncIO",
18
+ "Intended Audience :: Developers",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Python :: 3.14",
23
+ "Topic :: Internet :: WWW/HTTP",
24
+ "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
25
+ "Topic :: Software Development :: Libraries",
26
+ "Typing :: Typed",
27
+ ]
28
+ dependencies = [
29
+ "without-core==0.0.2",
30
+ "without-asgi==0.0.2",
31
+ "h11>=0.16",
32
+ "h2>=4.1",
33
+ "wsproto>=1.2",
34
+ ]
35
+
36
+ [tool.uv.sources]
37
+ without-core = { workspace = true }
38
+ without-asgi = { workspace = true }
@@ -0,0 +1,85 @@
1
+ from without_http.client import ClientExchange
2
+ from without_http.client import ClientMiddleware
3
+ from without_http.client import ClientRequest
4
+ from without_http.client import ClientResponse
5
+ from without_http.client import ConnectionPool
6
+ from without_http.client import CookieJar
7
+ from without_http.client import ResponseBody
8
+ from without_http.client import ResponseHead
9
+ from without_http.client import ResponseTrailers
10
+ from without_http.client import add_headers
11
+ from without_http.client import cookies
12
+ from without_http.client import follow_redirects
13
+ from without_http.client import stack
14
+ from without_http.client import wrap
15
+ from without_http.h2_wire import early_hint_headers
16
+ from without_http.h2_wire import request_headers
17
+ from without_http.h2_wire import response_headers
18
+ from without_http.h2_wire import response_status_and_headers
19
+ from without_http.h2_wire import scope_from_h2_headers
20
+ from without_http.h11_wire import h11_events_from_outbound
21
+ from without_http.h11_wire import inbound_from_event
22
+ from without_http.h11_wire import scope_from_request
23
+ from without_http.lifespan import LifespanError
24
+ from without_http.lifespan import run_lifespan
25
+ from without_http.server import Server
26
+ from without_http.server import serving
27
+ from without_http.socket_options import SocketOptions
28
+ from without_http.socket_options import receive_buffer_size
29
+ from without_http.socket_options import send_buffer_size
30
+ from without_http.socket_options import tcp_keepalive
31
+ from without_http.timeouts import ConnectTimeout
32
+ from without_http.timeouts import HTTPTimeout
33
+ from without_http.timeouts import PoolTimeout
34
+ from without_http.timeouts import ReadTimeout
35
+ from without_http.timeouts import Timeout
36
+ from without_http.timeouts import WriteTimeout
37
+ from without_http.tls import ALPN_PROTOCOLS
38
+ from without_http.tls import server_ssl_context
39
+ from without_http.ws_wire import is_websocket_upgrade
40
+ from without_http.ws_wire import websocket_scope_from_request
41
+ from without_http.ws_wire import ws_events_from_outbound
42
+
43
+ __all__ = [
44
+ "ALPN_PROTOCOLS",
45
+ "ClientExchange",
46
+ "ClientMiddleware",
47
+ "ClientRequest",
48
+ "ClientResponse",
49
+ "ConnectTimeout",
50
+ "ConnectionPool",
51
+ "CookieJar",
52
+ "HTTPTimeout",
53
+ "LifespanError",
54
+ "PoolTimeout",
55
+ "ReadTimeout",
56
+ "ResponseBody",
57
+ "ResponseHead",
58
+ "ResponseTrailers",
59
+ "Server",
60
+ "SocketOptions",
61
+ "Timeout",
62
+ "WriteTimeout",
63
+ "add_headers",
64
+ "cookies",
65
+ "early_hint_headers",
66
+ "follow_redirects",
67
+ "h11_events_from_outbound",
68
+ "inbound_from_event",
69
+ "is_websocket_upgrade",
70
+ "receive_buffer_size",
71
+ "request_headers",
72
+ "response_headers",
73
+ "response_status_and_headers",
74
+ "run_lifespan",
75
+ "scope_from_h2_headers",
76
+ "scope_from_request",
77
+ "send_buffer_size",
78
+ "server_ssl_context",
79
+ "serving",
80
+ "stack",
81
+ "tcp_keepalive",
82
+ "websocket_scope_from_request",
83
+ "wrap",
84
+ "ws_events_from_outbound",
85
+ ]