http3x 0.1.2__tar.gz → 0.2.0__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.
- {http3x-0.1.2 → http3x-0.2.0}/LICENSE +1 -1
- {http3x-0.1.2 → http3x-0.2.0}/PKG-INFO +35 -3
- {http3x-0.1.2 → http3x-0.2.0}/README.md +33 -1
- http3x-0.2.0/docs/http3.md +396 -0
- {http3x-0.1.2 → http3x-0.2.0}/docs/webtransport.md +478 -489
- {http3x-0.1.2 → http3x-0.2.0}/http3x/_core/base.py +161 -22
- http3x-0.2.0/http3x/_core/http3.py +272 -0
- {http3x-0.1.2 → http3x-0.2.0}/http3x/_core/webtransport.py +160 -70
- http3x-0.2.0/http3x/h3.py +13 -0
- {http3x-0.1.2 → http3x-0.2.0}/http3x/wt.py +4 -1
- {http3x-0.1.2 → http3x-0.2.0}/pyproject.toml +2 -2
- http3x-0.2.0/tests/h3_mini.cmd +2 -0
- http3x-0.2.0/tests/h3_mini.py +15 -0
- {http3x-0.1.2 → http3x-0.2.0}/tests/wt_chat_stream.html +3 -1
- http3x-0.2.0/tests/wt_mini.html +197 -0
- http3x-0.2.0/tests/wt_mini.py +19 -0
- http3x-0.1.2/http3x/_core/http3.py +0 -177
- http3x-0.1.2/http3x/h3.py +0 -0
- {http3x-0.1.2 → http3x-0.2.0}/.github/workflows/jekyll-gh-pages.yml +0 -0
- {http3x-0.1.2 → http3x-0.2.0}/.gitignore +0 -0
- {http3x-0.1.2 → http3x-0.2.0}/http3x/__init__.py +0 -0
- {http3x-0.1.2 → http3x-0.2.0}/http3x/_core/__init__.py +0 -0
- {http3x-0.1.2 → http3x-0.2.0}/tests/wt_chat_stream.png +0 -0
- {http3x-0.1.2 → http3x-0.2.0}/tests/wt_chat_stream.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: http3x
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: A modern async server framework for HTTP/3 and WebTransport over QUIC.
|
|
5
5
|
Keywords: http3,http/3,quic,webtransport,websocket replacement,realtime,streaming,async server,python web framework,datagram,aioquic
|
|
6
|
-
Author-email:
|
|
6
|
+
Author-email: Canbiao Xu <canbiaoxu@outlook.com>
|
|
7
7
|
Requires-Python: >=3.12
|
|
8
8
|
Description-Content-Type: text/markdown
|
|
9
9
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -47,7 +47,7 @@ app.run(host='::', port=4433, certfile="cert.pem", keyfile="key.pem")
|
|
|
47
47
|
pip install http3x
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
## 🚀 Live Example
|
|
50
|
+
## 🚀 WebTransport Live Example
|
|
51
51
|
|
|
52
52
|
Streaming AI-style responses over HTTP/3 (WebTransport):
|
|
53
53
|
|
|
@@ -78,6 +78,37 @@ See [tests/wt_chat_stream.py](https://github.com/canbiaoxu/http3x/blob/main/test
|
|
|
78
78
|
| Datagram | No support | Built-in datagram |
|
|
79
79
|
| Head-of-line blocking | Yes | No |
|
|
80
80
|
|
|
81
|
+
## 🚀 HTTP/3 Live Example
|
|
82
|
+
|
|
83
|
+
Simple HTTP/3 server with GET and POST endpoints:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
from http3x import App
|
|
87
|
+
from http3x.h3 import Handler
|
|
88
|
+
|
|
89
|
+
app = App()
|
|
90
|
+
|
|
91
|
+
class ApiHandler(Handler):
|
|
92
|
+
async def get(self):
|
|
93
|
+
return {'status': 'ok'}
|
|
94
|
+
|
|
95
|
+
async def post(self):
|
|
96
|
+
return {'status': 'ok'}
|
|
97
|
+
|
|
98
|
+
app.h3.add('/h3', ApiHandler)
|
|
99
|
+
|
|
100
|
+
app.run(host='0.0.0.0', port=443, certfile="cert.pem", keyfile="key.pem")
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Using curl with HTTP/3 support:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
curl --http3-only -k https://localhost:443/h3
|
|
107
|
+
curl --http3-only -k -X POST -d "Hello, HTTP/3!" https://localhost:443/h3
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
See [tests/h3_mini.py](https://github.com/canbiaoxu/http3x/blob/main/tests/h3_mini.py) for the complete example.
|
|
111
|
+
|
|
81
112
|
## Features
|
|
82
113
|
|
|
83
114
|
- HTTP/3 server (QUIC-based)
|
|
@@ -89,6 +120,7 @@ See [tests/wt_chat_stream.py](https://github.com/canbiaoxu/http3x/blob/main/test
|
|
|
89
120
|
## Documentation
|
|
90
121
|
|
|
91
122
|
- [WebTransport Guide](https://github.com/canbiaoxu/http3x/blob/main/docs/webtransport.md) - Complete documentation for WebTransport functionality
|
|
123
|
+
- [HTTP/3 Guide](https://github.com/canbiaoxu/http3x/blob/main/docs/http3.md) - Complete documentation for HTTP/3 functionality
|
|
92
124
|
|
|
93
125
|
More docs coming soon.
|
|
94
126
|
|
|
@@ -29,7 +29,7 @@ app.run(host='::', port=4433, certfile="cert.pem", keyfile="key.pem")
|
|
|
29
29
|
pip install http3x
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
## 🚀 Live Example
|
|
32
|
+
## 🚀 WebTransport Live Example
|
|
33
33
|
|
|
34
34
|
Streaming AI-style responses over HTTP/3 (WebTransport):
|
|
35
35
|
|
|
@@ -60,6 +60,37 @@ See [tests/wt_chat_stream.py](https://github.com/canbiaoxu/http3x/blob/main/test
|
|
|
60
60
|
| Datagram | No support | Built-in datagram |
|
|
61
61
|
| Head-of-line blocking | Yes | No |
|
|
62
62
|
|
|
63
|
+
## 🚀 HTTP/3 Live Example
|
|
64
|
+
|
|
65
|
+
Simple HTTP/3 server with GET and POST endpoints:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from http3x import App
|
|
69
|
+
from http3x.h3 import Handler
|
|
70
|
+
|
|
71
|
+
app = App()
|
|
72
|
+
|
|
73
|
+
class ApiHandler(Handler):
|
|
74
|
+
async def get(self):
|
|
75
|
+
return {'status': 'ok'}
|
|
76
|
+
|
|
77
|
+
async def post(self):
|
|
78
|
+
return {'status': 'ok'}
|
|
79
|
+
|
|
80
|
+
app.h3.add('/h3', ApiHandler)
|
|
81
|
+
|
|
82
|
+
app.run(host='0.0.0.0', port=443, certfile="cert.pem", keyfile="key.pem")
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Using curl with HTTP/3 support:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
curl --http3-only -k https://localhost:443/h3
|
|
89
|
+
curl --http3-only -k -X POST -d "Hello, HTTP/3!" https://localhost:443/h3
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
See [tests/h3_mini.py](https://github.com/canbiaoxu/http3x/blob/main/tests/h3_mini.py) for the complete example.
|
|
93
|
+
|
|
63
94
|
## Features
|
|
64
95
|
|
|
65
96
|
- HTTP/3 server (QUIC-based)
|
|
@@ -71,6 +102,7 @@ See [tests/wt_chat_stream.py](https://github.com/canbiaoxu/http3x/blob/main/test
|
|
|
71
102
|
## Documentation
|
|
72
103
|
|
|
73
104
|
- [WebTransport Guide](https://github.com/canbiaoxu/http3x/blob/main/docs/webtransport.md) - Complete documentation for WebTransport functionality
|
|
105
|
+
- [HTTP/3 Guide](https://github.com/canbiaoxu/http3x/blob/main/docs/http3.md) - Complete documentation for HTTP/3 functionality
|
|
74
106
|
|
|
75
107
|
More docs coming soon.
|
|
76
108
|
|
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
# HTTP/3
|
|
2
|
+
|
|
3
|
+
HTTP/3 is the third major version of the Hypertext Transfer Protocol, built on top of QUIC. It provides faster connection establishment, improved performance over lossy networks, and multiplexed streams without head-of-line blocking.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
HTTP3X provides a simple and intuitive API for building HTTP/3 servers. The framework handles the underlying QUIC protocol, allowing you to focus on your application logic.
|
|
8
|
+
|
|
9
|
+
### Key Features
|
|
10
|
+
|
|
11
|
+
- **HTTP/3 Server**: Built on QUIC for improved performance
|
|
12
|
+
- **Async/Await Support**: Native Python async/await syntax for handling requests
|
|
13
|
+
- **Route-based Handlers**: Organize your HTTP/3 endpoints with route patterns
|
|
14
|
+
- **Easy Integration**: Simple API that integrates with the HTTP3X application
|
|
15
|
+
- **Streaming Support**: Efficiently handle large requests and responses
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install http3x
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### Server-Side
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from http3x import App
|
|
29
|
+
from http3x.h3 import Handler
|
|
30
|
+
|
|
31
|
+
app = App()
|
|
32
|
+
|
|
33
|
+
class ApiHandler(Handler):
|
|
34
|
+
async def get(self):
|
|
35
|
+
return {'status': 'ok'}
|
|
36
|
+
|
|
37
|
+
async def post(self):
|
|
38
|
+
return {'status': 'ok'}
|
|
39
|
+
|
|
40
|
+
app.h3.add('/h3', ApiHandler)
|
|
41
|
+
|
|
42
|
+
app.run(host='0.0.0.0', port=443, certfile="cert.pem", keyfile="key.pem")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Client-Side
|
|
46
|
+
|
|
47
|
+
Using curl with HTTP/3 support:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
curl --http3-only -k https://localhost:443/h3
|
|
51
|
+
curl --http3-only -k -X POST -d "Hello, HTTP/3!" https://localhost:443/h3
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Handler Class
|
|
55
|
+
|
|
56
|
+
The `Handler` class (alias for `HTTP3Handler`) is the main class for handling HTTP/3 requests. You create a subclass and override its methods to handle GET and POST requests.
|
|
57
|
+
|
|
58
|
+
### Handler Properties
|
|
59
|
+
|
|
60
|
+
| Property | Type | Description |
|
|
61
|
+
|----------|------|-------------|
|
|
62
|
+
| `session_id` | `int` | The unique identifier for this request stream |
|
|
63
|
+
| `connection` | `QuicConnection` | The underlying QUIC connection |
|
|
64
|
+
| `request` | `HTTP3Request` | The request object containing request information |
|
|
65
|
+
| `request.address` | `tuple[str, int]` | The client address (host, port) |
|
|
66
|
+
| `request.headers` | `list[tuple[bytes, bytes]]` | The request headers |
|
|
67
|
+
| `request.raw_path` | `str` | The full request path including query parameters |
|
|
68
|
+
| `request.path` | `str` | The path without query parameters |
|
|
69
|
+
| `request.path_params` | `tuple[str]` | Captured path parameters from route pattern |
|
|
70
|
+
| `closed` | `bool` | Whether the handler is closed |
|
|
71
|
+
|
|
72
|
+
### Handler Methods to Override
|
|
73
|
+
|
|
74
|
+
#### `get()`
|
|
75
|
+
|
|
76
|
+
Called to handle GET requests. Override this method to implement custom GET request handling.
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
class MyHandler(Handler):
|
|
80
|
+
async def get(self):
|
|
81
|
+
await self.write("Hello, World!")
|
|
82
|
+
return "Done"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Returns**: Optional data to send as the response body.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
#### `post()`
|
|
90
|
+
|
|
91
|
+
Called to handle POST requests. Override this method to implement custom POST request handling.
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
class MyHandler(Handler):
|
|
95
|
+
async def post(self):
|
|
96
|
+
body = await self.request.read()
|
|
97
|
+
return {"received": body.decode()}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Returns**: Optional data to send as the response body.
|
|
101
|
+
|
|
102
|
+
### Handler Methods to Call
|
|
103
|
+
|
|
104
|
+
#### `write(chunk, flush=True)`
|
|
105
|
+
|
|
106
|
+
Write data to the response. This method sends response headers if not already sent, then sends the data chunk.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
await self.write("Hello!")
|
|
110
|
+
await self.write({"status": "ok"}) # JSON serialization
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
| Parameter | Type | Default | Description |
|
|
114
|
+
|-----------|------|---------|-------------|
|
|
115
|
+
| `chunk` | `bytes str Jsonable` | required | The data to write |
|
|
116
|
+
| `flush` | `bool` | `True` | Whether to flush the connection immediately |
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
#### `finish(chunk=None)`
|
|
121
|
+
|
|
122
|
+
Finish the response. This method optionally writes a final chunk and then ends the stream.
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
await self.finish("Goodbye!")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
| Parameter | Type | Default | Description |
|
|
129
|
+
|-----------|------|---------|-------------|
|
|
130
|
+
| `chunk` | `bytes str Jsonable` | `None` | Optional final data to write |
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
#### `flush()`
|
|
135
|
+
|
|
136
|
+
Flush any pending data to the connection.
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
await self.flush()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
#### `wait_closed()`
|
|
145
|
+
|
|
146
|
+
Wait until the handler is closed.
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
await self.wait_closed()
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Request Class
|
|
153
|
+
|
|
154
|
+
The `Request` class (alias for `HTTP3Request`) represents an HTTP/3 request and provides access to request information.
|
|
155
|
+
|
|
156
|
+
### Request Properties
|
|
157
|
+
|
|
158
|
+
| Property | Type | Description |
|
|
159
|
+
|----------|------|-------------|
|
|
160
|
+
| `handler` | `HTTP3Handler` | The handler handling this request |
|
|
161
|
+
| `address` | `tuple[str, int]` | The client address (host, port) |
|
|
162
|
+
| `headers` | `list[tuple[bytes, bytes]]` | The request headers |
|
|
163
|
+
| `raw_path` | `str` | The full request path including query parameters |
|
|
164
|
+
| `path` | `str` | The path without query parameters |
|
|
165
|
+
| `path_params` | `tuple[str]` | Captured path parameters from route pattern |
|
|
166
|
+
|
|
167
|
+
### Request Methods
|
|
168
|
+
|
|
169
|
+
#### `body()`
|
|
170
|
+
|
|
171
|
+
Asynchronously iterate over the request body chunks.
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
async for chunk in self.request.body():
|
|
175
|
+
process_chunk(chunk)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Yields**: `bytes` - Each chunk of the request body.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
#### `read()`
|
|
183
|
+
|
|
184
|
+
Read the entire request body.
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
body = await self.request.read()
|
|
188
|
+
print(body.decode())
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**Returns**: `bytes` - The complete request body.
|
|
192
|
+
|
|
193
|
+
## Routing
|
|
194
|
+
|
|
195
|
+
HTTP/3 requests are routed using path patterns. The framework supports regex-based route matching.
|
|
196
|
+
|
|
197
|
+
### Basic Routing
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
app.h3.add('/api', ApiHandler)
|
|
201
|
+
app.h3.add('/docs', DocsHandler)
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Path Parameters
|
|
205
|
+
|
|
206
|
+
Use regex capture groups to extract path parameters:
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
class UserHandler(Handler):
|
|
210
|
+
async def get(self):
|
|
211
|
+
user_id = self.request.path_params[0]
|
|
212
|
+
return {"user_id": user_id}
|
|
213
|
+
|
|
214
|
+
app.h3.add(r'/user/(\d+)', UserHandler)
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
The captured groups are available in `self.request.path_params` as a tuple.
|
|
218
|
+
|
|
219
|
+
## Running the Server
|
|
220
|
+
|
|
221
|
+
### Synchronous
|
|
222
|
+
|
|
223
|
+
```python
|
|
224
|
+
app.run(
|
|
225
|
+
host='0.0.0.0',
|
|
226
|
+
port=443,
|
|
227
|
+
certfile="cert.pem",
|
|
228
|
+
keyfile="key.pem"
|
|
229
|
+
)
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Asynchronous
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
async def main():
|
|
236
|
+
await app.async_run(
|
|
237
|
+
host='0.0.0.0',
|
|
238
|
+
port=443,
|
|
239
|
+
certfile="cert.pem",
|
|
240
|
+
keyfile="key.pem"
|
|
241
|
+
)
|
|
242
|
+
await asyncio.Event().wait()
|
|
243
|
+
|
|
244
|
+
asyncio.run(main())
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Parameters
|
|
248
|
+
|
|
249
|
+
| Parameter | Type | Default | Description |
|
|
250
|
+
|-----------|------|---------|-------------|
|
|
251
|
+
| `host` | `str` | required | The host to bind to (`'0.0.0.0'` for all interfaces) |
|
|
252
|
+
| `port` | `int` | required | The port to listen on |
|
|
253
|
+
| `certfile` | `str \| Path` | required | Path to the SSL certificate file |
|
|
254
|
+
| `keyfile` | `str \| Path` | required | Path to the SSL private key file |
|
|
255
|
+
| `retry` | `bool` | `False` | Enable QUIC retry mechanism |
|
|
256
|
+
| `configuration` | `AppConfiguration \| None` | `None` | Custom QUIC configuration |
|
|
257
|
+
|
|
258
|
+
## SSL Certificates
|
|
259
|
+
|
|
260
|
+
HTTP/3 requires HTTPS. You can generate a self-signed certificate for development using mkcert:
|
|
261
|
+
|
|
262
|
+
```bash
|
|
263
|
+
mkcert -cert-file cert.pem -key-file key.pem localhost 127.0.0.1 ::1
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
For production, use a certificate from a trusted Certificate Authority.
|
|
267
|
+
|
|
268
|
+
## Complete Example
|
|
269
|
+
|
|
270
|
+
### Server (Python)
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
from http3x import App
|
|
274
|
+
from http3x.h3 import Handler
|
|
275
|
+
|
|
276
|
+
app = App()
|
|
277
|
+
|
|
278
|
+
class ApiHandler(Handler):
|
|
279
|
+
async def get(self):
|
|
280
|
+
return {
|
|
281
|
+
"message": "Hello, HTTP/3!",
|
|
282
|
+
"method": "GET"
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async def post(self):
|
|
286
|
+
body = await self.request.read()
|
|
287
|
+
return {
|
|
288
|
+
"message": "Received POST data",
|
|
289
|
+
"data": body.decode()
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
app.h3.add('/api', ApiHandler)
|
|
293
|
+
|
|
294
|
+
class UserHandler(Handler):
|
|
295
|
+
async def get(self):
|
|
296
|
+
user_id = self.request.path_params[0]
|
|
297
|
+
return {
|
|
298
|
+
"user_id": user_id,
|
|
299
|
+
"name": f"User {user_id}"
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
app.h3.add(r'/user/(\d+)', UserHandler)
|
|
303
|
+
|
|
304
|
+
app.run(host='0.0.0.0', port=443, certfile="cert.pem", keyfile="key.pem")
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### Client (curl)
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
# Test GET request
|
|
311
|
+
curl --http3-only -k https://localhost:443/api
|
|
312
|
+
|
|
313
|
+
# Test POST request
|
|
314
|
+
curl --http3-only -k -X POST -d "Hello, HTTP/3!" https://localhost:443/api
|
|
315
|
+
|
|
316
|
+
# Test path parameters
|
|
317
|
+
curl --http3-only -k https://localhost:443/user/123
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Error Handling
|
|
321
|
+
|
|
322
|
+
The framework handles errors gracefully. Requests are automatically cleaned up when:
|
|
323
|
+
|
|
324
|
+
- The client disconnects
|
|
325
|
+
- The connection times out
|
|
326
|
+
- An unhandled exception occurs
|
|
327
|
+
|
|
328
|
+
You can add error handling in your handler methods:
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
class MyHandler(Handler):
|
|
332
|
+
async def get(self):
|
|
333
|
+
try:
|
|
334
|
+
# Your logic here
|
|
335
|
+
return {"status": "ok"}
|
|
336
|
+
except Exception as e:
|
|
337
|
+
# Handle error
|
|
338
|
+
await self.write({"error": str(e)})
|
|
339
|
+
return
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Performance Tips
|
|
343
|
+
|
|
344
|
+
1. **Use Streaming for Large Data**: For large request or response bodies, use the streaming API to avoid loading everything into memory.
|
|
345
|
+
|
|
346
|
+
2. **Batch Operations**: Set `flush=False` when sending multiple messages, then call `flush()` once:
|
|
347
|
+
|
|
348
|
+
```python
|
|
349
|
+
await self.write(b'part1', flush=False)
|
|
350
|
+
await self.write(b'part2', flush=False)
|
|
351
|
+
await self.write(b'part3', flush=True)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
3. **Handle Backpressure**: The async API naturally handles backpressure. Don't buffer more data than necessary.
|
|
355
|
+
|
|
356
|
+
## API Reference
|
|
357
|
+
|
|
358
|
+
### Imports
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
from http3x import App, AppConfiguration
|
|
362
|
+
from http3x.h3 import Handler, Request
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### App
|
|
366
|
+
|
|
367
|
+
Main application class for HTTP3X.
|
|
368
|
+
|
|
369
|
+
| Method | Description |
|
|
370
|
+
|--------|-------------|
|
|
371
|
+
| `h3.add(pattern, handler)` | Register an HTTP/3 request handler |
|
|
372
|
+
| `run(...)` | Run the server synchronously |
|
|
373
|
+
| `async_run(...)` | Run the server asynchronously |
|
|
374
|
+
| `close()` | Close the server |
|
|
375
|
+
|
|
376
|
+
### Handler
|
|
377
|
+
|
|
378
|
+
Base class for HTTP/3 request handlers.
|
|
379
|
+
|
|
380
|
+
| Method | Description |
|
|
381
|
+
|--------|-------------|
|
|
382
|
+
| `get()` | Handle GET requests |
|
|
383
|
+
| `post()` | Handle POST requests |
|
|
384
|
+
| `write(data)` | Write data to the response |
|
|
385
|
+
| `finish(data)` | Finish the response |
|
|
386
|
+
| `flush()` | Flush pending data |
|
|
387
|
+
| `wait_closed()` | Wait for handler to close |
|
|
388
|
+
|
|
389
|
+
### Request
|
|
390
|
+
|
|
391
|
+
Represents an HTTP/3 request.
|
|
392
|
+
|
|
393
|
+
| Method | Description |
|
|
394
|
+
|--------|-------------|
|
|
395
|
+
| `body()` | Asynchronously iterate over request body chunks |
|
|
396
|
+
| `read()` | Read the entire request body |
|