without-http 0.0.2__tar.gz → 0.0.4__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 → without_http-0.0.4}/PKG-INFO +22 -12
- {without_http-0.0.2 → without_http-0.0.4}/README.md +17 -9
- {without_http-0.0.2 → without_http-0.0.4}/pyproject.toml +6 -4
- {without_http-0.0.2 → without_http-0.0.4}/pyproject.toml.orig +6 -4
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/__init__.py +44 -2
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/client.py +663 -125
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/h11_wire.py +34 -8
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/h2_wire.py +7 -2
- without_http-0.0.4/src/without_http/py.typed +0 -0
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/server.py +213 -32
- without_http-0.0.4/src/without_http/testing.py +599 -0
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/timeouts.py +5 -3
- without_http-0.0.4/src/without_http/tls.py +143 -0
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/ws_wire.py +16 -2
- without_http-0.0.2/src/without_http/tls.py +0 -28
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/lifespan.py +0 -0
- {without_http-0.0.2 → without_http-0.0.4}/src/without_http/socket_options.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: without-http
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets.
|
|
5
5
|
Author: Josh Karpel
|
|
6
6
|
Author-email: Josh Karpel <josh.karpel@gmail.com>
|
|
@@ -16,11 +16,13 @@ Classifier: Topic :: Internet :: WWW/HTTP
|
|
|
16
16
|
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
17
17
|
Classifier: Topic :: Software Development :: Libraries
|
|
18
18
|
Classifier: Typing :: Typed
|
|
19
|
-
Requires-Dist: without-core==0.0.
|
|
20
|
-
Requires-Dist: without-asgi==0.0.
|
|
19
|
+
Requires-Dist: without-core==0.0.4
|
|
20
|
+
Requires-Dist: without-asgi==0.0.4
|
|
21
21
|
Requires-Dist: h11>=0.16
|
|
22
22
|
Requires-Dist: h2>=4.1
|
|
23
23
|
Requires-Dist: wsproto>=1.2
|
|
24
|
+
Requires-Dist: aiohappyeyeballs>=2.6
|
|
25
|
+
Requires-Dist: brotli>=1.1
|
|
24
26
|
Requires-Python: >=3.14
|
|
25
27
|
Description-Content-Type: text/markdown
|
|
26
28
|
|
|
@@ -43,15 +45,15 @@ translate between typed events and the ASGI dicts an app expects.
|
|
|
43
45
|
```python
|
|
44
46
|
from without import sleep_forever
|
|
45
47
|
from without_asgi import make_asgi_app
|
|
46
|
-
from without_http import ConnectionPool, serving
|
|
48
|
+
from without_http import ConnectionPool, request, serving
|
|
47
49
|
|
|
48
50
|
app = make_asgi_app(lifespan, http=router.dispatch, websocket=sockets.dispatch)
|
|
49
51
|
|
|
50
52
|
async with serving(app, host="127.0.0.1", port=8000):
|
|
51
|
-
await sleep_forever()
|
|
53
|
+
await sleep_forever() # run until cancelled
|
|
52
54
|
|
|
53
55
|
async with ConnectionPool() as pool:
|
|
54
|
-
async with
|
|
56
|
+
async with request(pool, "GET", "http://127.0.0.1:8000/items") as (head, body):
|
|
55
57
|
assert head.status == 200
|
|
56
58
|
data = await body.read()
|
|
57
59
|
```
|
|
@@ -59,13 +61,21 @@ async with ConnectionPool() as pool:
|
|
|
59
61
|
Because `without-http` speaks plain ASGI to the app, *any* ASGI app runs over it,
|
|
60
62
|
interchangeably with uvicorn. The server handles TLS, HTTP/2 (by ALPN or prior
|
|
61
63
|
knowledge), keep-alive, WebSockets over the HTTP/1.1 upgrade, per-handler
|
|
62
|
-
isolation, and flow control.
|
|
63
|
-
|
|
64
|
-
opt-in trailers, HTTP/2
|
|
65
|
-
request timeouts, consumer-driven
|
|
66
|
-
HTTP/2), and `stack`-composed middleware.
|
|
64
|
+
isolation, and flow control. A client is a function from a request to a response, and
|
|
65
|
+
a `ConnectionPool` is the one that answers over the network: a `(head, body)` response
|
|
66
|
+
split, buffered and streaming bodies in both directions, opt-in trailers, HTTP/2
|
|
67
|
+
multiplexing, per-host connection bounds, per-phase request timeouts, consumer-driven
|
|
68
|
+
duplex (with bidirectional streaming over HTTP/2), and `stack`-composed middleware.
|
|
69
|
+
|
|
70
|
+
`without_http.testing` carries the same interface into a test: a mock client that answers
|
|
71
|
+
from a function, an ASGI client that drives an app in memory, and a loopback client that
|
|
72
|
+
runs the real wire protocols over no socket at all, plus the raw in-memory endpoints
|
|
73
|
+
those are built from, for a test that writes frames rather than requests.
|
|
67
74
|
|
|
68
75
|
See the
|
|
69
76
|
[`without-http` guide](https://without.help/without-http/)
|
|
70
77
|
(with the [API reference](https://without.help/reference/without_http/))
|
|
71
|
-
for the full surface,
|
|
78
|
+
for the full surface, and
|
|
79
|
+
[Alternatives](https://without.help/without-http/alternatives/) for where the
|
|
80
|
+
client and server stand against httpx, aiohttp, niquests, and the ASGI servers,
|
|
81
|
+
including which absences are gaps and which are positions.
|
|
@@ -17,15 +17,15 @@ translate between typed events and the ASGI dicts an app expects.
|
|
|
17
17
|
```python
|
|
18
18
|
from without import sleep_forever
|
|
19
19
|
from without_asgi import make_asgi_app
|
|
20
|
-
from without_http import ConnectionPool, serving
|
|
20
|
+
from without_http import ConnectionPool, request, serving
|
|
21
21
|
|
|
22
22
|
app = make_asgi_app(lifespan, http=router.dispatch, websocket=sockets.dispatch)
|
|
23
23
|
|
|
24
24
|
async with serving(app, host="127.0.0.1", port=8000):
|
|
25
|
-
await sleep_forever()
|
|
25
|
+
await sleep_forever() # run until cancelled
|
|
26
26
|
|
|
27
27
|
async with ConnectionPool() as pool:
|
|
28
|
-
async with
|
|
28
|
+
async with request(pool, "GET", "http://127.0.0.1:8000/items") as (head, body):
|
|
29
29
|
assert head.status == 200
|
|
30
30
|
data = await body.read()
|
|
31
31
|
```
|
|
@@ -33,13 +33,21 @@ async with ConnectionPool() as pool:
|
|
|
33
33
|
Because `without-http` speaks plain ASGI to the app, *any* ASGI app runs over it,
|
|
34
34
|
interchangeably with uvicorn. The server handles TLS, HTTP/2 (by ALPN or prior
|
|
35
35
|
knowledge), keep-alive, WebSockets over the HTTP/1.1 upgrade, per-handler
|
|
36
|
-
isolation, and flow control.
|
|
37
|
-
|
|
38
|
-
opt-in trailers, HTTP/2
|
|
39
|
-
request timeouts, consumer-driven
|
|
40
|
-
HTTP/2), and `stack`-composed middleware.
|
|
36
|
+
isolation, and flow control. A client is a function from a request to a response, and
|
|
37
|
+
a `ConnectionPool` is the one that answers over the network: a `(head, body)` response
|
|
38
|
+
split, buffered and streaming bodies in both directions, opt-in trailers, HTTP/2
|
|
39
|
+
multiplexing, per-host connection bounds, per-phase request timeouts, consumer-driven
|
|
40
|
+
duplex (with bidirectional streaming over HTTP/2), and `stack`-composed middleware.
|
|
41
|
+
|
|
42
|
+
`without_http.testing` carries the same interface into a test: a mock client that answers
|
|
43
|
+
from a function, an ASGI client that drives an app in memory, and a loopback client that
|
|
44
|
+
runs the real wire protocols over no socket at all, plus the raw in-memory endpoints
|
|
45
|
+
those are built from, for a test that writes frames rather than requests.
|
|
41
46
|
|
|
42
47
|
See the
|
|
43
48
|
[`without-http` guide](https://without.help/without-http/)
|
|
44
49
|
(with the [API reference](https://without.help/reference/without_http/))
|
|
45
|
-
for the full surface,
|
|
50
|
+
for the full surface, and
|
|
51
|
+
[Alternatives](https://without.help/without-http/alternatives/) for where the
|
|
52
|
+
client and server stand against httpx, aiohttp, niquests, and the ASGI servers,
|
|
53
|
+
including which absences are gaps and which are positions.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["uv_build>=0.
|
|
2
|
+
requires = ["uv_build>=0.12.3,<0.13"]
|
|
3
3
|
build-backend = "uv_build"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "without-http"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.4"
|
|
8
8
|
description = "A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -23,11 +23,13 @@ classifiers = [
|
|
|
23
23
|
"Typing :: Typed",
|
|
24
24
|
]
|
|
25
25
|
dependencies = [
|
|
26
|
-
"without-core==0.0.
|
|
27
|
-
"without-asgi==0.0.
|
|
26
|
+
"without-core==0.0.4",
|
|
27
|
+
"without-asgi==0.0.4",
|
|
28
28
|
"h11>=0.16",
|
|
29
29
|
"h2>=4.1",
|
|
30
30
|
"wsproto>=1.2",
|
|
31
|
+
"aiohappyeyeballs>=2.6",
|
|
32
|
+
"brotli>=1.1",
|
|
31
33
|
]
|
|
32
34
|
|
|
33
35
|
[[project.authors]]
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["uv_build>=0.
|
|
2
|
+
requires = ["uv_build>=0.12.3,<0.13"]
|
|
3
3
|
build-backend = "uv_build"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "without-http"
|
|
7
|
-
version = "0.0.
|
|
7
|
+
version = "0.0.4"
|
|
8
8
|
description = "A sans-IO-backed ASGI server and HTTP client for without: h11/h2/wsproto over asyncio sockets."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -26,11 +26,13 @@ classifiers = [
|
|
|
26
26
|
"Typing :: Typed",
|
|
27
27
|
]
|
|
28
28
|
dependencies = [
|
|
29
|
-
"without-core==0.0.
|
|
30
|
-
"without-asgi==0.0.
|
|
29
|
+
"without-core==0.0.4",
|
|
30
|
+
"without-asgi==0.0.4",
|
|
31
31
|
"h11>=0.16",
|
|
32
32
|
"h2>=4.1",
|
|
33
33
|
"wsproto>=1.2",
|
|
34
|
+
"aiohappyeyeballs>=2.6",
|
|
35
|
+
"brotli>=1.1",
|
|
34
36
|
]
|
|
35
37
|
|
|
36
38
|
[tool.uv.sources]
|
|
@@ -1,17 +1,35 @@
|
|
|
1
|
-
from without_http.client import
|
|
1
|
+
from without_http.client import DEFAULT_DECOMPRESSORS
|
|
2
|
+
from without_http.client import USER_AGENT
|
|
3
|
+
from without_http.client import Client
|
|
2
4
|
from without_http.client import ClientMiddleware
|
|
3
5
|
from without_http.client import ClientRequest
|
|
4
6
|
from without_http.client import ClientResponse
|
|
7
|
+
from without_http.client import Compressor
|
|
8
|
+
from without_http.client import Connect
|
|
5
9
|
from without_http.client import ConnectionPool
|
|
6
10
|
from without_http.client import CookieJar
|
|
11
|
+
from without_http.client import Decompressor
|
|
12
|
+
from without_http.client import Resolve
|
|
7
13
|
from without_http.client import ResponseBody
|
|
8
14
|
from without_http.client import ResponseHead
|
|
9
15
|
from without_http.client import ResponseTrailers
|
|
10
16
|
from without_http.client import add_headers
|
|
17
|
+
from without_http.client import basic_auth
|
|
18
|
+
from without_http.client import bearer_auth
|
|
19
|
+
from without_http.client import brotli_compress
|
|
20
|
+
from without_http.client import compressing
|
|
11
21
|
from without_http.client import cookies
|
|
22
|
+
from without_http.client import deadline
|
|
23
|
+
from without_http.client import decompress
|
|
24
|
+
from without_http.client import default_headers
|
|
12
25
|
from without_http.client import follow_redirects
|
|
26
|
+
from without_http.client import gzip_compress
|
|
27
|
+
from without_http.client import request
|
|
13
28
|
from without_http.client import stack
|
|
29
|
+
from without_http.client import tcp_connect
|
|
30
|
+
from without_http.client import user_agent
|
|
14
31
|
from without_http.client import wrap
|
|
32
|
+
from without_http.client import zstd_compress
|
|
15
33
|
from without_http.h2_wire import early_hint_headers
|
|
16
34
|
from without_http.h2_wire import request_headers
|
|
17
35
|
from without_http.h2_wire import response_headers
|
|
@@ -35,24 +53,33 @@ from without_http.timeouts import ReadTimeout
|
|
|
35
53
|
from without_http.timeouts import Timeout
|
|
36
54
|
from without_http.timeouts import WriteTimeout
|
|
37
55
|
from without_http.tls import ALPN_PROTOCOLS
|
|
56
|
+
from without_http.tls import distinguished_name
|
|
57
|
+
from without_http.tls import extensions_with_tls
|
|
38
58
|
from without_http.tls import server_ssl_context
|
|
59
|
+
from without_http.tls import tls_extension
|
|
39
60
|
from without_http.ws_wire import is_websocket_upgrade
|
|
40
61
|
from without_http.ws_wire import websocket_scope_from_request
|
|
41
62
|
from without_http.ws_wire import ws_events_from_outbound
|
|
42
63
|
|
|
43
64
|
__all__ = [
|
|
44
65
|
"ALPN_PROTOCOLS",
|
|
45
|
-
"
|
|
66
|
+
"DEFAULT_DECOMPRESSORS",
|
|
67
|
+
"USER_AGENT",
|
|
68
|
+
"Client",
|
|
46
69
|
"ClientMiddleware",
|
|
47
70
|
"ClientRequest",
|
|
48
71
|
"ClientResponse",
|
|
72
|
+
"Compressor",
|
|
73
|
+
"Connect",
|
|
49
74
|
"ConnectTimeout",
|
|
50
75
|
"ConnectionPool",
|
|
51
76
|
"CookieJar",
|
|
77
|
+
"Decompressor",
|
|
52
78
|
"HTTPTimeout",
|
|
53
79
|
"LifespanError",
|
|
54
80
|
"PoolTimeout",
|
|
55
81
|
"ReadTimeout",
|
|
82
|
+
"Resolve",
|
|
56
83
|
"ResponseBody",
|
|
57
84
|
"ResponseHead",
|
|
58
85
|
"ResponseTrailers",
|
|
@@ -61,13 +88,24 @@ __all__ = [
|
|
|
61
88
|
"Timeout",
|
|
62
89
|
"WriteTimeout",
|
|
63
90
|
"add_headers",
|
|
91
|
+
"basic_auth",
|
|
92
|
+
"bearer_auth",
|
|
93
|
+
"brotli_compress",
|
|
94
|
+
"compressing",
|
|
64
95
|
"cookies",
|
|
96
|
+
"deadline",
|
|
97
|
+
"decompress",
|
|
98
|
+
"default_headers",
|
|
99
|
+
"distinguished_name",
|
|
65
100
|
"early_hint_headers",
|
|
101
|
+
"extensions_with_tls",
|
|
66
102
|
"follow_redirects",
|
|
103
|
+
"gzip_compress",
|
|
67
104
|
"h11_events_from_outbound",
|
|
68
105
|
"inbound_from_event",
|
|
69
106
|
"is_websocket_upgrade",
|
|
70
107
|
"receive_buffer_size",
|
|
108
|
+
"request",
|
|
71
109
|
"request_headers",
|
|
72
110
|
"response_headers",
|
|
73
111
|
"response_status_and_headers",
|
|
@@ -78,8 +116,12 @@ __all__ = [
|
|
|
78
116
|
"server_ssl_context",
|
|
79
117
|
"serving",
|
|
80
118
|
"stack",
|
|
119
|
+
"tcp_connect",
|
|
81
120
|
"tcp_keepalive",
|
|
121
|
+
"tls_extension",
|
|
122
|
+
"user_agent",
|
|
82
123
|
"websocket_scope_from_request",
|
|
83
124
|
"wrap",
|
|
84
125
|
"ws_events_from_outbound",
|
|
126
|
+
"zstd_compress",
|
|
85
127
|
]
|