or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdcontrol-frames.mddata-headers.mdframe-operations.mdindex.md

frame-operations.mddocs/

0

# Frame Operations

1

2

Core functionality for parsing HTTP/2 frames from binary data and creating new frames with proper validation and serialization support. This forms the foundation of all HTTP/2 frame handling in hyperframe.

3

4

## Capabilities

5

6

### Frame Base Class

7

8

The base Frame class provides common functionality for all HTTP/2 frame types including stream ID management, flag handling, and serialization/parsing infrastructure.

9

10

```python { .api }

11

class Frame:

12

def __init__(self, stream_id: int, flags: Iterable[str] = ()) -> None:

13

"""

14

Initialize a frame with stream ID and optional flags.

15

16

Parameters:

17

- stream_id (int): Stream identifier (0 for connection-level frames)

18

- flags (Iterable[str]): Initial flags to set on the frame

19

20

Raises:

21

- InvalidDataError: If stream_id validation fails based on stream_association

22

"""

23

24

@property

25

def stream_id(self) -> int: ...

26

27

@property

28

def flags(self) -> Flags: ...

29

30

@property

31

def body_len(self) -> int: ...

32

33

def serialize(self) -> bytes:

34

"""

35

Convert frame into binary representation.

36

37

Returns:

38

bytes: Complete frame including 9-byte header and body

39

"""

40

41

def serialize_body(self) -> bytes:

42

"""

43

Serialize frame body data. Must be implemented by subclasses.

44

45

Returns:

46

bytes: Frame body data

47

48

Raises:

49

NotImplementedError: If called on base Frame class

50

"""

51

52

def parse_body(self, data: memoryview) -> None:

53

"""

54

Parse frame body from binary data. Must be implemented by subclasses.

55

56

Parameters:

57

- data (memoryview): Body data to parse

58

59

Raises:

60

NotImplementedError: If called on base Frame class

61

"""

62

63

def parse_flags(self, flag_byte: int) -> Flags:

64

"""

65

Parse flag byte and set appropriate flags.

66

67

Parameters:

68

- flag_byte (int): 8-bit flag value from frame header

69

70

Returns:

71

Flags: Updated flags object

72

"""

73

```

74

75

### Frame Header Parsing

76

77

Static methods for parsing frame headers and handling frame discovery from binary streams.

78

79

```python { .api }

80

@staticmethod

81

def parse_frame_header(header: memoryview, strict: bool = False) -> tuple[Frame, int]:

82

"""

83

Parse 9-byte frame header and return appropriate Frame object.

84

85

Parameters:

86

- header (memoryview): Exactly 9 bytes of frame header data

87

- strict (bool): If True, raise exception for unknown frame types

88

89

Returns:

90

tuple[Frame, int]: Frame object and body length to read

91

92

Raises:

93

- InvalidFrameError: If header data is malformed

94

- UnknownFrameError: If frame type unknown and strict=True

95

"""

96

97

@staticmethod

98

def explain(data: memoryview) -> tuple[Frame, int]:

99

"""

100

Debug helper that parses and prints a complete frame.

101

102

Parameters:

103

- data (memoryview): Complete frame data (header + body)

104

105

Returns:

106

tuple[Frame, int]: Parsed frame and body length

107

"""

108

```

109

110

### Mixin Classes

111

112

Base functionality that can be inherited by frame types supporting padding or priority information.

113

114

```python { .api }

115

class Padding:

116

def __init__(self, stream_id: int, pad_length: int = 0, **kwargs) -> None:

117

"""

118

Initialize padding support.

119

120

Parameters:

121

- stream_id (int): Stream identifier

122

- pad_length (int): Number of padding bytes to add

123

- **kwargs: Additional arguments passed to parent class

124

"""

125

126

@property

127

def pad_length(self) -> int: ...

128

129

def serialize_padding_data(self) -> bytes:

130

"""

131

Serialize padding length field if PADDED flag is set.

132

133

Returns:

134

bytes: Padding length byte or empty if not padded

135

"""

136

137

def parse_padding_data(self, data: memoryview) -> int:

138

"""

139

Parse padding length from frame data if PADDED flag is set.

140

141

Parameters:

142

- data (memoryview): Frame body data starting with padding info

143

144

Returns:

145

int: Number of bytes consumed (1 if padded, 0 if not)

146

147

Raises:

148

- InvalidFrameError: If padding data is malformed

149

"""

150

151

class Priority:

152

def __init__(self, stream_id: int, depends_on: int = 0, stream_weight: int = 0,

153

exclusive: bool = False, **kwargs) -> None:

154

"""

155

Initialize priority support.

156

157

Parameters:

158

- stream_id (int): Stream identifier

159

- depends_on (int): Stream ID this stream depends on

160

- stream_weight (int): Stream weight (0-255)

161

- exclusive (bool): Whether this stream has exclusive dependency

162

- **kwargs: Additional arguments passed to parent class

163

"""

164

165

@property

166

def depends_on(self) -> int: ...

167

168

@property

169

def stream_weight(self) -> int: ...

170

171

@property

172

def exclusive(self) -> bool: ...

173

174

def serialize_priority_data(self) -> bytes:

175

"""

176

Serialize 5-byte priority information.

177

178

Returns:

179

bytes: Priority data (4 bytes stream dependency + 1 byte weight)

180

"""

181

182

def parse_priority_data(self, data: memoryview) -> int:

183

"""

184

Parse priority information from frame data.

185

186

Parameters:

187

- data (memoryview): Frame body data starting with priority info

188

189

Returns:

190

int: Number of bytes consumed (always 5)

191

192

Raises:

193

- InvalidFrameError: If priority data is malformed

194

"""

195

```

196

197

## Usage Examples

198

199

### Basic Frame Parsing

200

201

```python

202

from hyperframe.frame import Frame

203

204

# Parse frame from binary data

205

frame_data = b'\\x00\\x00\\x05\\x00\\x00\\x00\\x00\\x00\\x01Hello'

206

frame, body_length = Frame.parse_frame_header(frame_data[:9])

207

frame.parse_body(memoryview(frame_data[9:9 + body_length]))

208

209

print(f"Frame type: {frame.type}")

210

print(f"Stream ID: {frame.stream_id}")

211

print(f"Body length: {body_length}")

212

```

213

214

### Creating Custom Frames

215

216

```python

217

from hyperframe.frame import DataFrame

218

219

# Create DATA frame with padding

220

frame = DataFrame(

221

stream_id=1,

222

data=b"Hello, HTTP/2!",

223

pad_length=8,

224

flags=["END_STREAM", "PADDED"]

225

)

226

227

# Serialize to binary

228

binary_data = frame.serialize()

229

print(f"Serialized frame: {len(binary_data)} bytes")

230

```

231

232

### Handling Unknown Frame Types

233

234

```python

235

from hyperframe.frame import Frame, ExtensionFrame

236

from hyperframe.exceptions import UnknownFrameError

237

238

# Parse with strict=False to handle unknown frames

239

frame_data = b'\\x00\\x00\\x05\\xFF\\x00\\x00\\x00\\x00\\x01Hello' # Type 0xFF

240

frame, length = Frame.parse_frame_header(frame_data[:9], strict=False)

241

242

if isinstance(frame, ExtensionFrame):

243

print(f"Unknown frame type: 0x{frame.type:02X}")

244

frame.parse_body(memoryview(frame_data[9:9 + length]))

245

print(f"Frame body: {frame.body}")

246

247

# Parse with strict=True raises exception

248

try:

249

Frame.parse_frame_header(frame_data[:9], strict=True)

250

except UnknownFrameError as e:

251

print(f"Unknown frame: type=0x{e.frame_type:02X}, length={e.length}")

252

```