or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdconnection.mdevents.mdexceptions.mdindex.mdsettings.md

events.mddocs/

0

# Event System

1

2

Structured events representing HTTP/2 protocol actions and state changes. All H2Connection operations generate events that applications process to handle requests, responses, data transmission, and protocol state changes.

3

4

## Capabilities

5

6

### Base Event Class

7

8

All events inherit from the base Event class.

9

10

```python { .api }

11

class Event:

12

"""Base class for all h2 events."""

13

```

14

15

### Request/Response Events

16

17

Events related to HTTP request and response processing.

18

19

#### RequestReceived

20

21

Event generated when a complete request is received (headers with possible END_STREAM).

22

23

```python { .api }

24

class RequestReceived(Event):

25

"""

26

Request received from remote peer.

27

28

Attributes:

29

stream_id: Stream ID for the request

30

headers: List of header objects

31

stream_ended: Associated StreamEnded event if END_STREAM flag set

32

priority_updated: Associated PriorityUpdated event if priority info present

33

"""

34

stream_id: int

35

headers: list[Header]

36

stream_ended: StreamEnded | None

37

priority_updated: PriorityUpdated | None

38

```

39

40

#### ResponseReceived

41

42

Event generated when a complete response is received (headers with possible END_STREAM).

43

44

```python { .api }

45

class ResponseReceived(Event):

46

"""

47

Response received from remote peer.

48

49

Attributes:

50

stream_id: Stream ID for the response

51

headers: List of header objects

52

stream_ended: Associated StreamEnded event if END_STREAM flag set

53

priority_updated: Associated PriorityUpdated event if priority info present

54

"""

55

stream_id: int

56

headers: list[Header]

57

stream_ended: StreamEnded | None

58

priority_updated: PriorityUpdated | None

59

```

60

61

#### TrailersReceived

62

63

Event generated when HTTP trailers are received (always includes END_STREAM).

64

65

```python { .api }

66

class TrailersReceived(Event):

67

"""

68

Trailers received from remote peer.

69

70

Attributes:

71

stream_id: Stream ID for the trailers

72

headers: List of header objects

73

stream_ended: Associated StreamEnded event (always present for trailers)

74

priority_updated: Associated PriorityUpdated event if priority info present

75

"""

76

stream_id: int

77

headers: list[Header]

78

stream_ended: StreamEnded | None

79

priority_updated: PriorityUpdated | None

80

```

81

82

#### InformationalResponseReceived

83

84

Event generated when 1xx informational response is received.

85

86

```python { .api }

87

class InformationalResponseReceived(Event):

88

"""

89

Informational response (1xx) received from remote peer.

90

91

Attributes:

92

stream_id: Stream ID for the informational response

93

headers: List of header objects

94

priority_updated: Associated PriorityUpdated event if priority info present

95

"""

96

stream_id: int

97

headers: list[Header]

98

priority_updated: PriorityUpdated | None

99

```

100

101

### Data Events

102

103

Events related to data transmission and reception.

104

105

#### DataReceived

106

107

Event generated when data is received on a stream.

108

109

```python { .api }

110

class DataReceived(Event):

111

"""

112

Data received from remote peer.

113

114

Attributes:

115

stream_id: Stream ID the data was received on

116

data: Raw data bytes received

117

flow_controlled_length: Number of flow-controlled bytes (may differ from len(data) due to padding)

118

stream_ended: Associated StreamEnded event if END_STREAM flag set

119

"""

120

stream_id: int

121

data: bytes

122

flow_controlled_length: int

123

stream_ended: StreamEnded | None

124

```

125

126

### Flow Control Events

127

128

Events related to HTTP/2 flow control window management.

129

130

#### WindowUpdated

131

132

Event generated when a flow control window changes size.

133

134

```python { .api }

135

class WindowUpdated(Event):

136

"""

137

Flow control window updated.

138

139

Attributes:

140

stream_id: Stream ID whose window was updated (0 for connection window)

141

delta: Number of bytes the window was increased by

142

"""

143

stream_id: int

144

delta: int

145

```

146

147

### Stream Lifecycle Events

148

149

Events related to stream creation, termination, and management.

150

151

#### StreamEnded

152

153

Event generated when a stream is ended by a remote party.

154

155

```python { .api }

156

class StreamEnded(Event):

157

"""

158

Stream ended by remote peer.

159

160

Attributes:

161

stream_id: Stream ID that was ended

162

"""

163

stream_id: int

164

```

165

166

#### StreamReset

167

168

Event generated when a stream is reset by either party.

169

170

```python { .api }

171

class StreamReset(Event):

172

"""

173

Stream reset by local or remote peer.

174

175

Attributes:

176

stream_id: Stream ID that was reset

177

error_code: HTTP/2 error code for reset reason

178

remote_reset: True if reset by remote peer, False if reset locally

179

"""

180

stream_id: int

181

error_code: ErrorCodes | int

182

remote_reset: bool

183

```

184

185

#### PushedStreamReceived

186

187

Event generated when a pushed stream is received from a server (client-side only).

188

189

```python { .api }

190

class PushedStreamReceived(Event):

191

"""

192

Pushed stream received from server.

193

194

Attributes:

195

pushed_stream_id: Stream ID for the pushed response

196

parent_stream_id: Stream ID that initiated the push

197

headers: List of header objects for the pushed request

198

"""

199

pushed_stream_id: int

200

parent_stream_id: int

201

headers: list[Header]

202

```

203

204

### Connection Control Events

205

206

Events related to connection-level control operations.

207

208

#### PingReceived

209

210

Event generated when a PING frame is received.

211

212

```python { .api }

213

class PingReceived(Event):

214

"""

215

PING frame received from remote peer.

216

217

A ping acknowledgment with the same opaque data is automatically emitted

218

after receiving a ping.

219

220

Attributes:

221

ping_data: 8 bytes of opaque data from the PING frame

222

223

.. versionadded:: 3.1.0

224

"""

225

ping_data: bytes

226

```

227

228

#### PingAckReceived

229

230

Event generated when a PING acknowledgment is received.

231

232

```python { .api }

233

class PingAckReceived(Event):

234

"""

235

PING acknowledgment received from remote peer.

236

237

Contains the opaque data of the PING+ACK frame, allowing correlation

238

of PINGs and calculation of RTT.

239

240

Attributes:

241

ping_data: 8 bytes of opaque data from the PING+ACK frame

242

243

.. versionadded:: 3.1.0

244

.. versionchanged:: 4.0.0

245

Removed deprecated but equivalent PingAcknowledged

246

"""

247

ping_data: bytes

248

```

249

250

#### ConnectionTerminated

251

252

Event generated when a connection is terminated.

253

254

```python { .api }

255

class ConnectionTerminated(Event):

256

"""

257

Connection terminated by local or remote peer.

258

259

Attributes:

260

error_code: HTTP/2 error code for termination reason

261

last_stream_id: Last stream ID processed before termination

262

additional_data: Additional debug information

263

"""

264

error_code: ErrorCodes | int | None

265

last_stream_id: int | None

266

additional_data: bytes | None

267

```

268

269

### Settings Events

270

271

Events related to HTTP/2 settings negotiation and acknowledgment.

272

273

#### RemoteSettingsChanged

274

275

Event generated when remote peer changes its settings.

276

277

```python { .api }

278

class RemoteSettingsChanged(Event):

279

"""

280

Remote peer settings changed.

281

282

Attributes:

283

changed_settings: Dictionary of setting codes to ChangedSetting objects

284

"""

285

changed_settings: dict[int, ChangedSetting]

286

287

@classmethod

288

def from_settings(

289

cls,

290

old_settings: Settings | dict[int, int],

291

new_settings: dict[int, int]

292

) -> RemoteSettingsChanged:

293

"""

294

Create event from old and new settings.

295

296

Args:

297

old_settings: Previous settings state

298

new_settings: New settings state

299

300

Returns:

301

RemoteSettingsChanged event with populated changed_settings

302

"""

303

```

304

305

#### SettingsAcknowledged

306

307

Event generated when a settings acknowledgment is received.

308

309

```python { .api }

310

class SettingsAcknowledged(Event):

311

"""

312

Settings acknowledged by remote peer.

313

314

Attributes:

315

changed_settings: Dictionary of setting codes to ChangedSetting objects

316

"""

317

changed_settings: dict[SettingCodes | int, ChangedSetting]

318

```

319

320

### Priority Events

321

322

Events related to stream priority and dependency management.

323

324

#### PriorityUpdated

325

326

Event generated when stream priority information is updated.

327

328

```python { .api }

329

class PriorityUpdated(Event):

330

"""

331

Stream priority updated.

332

333

Attributes:

334

stream_id: Stream ID whose priority was updated

335

weight: New stream weight (1-256)

336

depends_on: Stream ID this stream depends on

337

exclusive: Whether dependency is exclusive

338

"""

339

stream_id: int | None

340

weight: int | None

341

depends_on: int | None

342

exclusive: bool | None

343

```

344

345

### Extension Events

346

347

Events related to HTTP/2 extensions and unknown frames.

348

349

#### AlternativeServiceAvailable

350

351

Event generated when alternative service is advertised.

352

353

```python { .api }

354

class AlternativeServiceAvailable(Event):

355

"""

356

Alternative service advertised by remote peer.

357

358

Attributes:

359

origin: Origin for which alternative service is available

360

field_value: Alt-Svc field value as defined in RFC 7838

361

"""

362

origin: bytes | None

363

field_value: bytes | None

364

```

365

366

#### UnknownFrameReceived

367

368

Event generated when an unknown or unsupported frame is received.

369

370

```python { .api }

371

class UnknownFrameReceived(Event):

372

"""

373

Unknown frame received from remote peer.

374

375

This occurs primarily when the remote peer is employing HTTP/2 extensions

376

that h2 doesn't know anything about.

377

378

Attributes:

379

frame: The unknown frame object

380

381

.. versionadded:: 2.7.0

382

"""

383

frame: Frame

384

```

385

386

## Header Type

387

388

For events that include headers, the `Header` type represents HTTP/2 headers:

389

390

```python { .api }

391

from typing import Union

392

from hpack.struct import Header

393

394

# Header is a union type that can be:

395

Header = Union[

396

tuple[bytes, bytes], # (name, value) as bytes

397

tuple[str, str], # (name, value) as strings

398

tuple[bytes, str], # Mixed types

399

tuple[str, bytes] # Mixed types

400

]

401

```

402

403

## Event Processing Patterns

404

405

### Basic Event Handling

406

407

Simple event processing loop for handling HTTP/2 events:

408

409

```python

410

from h2.connection import H2Connection

411

from h2.events import (

412

RequestReceived, ResponseReceived, DataReceived,

413

StreamEnded, ConnectionTerminated

414

)

415

416

def process_events(conn: H2Connection, data: bytes):

417

events = conn.receive_data(data)

418

419

for event in events:

420

if isinstance(event, RequestReceived):

421

print(f"Request on stream {event.stream_id}")

422

for name, value in event.headers:

423

print(f" {name}: {value}")

424

425

elif isinstance(event, DataReceived):

426

print(f"Data on stream {event.stream_id}: {len(event.data)} bytes")

427

# Acknowledge received data for flow control

428

conn.acknowledge_received_data(

429

acknowledged_size=event.flow_controlled_length,

430

stream_id=event.stream_id

431

)

432

433

elif isinstance(event, StreamEnded):

434

print(f"Stream {event.stream_id} ended")

435

436

elif isinstance(event, ConnectionTerminated):

437

print(f"Connection terminated: {event.error_code}")

438

break

439

440

# Send any response data

441

data_to_send = conn.data_to_send()

442

if data_to_send:

443

# Send data_to_send over your socket

444

pass

445

```

446

447

### Advanced Event Handling

448

449

More sophisticated event handling with error handling and stream management:

450

451

```python

452

from h2.connection import H2Connection

453

from h2.events import *

454

from h2.exceptions import ProtocolError

455

456

class HTTP2EventHandler:

457

def __init__(self, conn: H2Connection):

458

self.conn = conn

459

self.streams = {} # Track active streams

460

461

def handle_events(self, data: bytes):

462

try:

463

events = self.conn.receive_data(data)

464

465

for event in events:

466

handler = getattr(self, f"handle_{event.__class__.__name__}", None)

467

if handler:

468

handler(event)

469

else:

470

print(f"Unhandled event: {event.__class__.__name__}")

471

472

except ProtocolError as e:

473

print(f"Protocol error: {e}")

474

self.conn.close_connection()

475

476

return self.conn.data_to_send()

477

478

def handle_RequestReceived(self, event: RequestReceived):

479

self.streams[event.stream_id] = {

480

'headers': event.headers,

481

'method': next((v for n, v in event.headers if n == b':method'), None),

482

'path': next((v for n, v in event.headers if n == b':path'), None)

483

}

484

485

if event.stream_ended:

486

self.handle_complete_request(event.stream_id)

487

488

def handle_DataReceived(self, event: DataReceived):

489

if event.stream_id in self.streams:

490

stream_data = self.streams[event.stream_id].setdefault('data', b'')

491

self.streams[event.stream_id]['data'] = stream_data + event.data

492

493

# Acknowledge for flow control

494

self.conn.acknowledge_received_data(

495

acknowledged_size=event.flow_controlled_length,

496

stream_id=event.stream_id

497

)

498

499

if event.stream_ended:

500

self.handle_complete_request(event.stream_id)

501

502

def handle_PingReceived(self, event: PingReceived):

503

print(f"Ping received with data: {event.ping_data.hex()}")

504

# Ping acknowledgment is sent automatically

505

506

def handle_complete_request(self, stream_id: int):

507

if stream_id in self.streams:

508

stream = self.streams[stream_id]

509

print(f"Complete request on stream {stream_id}: {stream.get('method')} {stream.get('path')}")

510

# Process complete request...

511

del self.streams[stream_id]

512

```