0
# Settings Management
1
2
HTTP/2 settings negotiation, validation, and state management. Settings control connection behavior and are negotiated between peers during connection establishment and throughout the connection lifetime.
3
4
## Capabilities
5
6
### Setting Codes Enumeration
7
8
Standard HTTP/2 setting codes defined in the specification.
9
10
```python { .api }
11
class SettingCodes(enum.IntEnum):
12
"""
13
All known HTTP/2 setting codes.
14
15
Values correspond to official HTTP/2 specification setting identifiers.
16
"""
17
18
HEADER_TABLE_SIZE = 0x1
19
"""Maximum size of header compression table used to decode header blocks."""
20
21
ENABLE_PUSH = 0x2
22
"""Enable or disable server push (0 to disable, 1 to enable)."""
23
24
MAX_CONCURRENT_STREAMS = 0x3
25
"""Maximum number of concurrent streams sender will allow."""
26
27
INITIAL_WINDOW_SIZE = 0x4
28
"""Sender's initial window size for stream-level flow control."""
29
30
MAX_FRAME_SIZE = 0x5
31
"""Size of largest frame payload sender is willing to receive."""
32
33
MAX_HEADER_LIST_SIZE = 0x6
34
"""Maximum size of header list sender is prepared to accept."""
35
36
ENABLE_CONNECT_PROTOCOL = 0x8
37
"""Enable connect protocol (0 to disable, 1 to enable)."""
38
```
39
40
### Setting Change Tracking
41
42
Object representing a setting value change.
43
44
```python { .api }
45
class ChangedSetting:
46
"""
47
Represents a setting that has changed value.
48
49
Attributes:
50
setting: The setting code that changed
51
original_value: Previous value (None if first setting)
52
new_value: New value after change
53
"""
54
55
def __init__(
56
self,
57
setting: SettingCodes | int,
58
original_value: int | None,
59
new_value: int
60
):
61
"""
62
Initialize changed setting.
63
64
Args:
65
setting: Setting code (SettingCodes enum or int)
66
original_value: Previous value, None if not previously set
67
new_value: New value after change
68
"""
69
self.setting = setting
70
self.original_value = original_value
71
self.new_value = new_value
72
73
def __repr__(self) -> str:
74
"""String representation of the setting change."""
75
```
76
77
### Settings State Management
78
79
Main settings management class implementing MutableMapping interface.
80
81
```python { .api }
82
class Settings(MutableMapping[Union[SettingCodes, int], int]):
83
"""
84
HTTP/2 settings state management.
85
86
Manages local and remote settings with acknowledgment tracking,
87
validation, and default value handling. Settings changes are
88
tracked until acknowledged by the remote peer.
89
"""
90
91
def __init__(
92
self,
93
client: bool = True,
94
initial_values: dict[SettingCodes | int, int] | None = None
95
):
96
"""
97
Initialize settings object.
98
99
Args:
100
client: Whether this is for client-side (True) or server-side (False)
101
initial_values: Initial setting values to apply
102
"""
103
104
def acknowledge(self) -> dict[SettingCodes | int, ChangedSetting]:
105
"""
106
Acknowledge pending settings changes.
107
108
Called when SETTINGS ACK frame is received. Applies all pending
109
setting changes and returns what changed.
110
111
Returns:
112
Dictionary mapping setting codes to ChangedSetting objects
113
"""
114
```
115
116
#### Settings Properties
117
118
Direct access to individual HTTP/2 settings with validation.
119
120
```python { .api }
121
@property
122
def header_table_size(self) -> int:
123
"""
124
HPACK dynamic table maximum size.
125
126
Range: 0 to 2^32-1
127
Default: 4096
128
"""
129
130
@header_table_size.setter
131
def header_table_size(self, value: int) -> None: ...
132
133
@property
134
def enable_push(self) -> int:
135
"""
136
Server push enablement.
137
138
Values: 0 (disabled) or 1 (enabled)
139
Default: 1 (enabled)
140
"""
141
142
@enable_push.setter
143
def enable_push(self, value: int) -> None: ...
144
145
@property
146
def initial_window_size(self) -> int:
147
"""
148
Initial flow control window size for new streams.
149
150
Range: 0 to 2^31-1
151
Default: 65535
152
"""
153
154
@initial_window_size.setter
155
def initial_window_size(self, value: int) -> None: ...
156
157
@property
158
def max_frame_size(self) -> int:
159
"""
160
Maximum frame payload size willing to receive.
161
162
Range: 16384 to 2^24-1
163
Default: 16384
164
"""
165
166
@max_frame_size.setter
167
def max_frame_size(self, value: int) -> None: ...
168
169
@property
170
def max_concurrent_streams(self) -> int:
171
"""
172
Maximum number of concurrent streams.
173
174
Range: 0 to 2^32-1
175
Default: unlimited (but h2 defaults to 100 for safety)
176
"""
177
178
@max_concurrent_streams.setter
179
def max_concurrent_streams(self, value: int) -> None: ...
180
181
@property
182
def max_header_list_size(self) -> int | None:
183
"""
184
Maximum header list size willing to accept.
185
186
Range: 0 to 2^32-1, or None if not set
187
Default: None (unlimited)
188
"""
189
190
@max_header_list_size.setter
191
def max_header_list_size(self, value: int | None) -> None: ...
192
193
@property
194
def enable_connect_protocol(self) -> int:
195
"""
196
Connect protocol enablement.
197
198
Values: 0 (disabled) or 1 (enabled)
199
Default: 0 (disabled)
200
"""
201
202
@enable_connect_protocol.setter
203
def enable_connect_protocol(self, value: int) -> None: ...
204
```
205
206
#### MutableMapping Interface
207
208
Full dictionary-like interface for settings manipulation.
209
210
```python { .api }
211
def __getitem__(self, key: SettingCodes | int) -> int:
212
"""Get setting value by code."""
213
214
def __setitem__(self, key: SettingCodes | int, value: int) -> None:
215
"""Set setting value by code."""
216
217
def __delitem__(self, key: SettingCodes | int) -> None:
218
"""Delete/reset setting to default value."""
219
220
def __iter__(self):
221
"""Iterate over setting codes."""
222
223
def __len__(self) -> int:
224
"""Number of configured settings."""
225
226
def __eq__(self, other) -> bool:
227
"""Compare settings objects for equality."""
228
229
def __ne__(self, other) -> bool:
230
"""Compare settings objects for inequality."""
231
```
232
233
### Utility Functions
234
235
Helper functions for settings code conversion and validation.
236
237
```python { .api }
238
def _setting_code_from_int(code: int) -> SettingCodes | int:
239
"""
240
Convert integer to SettingCodes enum if known, otherwise return int.
241
242
Args:
243
code: Integer setting code
244
245
Returns:
246
SettingCodes enum member if known, otherwise the original int
247
"""
248
```
249
250
## Settings Usage Patterns
251
252
### Basic Settings Management
253
254
```python
255
from h2.settings import Settings, SettingCodes
256
257
# Create settings for client
258
settings = Settings(client=True)
259
260
# Access individual settings
261
print(f"Initial window size: {settings.initial_window_size}")
262
print(f"Max frame size: {settings.max_frame_size}")
263
264
# Modify settings
265
settings.initial_window_size = 32768
266
settings.max_concurrent_streams = 50
267
268
# Use dictionary interface
269
settings[SettingCodes.ENABLE_PUSH] = 0 # Disable server push
270
```
271
272
### Settings with Initial Values
273
274
```python
275
from h2.settings import Settings, SettingCodes
276
277
# Initialize with custom defaults
278
initial_settings = {
279
SettingCodes.INITIAL_WINDOW_SIZE: 65536,
280
SettingCodes.MAX_CONCURRENT_STREAMS: 100,
281
SettingCodes.ENABLE_PUSH: 0
282
}
283
284
settings = Settings(client=True, initial_values=initial_settings)
285
```
286
287
### Settings Acknowledgment
288
289
```python
290
from h2.connection import H2Connection
291
from h2.settings import SettingCodes
292
293
conn = H2Connection()
294
295
# Update settings
296
new_settings = {
297
SettingCodes.INITIAL_WINDOW_SIZE: 32768,
298
SettingCodes.MAX_FRAME_SIZE: 32768
299
}
300
301
conn.update_settings(new_settings)
302
303
# Later, when SETTINGS ACK event is received
304
# (this happens automatically in H2Connection)
305
changed = conn.local_settings.acknowledge()
306
307
for setting_code, change in changed.items():
308
print(f"Setting {setting_code}: {change.original_value} -> {change.new_value}")
309
```
310
311
### Settings Validation
312
313
```python
314
from h2.settings import Settings, SettingCodes
315
from h2.exceptions import InvalidSettingsValueError
316
317
settings = Settings()
318
319
try:
320
# This will raise InvalidSettingsValueError
321
settings.max_frame_size = 1000 # Too small (minimum is 16384)
322
323
except InvalidSettingsValueError as e:
324
print(f"Invalid setting value: {e}")
325
print(f"Error code: {e.error_code}")
326
327
try:
328
# This will also raise InvalidSettingsValueError
329
settings.enable_push = 2 # Must be 0 or 1
330
331
except InvalidSettingsValueError as e:
332
print(f"Invalid setting value: {e}")
333
```
334
335
### Settings Iteration and Inspection
336
337
```python
338
from h2.settings import Settings
339
340
settings = Settings(client=True)
341
342
# Iterate over all settings
343
for setting_code in settings:
344
value = settings[setting_code]
345
print(f"{setting_code}: {value}")
346
347
# Check specific settings
348
if SettingCodes.MAX_HEADER_LIST_SIZE in settings:
349
print(f"Header list size limit: {settings.max_header_list_size}")
350
else:
351
print("No header list size limit set")
352
353
# Get all settings as dictionary
354
all_settings = dict(settings)
355
print(f"All settings: {all_settings}")
356
```
357
358
## Settings Behavior and Validation
359
360
### Default Values
361
362
- **HEADER_TABLE_SIZE**: 4096 bytes
363
- **ENABLE_PUSH**: 1 (enabled) for servers, not applicable for clients
364
- **MAX_CONCURRENT_STREAMS**: unlimited (h2 defaults to 100 for safety)
365
- **INITIAL_WINDOW_SIZE**: 65535 bytes
366
- **MAX_FRAME_SIZE**: 16384 bytes
367
- **MAX_HEADER_LIST_SIZE**: unlimited (None)
368
- **ENABLE_CONNECT_PROTOCOL**: 0 (disabled)
369
370
### Validation Rules
371
372
- **HEADER_TABLE_SIZE**: 0 to 2^32-1
373
- **ENABLE_PUSH**: Must be 0 or 1
374
- **MAX_CONCURRENT_STREAMS**: 0 to 2^32-1
375
- **INITIAL_WINDOW_SIZE**: 0 to 2^31-1
376
- **MAX_FRAME_SIZE**: 16384 to 2^24-1 (16777215)
377
- **MAX_HEADER_LIST_SIZE**: 0 to 2^32-1 or None
378
- **ENABLE_CONNECT_PROTOCOL**: Must be 0 or 1
379
380
### Client vs Server Differences
381
382
- **Server-side**: ENABLE_PUSH controls whether server can send push promises
383
- **Client-side**: ENABLE_PUSH setting sent to server controls push acceptance
384
- **MAX_CONCURRENT_STREAMS**: Limits streams the *remote* peer can open
385
- **Other settings**: Apply uniformly regardless of client/server role