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.
- without_http-0.0.2/PKG-INFO +71 -0
- without_http-0.0.2/README.md +45 -0
- without_http-0.0.2/pyproject.toml +41 -0
- without_http-0.0.2/pyproject.toml.orig +38 -0
- without_http-0.0.2/src/without_http/__init__.py +85 -0
- without_http-0.0.2/src/without_http/client.py +1636 -0
- without_http-0.0.2/src/without_http/h11_wire.py +107 -0
- without_http-0.0.2/src/without_http/h2_wire.py +144 -0
- without_http-0.0.2/src/without_http/lifespan.py +103 -0
- without_http-0.0.2/src/without_http/server.py +946 -0
- without_http-0.0.2/src/without_http/socket_options.py +109 -0
- without_http-0.0.2/src/without_http/timeouts.py +129 -0
- without_http-0.0.2/src/without_http/tls.py +28 -0
- without_http-0.0.2/src/without_http/ws_wire.py +103 -0
- without_http-0.0.0/PKG-INFO +0 -5
- without_http-0.0.0/pyproject.toml +0 -9
- without_http-0.0.0/src/without_http/__init__.py +0 -0
|
@@ -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
|
+
]
|