0
# HTTP Events
1
2
Event classes representing different parts of HTTP messages including requests, responses, data, and connection lifecycle. All events inherit from the base Event class and are implemented as frozen dataclasses for immutability.
3
4
## Capabilities
5
6
### Base Event Class
7
8
Abstract base class for all h11 events.
9
10
```python { .api }
11
class Event:
12
"""
13
Base class for h11 events.
14
15
Note:
16
Do not subclass or instantiate directly. Use concrete event types.
17
"""
18
```
19
20
### Request Events
21
22
Events representing HTTP requests from clients to servers.
23
24
```python { .api }
25
class Request(Event):
26
"""
27
The beginning of an HTTP request.
28
29
Attributes:
30
method (bytes): HTTP method (e.g., b"GET", b"POST")
31
target (bytes): Request target (e.g., b"/index.html")
32
headers (Headers): List of (name, value) header pairs
33
http_version (bytes): HTTP version (e.g., b"1.1")
34
"""
35
def __init__(
36
self,
37
*,
38
method,
39
target,
40
headers,
41
http_version=b"1.1"
42
):
43
"""
44
Create a new HTTP request event.
45
46
Args:
47
method (Union[bytes, str]): HTTP method
48
target (Union[bytes, str]): Request target/path
49
headers (Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]]): Request headers
50
http_version (Union[bytes, str]): HTTP version (default: b"1.1")
51
"""
52
```
53
54
**Usage Example:**
55
```python
56
# GET request
57
req = h11.Request(
58
method=b'GET',
59
target=b'/api/users',
60
headers=[
61
(b'host', b'api.example.com'),
62
(b'user-agent', b'my-client/1.0'),
63
(b'accept', b'application/json')
64
]
65
)
66
67
# POST request with body
68
req = h11.Request(
69
method=b'POST',
70
target=b'/api/users',
71
headers=[
72
(b'host', b'api.example.com'),
73
(b'content-type', b'application/json'),
74
(b'content-length', b'25')
75
]
76
)
77
```
78
79
### Response Events
80
81
Events representing HTTP responses from servers to clients.
82
83
```python { .api }
84
class InformationalResponse(Event):
85
"""
86
HTTP informational response (status codes 100-199).
87
88
Attributes:
89
status_code (int): Status code (100-199)
90
headers (Headers): Response headers
91
http_version (bytes): HTTP version
92
reason (bytes): Reason phrase
93
"""
94
def __init__(
95
self,
96
*,
97
status_code,
98
headers=None,
99
http_version=b"1.1",
100
reason=b""
101
):
102
"""
103
Create informational response event.
104
105
Args:
106
status_code (int): Status code (100-199)
107
headers (Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]]): Headers (default: empty)
108
http_version (Union[bytes, str]): HTTP version (default: b"1.1")
109
reason (Union[bytes, str]): Reason phrase (default: auto-generated)
110
"""
111
112
class Response(Event):
113
"""
114
Beginning of HTTP response (status codes 200-999).
115
116
Attributes:
117
status_code (int): Status code (200-999)
118
headers (Headers): Response headers
119
http_version (bytes): HTTP version
120
reason (bytes): Reason phrase
121
"""
122
def __init__(
123
self,
124
*,
125
status_code,
126
headers=None,
127
http_version=b"1.1",
128
reason=b""
129
):
130
"""
131
Create response event.
132
133
Args:
134
status_code (int): Status code (200-999)
135
headers (Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]]): Headers (default: empty)
136
http_version (Union[bytes, str]): HTTP version (default: b"1.1")
137
reason (Union[bytes, str]): Reason phrase (default: auto-generated)
138
"""
139
```
140
141
**Usage Examples:**
142
```python
143
# 100 Continue response
144
info_resp = h11.InformationalResponse(status_code=100)
145
146
# 200 OK response
147
resp = h11.Response(
148
status_code=200,
149
headers=[
150
(b'content-type', b'application/json'),
151
(b'content-length', b'42'),
152
(b'cache-control', b'no-cache')
153
]
154
)
155
156
# 404 Not Found response
157
resp = h11.Response(
158
status_code=404,
159
headers=[(b'content-type', b'text/plain')],
160
reason=b'Not Found'
161
)
162
```
163
164
### Message Body Events
165
166
Events representing HTTP message body data and message completion.
167
168
```python { .api }
169
class Data(Event):
170
"""
171
Part of an HTTP message body.
172
173
Attributes:
174
data (bytes): Message body data chunk
175
chunk_start (bool): Start of chunked encoding chunk
176
chunk_end (bool): End of chunked encoding chunk
177
"""
178
def __init__(self, *, data, chunk_start=False, chunk_end=False):
179
"""
180
Create data event.
181
182
Args:
183
data (Union[bytes, bytearray, memoryview]): Body data
184
chunk_start (bool): Mark start of chunk (default: False)
185
chunk_end (bool): Mark end of chunk (default: False)
186
"""
187
188
class EndOfMessage(Event):
189
"""
190
End of an HTTP message.
191
192
Attributes:
193
headers (Headers): Trailing headers (default: empty)
194
"""
195
def __init__(self, *, headers=None):
196
"""
197
Create end-of-message event.
198
199
Args:
200
headers (Union[Headers, List[Tuple[bytes, bytes]], List[Tuple[str, str]]]):
201
Trailing headers (default: empty list)
202
"""
203
```
204
205
**Usage Examples:**
206
```python
207
# Send body data
208
data_event = h11.Data(data=b'{"user": "john", "age": 30}')
209
210
# Send chunked data
211
chunk_start = h11.Data(data=b'Hello', chunk_start=True)
212
chunk_data = h11.Data(data=b' World')
213
chunk_end = h11.Data(data=b'!', chunk_end=True)
214
215
# End message (no trailing headers)
216
eom = h11.EndOfMessage()
217
218
# End message with trailing headers
219
eom = h11.EndOfMessage(headers=[
220
(b'x-checksum', b'abc123'),
221
(b'x-timestamp', b'1609459200')
222
])
223
```
224
225
### Connection Lifecycle Events
226
227
Events representing connection state changes.
228
229
```python { .api }
230
class ConnectionClosed(Event):
231
"""
232
Indicates the sender has closed their outgoing connection.
233
234
Note:
235
This event has no attributes and represents a clean connection closure.
236
Receiving this event means no more data will be sent by the peer.
237
"""
238
def __init__(self):
239
"""Create connection closed event."""
240
```
241
242
**Usage Example:**
243
```python
244
# Indicate connection is closing
245
closed_event = h11.ConnectionClosed()
246
247
# Handle in event loop
248
event = conn.next_event()
249
if isinstance(event, h11.ConnectionClosed):
250
print("Peer closed connection")
251
# Clean up resources
252
```
253
254
## Event Processing Patterns
255
256
### Client Request Pattern
257
258
```python
259
import h11
260
261
conn = h11.Connection(h11.CLIENT)
262
263
# 1. Send request headers
264
request = h11.Request(
265
method=b'POST',
266
target=b'/upload',
267
headers=[
268
(b'host', b'example.com'),
269
(b'content-type', b'application/json'),
270
(b'transfer-encoding', b'chunked')
271
]
272
)
273
data = conn.send(request)
274
send_to_socket(data)
275
276
# 2. Send body data
277
body_chunk = h11.Data(data=b'{"key": "value"}')
278
data = conn.send(body_chunk)
279
send_to_socket(data)
280
281
# 3. End message
282
eom = h11.EndOfMessage()
283
data = conn.send(eom)
284
send_to_socket(data)
285
```
286
287
### Server Response Pattern
288
289
```python
290
import h11
291
292
conn = h11.Connection(h11.SERVER)
293
294
# 1. Send response headers
295
response = h11.Response(
296
status_code=200,
297
headers=[
298
(b'content-type', b'text/html'),
299
(b'content-length', b'13')
300
]
301
)
302
data = conn.send(response)
303
send_to_socket(data)
304
305
# 2. Send body
306
body = h11.Data(data=b'Hello, World!')
307
data = conn.send(body)
308
send_to_socket(data)
309
310
# 3. End message
311
eom = h11.EndOfMessage()
312
data = conn.send(eom)
313
send_to_socket(data)
314
```
315
316
### Event Processing Loop
317
318
```python
319
while True:
320
# Get more data from socket
321
raw_data = receive_from_socket()
322
if not raw_data:
323
break
324
325
# Feed to connection
326
conn.receive_data(raw_data)
327
328
# Process all available events
329
while True:
330
event = conn.next_event()
331
332
if event is h11.NEED_DATA:
333
break # Need more data from socket
334
elif event is h11.PAUSED:
335
conn.start_next_cycle()
336
break
337
elif isinstance(event, h11.Request):
338
print(f"Request: {event.method} {event.target}")
339
elif isinstance(event, h11.Response):
340
print(f"Response: {event.status_code}")
341
elif isinstance(event, h11.Data):
342
print(f"Body data: {len(event.data)} bytes")
343
elif isinstance(event, h11.EndOfMessage):
344
print("Message complete")
345
elif isinstance(event, h11.ConnectionClosed):
346
print("Connection closed")
347
return
348
```