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.
@@ -1,4 +1,4 @@
1
- Copyright (c) 2026 Canbiao Xu (许灿标) and contributors
1
+ Copyright (c) 2026 Canbiao Xu and contributors
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License");
4
4
  you may not use this file except in compliance with the License.
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: http3x
3
- Version: 0.1.2
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: 许灿标 <canbiaoxu@outlook.com>
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 |