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

data-headers.mddocs/

0

# Data and Header Frames

1

2

Implementation of HTTP/2 DATA and HEADERS frames for carrying application data and HTTP headers. These frames support padding, priority information, and proper stream association for efficient HTTP/2 communication.

3

4

## Capabilities

5

6

### DATA Frames

7

8

DATA frames carry arbitrary application data associated with a stream, such as HTTP request or response payloads.

9

10

```python { .api }

11

class DataFrame(Padding, Frame):

12

def __init__(self, stream_id: int, data: bytes = b"", **kwargs) -> None:

13

"""

14

Create a DATA frame.

15

16

Parameters:

17

- stream_id (int): Stream identifier (must be non-zero)

18

- data (bytes): Application data to carry

19

- pad_length (int): Padding length if PADDED flag set

20

- flags (Iterable[str]): Frame flags ("END_STREAM", "PADDED")

21

- **kwargs: Additional arguments for parent classes

22

23

Raises:

24

- InvalidDataError: If stream_id is zero

25

"""

26

27

@property

28

def data(self) -> bytes:

29

"""Application data carried by this frame."""

30

31

@property

32

def flow_controlled_length(self) -> int:

33

"""

34

Length of frame that counts toward flow control.

35

36

Returns:

37

int: Data length plus padding overhead

38

"""

39

40

# Inherited from Frame

41

def serialize_body(self) -> bytes: ...

42

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

43

```

44

45

**Defined Flags:**

46

- `END_STREAM` (0x01): Indicates this is the last frame for the stream

47

- `PADDED` (0x08): Indicates frame contains padding

48

49

### HEADERS Frames

50

51

HEADERS frames carry HTTP header information and can open new streams. They support priority information and padding.

52

53

```python { .api }

54

class HeadersFrame(Padding, Priority, Frame):

55

def __init__(self, stream_id: int, data: bytes = b"", **kwargs) -> None:

56

"""

57

Create a HEADERS frame.

58

59

Parameters:

60

- stream_id (int): Stream identifier (must be non-zero)

61

- data (bytes): HPACK-encoded header block

62

- pad_length (int): Padding length if PADDED flag set

63

- depends_on (int): Stream dependency if PRIORITY flag set

64

- stream_weight (int): Stream weight if PRIORITY flag set

65

- exclusive (bool): Exclusive dependency if PRIORITY flag set

66

- flags (Iterable[str]): Frame flags

67

- **kwargs: Additional arguments for parent classes

68

69

Raises:

70

- InvalidDataError: If stream_id is zero

71

"""

72

73

@property

74

def data(self) -> bytes:

75

"""HPACK-encoded header block data."""

76

77

# Inherited from Frame

78

def serialize_body(self) -> bytes: ...

79

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

80

```

81

82

**Defined Flags:**

83

- `END_STREAM` (0x01): Indicates this is the last frame for the stream

84

- `END_HEADERS` (0x04): Indicates end of header list (no CONTINUATION frames follow)

85

- `PADDED` (0x08): Indicates frame contains padding

86

- `PRIORITY` (0x20): Indicates frame contains priority information

87

88

### CONTINUATION Frames

89

90

CONTINUATION frames continue header block fragments when headers don't fit in a single HEADERS or PUSH_PROMISE frame.

91

92

```python { .api }

93

class ContinuationFrame(Frame):

94

def __init__(self, stream_id: int, data: bytes = b"", **kwargs) -> None:

95

"""

96

Create a CONTINUATION frame.

97

98

Parameters:

99

- stream_id (int): Stream identifier (must be non-zero)

100

- data (bytes): HPACK-encoded header block fragment

101

- flags (Iterable[str]): Frame flags ("END_HEADERS")

102

- **kwargs: Additional arguments for parent classes

103

104

Raises:

105

- InvalidDataError: If stream_id is zero

106

"""

107

108

@property

109

def data(self) -> bytes:

110

"""HPACK-encoded header block fragment."""

111

112

# Inherited from Frame

113

def serialize_body(self) -> bytes: ...

114

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

115

```

116

117

**Defined Flags:**

118

- `END_HEADERS` (0x04): Indicates end of header list

119

120

## Usage Examples

121

122

### Creating DATA Frames

123

124

```python

125

from hyperframe.frame import DataFrame

126

127

# Simple DATA frame

128

data_frame = DataFrame(stream_id=1, data=b"Hello, World!")

129

130

# DATA frame with END_STREAM flag

131

final_frame = DataFrame(

132

stream_id=1,

133

data=b"Final chunk",

134

flags=["END_STREAM"]

135

)

136

137

# DATA frame with padding

138

padded_frame = DataFrame(

139

stream_id=1,

140

data=b"Padded data",

141

pad_length=10,

142

flags=["PADDED"]

143

)

144

145

# Check flow control length

146

print(f"Flow control length: {padded_frame.flow_controlled_length}")

147

```

148

149

### Creating HEADERS Frames

150

151

```python

152

from hyperframe.frame import HeadersFrame

153

154

# Simple HEADERS frame

155

headers_frame = HeadersFrame(

156

stream_id=1,

157

data=b"\\x00\\x07:method\\x03GET", # HPACK-encoded headers

158

flags=["END_HEADERS"]

159

)

160

161

# HEADERS frame with priority

162

priority_headers = HeadersFrame(

163

stream_id=1,

164

data=b"\\x00\\x07:method\\x04POST",

165

depends_on=0,

166

stream_weight=16,

167

exclusive=False,

168

flags=["END_HEADERS", "PRIORITY"]

169

)

170

171

# HEADERS frame opening stream

172

stream_opener = HeadersFrame(

173

stream_id=1,

174

data=b"\\x00\\x07:method\\x03GET\\x00\\x05:path\\x01/",

175

flags=["END_HEADERS", "END_STREAM"] # GET request with no body

176

)

177

```

178

179

### Working with CONTINUATION Frames

180

181

```python

182

from hyperframe.frame import HeadersFrame, ContinuationFrame

183

184

# Large header block split across frames

185

header_data = b"\\x00\\x07:method\\x03GET" + b"\\x00" * 1000 # Large headers

186

187

# Initial HEADERS frame (without END_HEADERS)

188

headers_frame = HeadersFrame(

189

stream_id=1,

190

data=header_data[:500]

191

# Note: no END_HEADERS flag

192

)

193

194

# CONTINUATION frame with remaining data

195

continuation_frame = ContinuationFrame(

196

stream_id=1,

197

data=header_data[500:],

198

flags=["END_HEADERS"] # End of header block

199

)

200

201

print(f"Headers frame: {len(headers_frame.data)} bytes")

202

print(f"Continuation frame: {len(continuation_frame.data)} bytes")

203

```

204

205

### Parsing Data and Header Frames

206

207

```python

208

from hyperframe.frame import Frame

209

210

# Parse DATA frame

211

data_bytes = b'\\x00\\x00\\x0D\\x00\\x01\\x00\\x00\\x00\\x01Hello, World!'

212

frame, length = Frame.parse_frame_header(data_bytes[:9])

213

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

214

215

print(f"Frame type: DATA")

216

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

217

print(f"Data: {frame.data}")

218

print(f"END_STREAM: {'END_STREAM' in frame.flags}")

219

220

# Parse HEADERS frame with priority

221

headers_bytes = (

222

b'\\x00\\x00\\x09\\x01\\x24\\x00\\x00\\x00\\x01' # Header

223

b'\\x00\\x00\\x00\\x00\\x10' # Priority (depends_on=0, weight=16)

224

b'\\x00\\x07:method\\x03GET' # HPACK data

225

)

226

frame, length = Frame.parse_frame_header(headers_bytes[:9])

227

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

228

229

print(f"Frame type: HEADERS")

230

print(f"Priority info: depends_on={frame.depends_on}, weight={frame.stream_weight}")

231

print(f"Exclusive: {frame.exclusive}")

232

```

233

234

### Error Handling

235

236

```python

237

from hyperframe.frame import DataFrame

238

from hyperframe.exceptions import InvalidDataError, InvalidPaddingError

239

240

# Invalid stream ID

241

try:

242

DataFrame(stream_id=0, data=b"Invalid") # DATA frames must have non-zero stream ID

243

except InvalidDataError as e:

244

print(f"Error: {e}")

245

246

# Invalid padding

247

try:

248

frame_data = b'\\x00\\x00\\x02\\x00\\x08\\x00\\x00\\x00\\x01\\xFF\\xFF' # Padding > body length

249

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

250

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

251

except InvalidPaddingError as e:

252

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

253

```