or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

addons.mdcommands.mdconfiguration.mdconnections.mdcontent.mdflow-io.mdhttp-flows.mdindex.mdprotocols.md

http-flows.mddocs/

0

# HTTP Flow Management

1

2

Core HTTP proxy functionality for intercepting, analyzing, and modifying HTTP/1, HTTP/2, and HTTP/3 traffic. HTTP flows represent complete request/response conversations with comprehensive metadata and manipulation capabilities.

3

4

## Capabilities

5

6

### HTTPFlow Class

7

8

The main container for HTTP conversations, tracking requests, responses, errors, and metadata throughout the proxy lifecycle.

9

10

```python { .api }

11

class HTTPFlow(Flow):

12

"""

13

An HTTP conversation between client and server.

14

15

Attributes:

16

- request: The HTTP request

17

- response: The HTTP response (None if not yet received)

18

- error: Error information if the flow failed

19

- server_conn: Server connection details

20

- client_conn: Client connection details

21

- intercepted: Whether the flow is currently intercepted

22

- marked: User-defined marker for flow identification

23

- metadata: Additional flow metadata

24

"""

25

request: Request

26

response: Optional[Response]

27

error: Optional[Error]

28

server_conn: Optional[Server]

29

client_conn: Optional[Client]

30

intercepted: bool

31

marked: str

32

metadata: Dict[str, Any]

33

34

def copy(self) -> "HTTPFlow": ...

35

def kill(self) -> None: ...

36

def resume(self) -> None: ...

37

def intercept(self) -> None: ...

38

```

39

40

### Request Class

41

42

HTTP request representation with comprehensive access to method, URL, headers, and content.

43

44

```python { .api }

45

class Request(Message):

46

"""

47

HTTP request with method, URL, headers, and content.

48

49

Parameters:

50

- host: Target server hostname

51

- port: Target server port

52

- method: HTTP method as bytes (b'GET', b'POST', etc.)

53

- scheme: URL scheme as bytes (b'http', b'https')

54

- authority: Host authority as bytes

55

- path: Request path as bytes

56

- http_version: HTTP version as bytes (b'HTTP/1.1', b'HTTP/2')

57

- headers: HTTP headers container

58

- content: Request body content as bytes

59

- trailers: HTTP trailers (for chunked encoding)

60

- timestamp_start: Request start timestamp

61

- timestamp_end: Request completion timestamp

62

"""

63

def __init__(

64

self,

65

host: str,

66

port: int,

67

method: bytes,

68

scheme: bytes,

69

authority: bytes,

70

path: bytes,

71

http_version: bytes,

72

headers: Headers,

73

content: bytes,

74

trailers: Optional[Headers] = None,

75

timestamp_start: float = 0,

76

timestamp_end: Optional[float] = None

77

) -> None: ...

78

79

# Properties

80

@property

81

def method(self) -> str: ...

82

@method.setter

83

def method(self, value: str) -> None: ...

84

85

@property

86

def url(self) -> str: ...

87

@url.setter

88

def url(self, value: str) -> None: ...

89

90

@property

91

def scheme(self) -> str: ...

92

@scheme.setter

93

def scheme(self, value: str) -> None: ...

94

95

@property

96

def host(self) -> str: ...

97

@host.setter

98

def host(self, value: str) -> None: ...

99

100

@property

101

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

102

@port.setter

103

def port(self, value: int) -> None: ...

104

105

@property

106

def path(self) -> str: ...

107

@path.setter

108

def path(self, value: str) -> None: ...

109

110

@property

111

def query(self) -> MultiDict: ...

112

@query.setter

113

def query(self, value: MultiDict) -> None: ...

114

115

# Content methods

116

def get_text(self, strict: bool = True) -> str: ...

117

def set_text(self, text: str) -> None: ...

118

def get_content(self, strict: bool = True) -> bytes: ...

119

def set_content(self, content: Optional[bytes]) -> None: ...

120

121

# Convenience methods

122

def json(self, **kwargs) -> Any: ...

123

def urlencoded_form(self) -> MultiDict: ...

124

def multipart_form(self) -> MultiDict: ...

125

126

# Static constructors

127

@classmethod

128

def make(

129

cls,

130

method: str,

131

url: str,

132

content: Union[bytes, str] = b"",

133

headers: Optional[Union[Headers, Dict]] = None,

134

**kwargs

135

) -> "Request": ...

136

```

137

138

### Response Class

139

140

HTTP response representation with status code, headers, and content manipulation capabilities.

141

142

```python { .api }

143

class Response(Message):

144

"""

145

HTTP response with status code, headers, and content.

146

147

Parameters:

148

- http_version: HTTP version as bytes

149

- status_code: HTTP status code (200, 404, etc.)

150

- reason: HTTP reason phrase as bytes

151

- headers: HTTP response headers

152

- content: Response body content as bytes

153

- trailers: HTTP trailers (for chunked encoding)

154

- timestamp_start: Response start timestamp

155

- timestamp_end: Response completion timestamp

156

"""

157

def __init__(

158

self,

159

http_version: bytes,

160

status_code: int,

161

reason: bytes,

162

headers: Headers,

163

content: bytes,

164

trailers: Optional[Headers] = None,

165

timestamp_start: float = 0,

166

timestamp_end: float = 0

167

) -> None: ...

168

169

# Properties

170

@property

171

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

172

@status_code.setter

173

def status_code(self, value: int) -> None: ...

174

175

@property

176

def reason(self) -> str: ...

177

@reason.setter

178

def reason(self, value: str) -> None: ...

179

180

@property

181

def http_version(self) -> str: ...

182

@http_version.setter

183

def http_version(self, value: str) -> None: ...

184

185

# Content methods (inherited from Message)

186

def get_text(self, strict: bool = True) -> str: ...

187

def set_text(self, text: str) -> None: ...

188

def get_content(self, strict: bool = True) -> bytes: ...

189

def set_content(self, content: Optional[bytes]) -> None: ...

190

191

# Convenience methods

192

def json(self, **kwargs) -> Any: ...

193

194

# Static constructors

195

@classmethod

196

def make(

197

cls,

198

status_code: int = 200,

199

content: Union[bytes, str] = b"",

200

headers: Optional[Union[Headers, Dict]] = None,

201

**kwargs

202

) -> "Response": ...

203

```

204

205

### Headers Class

206

207

Case-insensitive HTTP headers container with multi-value support and comprehensive manipulation methods.

208

209

```python { .api }

210

class Headers(multidict.MultiDict):

211

"""

212

Case-insensitive HTTP headers container supporting multiple values per key.

213

214

Extends multidict.MultiDict with HTTP-specific functionality.

215

"""

216

def __init__(self, data: Union[Dict, List[Tuple[str, str]], Headers] = None) -> None: ...

217

218

# Basic access (case-insensitive)

219

def __getitem__(self, key: str) -> str: ...

220

def __setitem__(self, key: str, value: str) -> None: ...

221

def __delitem__(self, key: str) -> None: ...

222

def __contains__(self, key: str) -> bool: ...

223

224

# Multi-value methods

225

def get(self, key: str, default: Optional[str] = None) -> Optional[str]: ...

226

def get_all(self, key: str) -> List[str]: ...

227

def add(self, key: str, value: str) -> None: ...

228

def extend(self, other: Union[Dict, Headers]) -> None: ...

229

230

# HTTP-specific methods

231

def set_all(self, key: str, values: List[str]) -> None: ...

232

def items(self, multi: bool = False) -> Iterator[Tuple[str, str]]: ...

233

def keys(self) -> KeysView: ...

234

def values(self) -> ValuesView: ...

235

236

# String representation

237

def __str__(self) -> str: ...

238

def __repr__(self) -> str: ...

239

```

240

241

### Message Base Class

242

243

Abstract base class for HTTP requests and responses providing common functionality.

244

245

```python { .api }

246

class Message:

247

"""

248

Base class for HTTP requests and responses.

249

250

Provides common functionality for header and content manipulation.

251

"""

252

headers: Headers

253

content: bytes

254

trailers: Optional[Headers]

255

timestamp_start: float

256

timestamp_end: Optional[float]

257

258

# Content handling

259

def get_text(self, strict: bool = True) -> str: ...

260

def set_text(self, text: str) -> None: ...

261

def get_content(self, strict: bool = True) -> bytes: ...

262

def set_content(self, content: Optional[bytes]) -> None: ...

263

264

# Content decoding/encoding

265

def decode(self, strict: bool = True) -> None: ...

266

def encode(self, encoding: str) -> None: ...

267

268

# JSON handling

269

def json(self, **kwargs) -> Any: ...

270

271

# Raw data access

272

@property

273

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

274

@raw_content.setter

275

def raw_content(self, content: bytes) -> None: ...

276

```

277

278

## Usage Examples

279

280

### Basic Request/Response Modification

281

282

```python

283

from mitmproxy import http

284

285

def request(flow: http.HTTPFlow) -> None:

286

"""Modify outgoing requests."""

287

# Add authentication header

288

if "api.example.com" in flow.request.url:

289

flow.request.headers["Authorization"] = "Bearer token123"

290

291

# Modify request body for POST requests

292

if flow.request.method == "POST":

293

if flow.request.headers.get("content-type", "").startswith("application/json"):

294

data = flow.request.json()

295

data["modified"] = True

296

flow.request.set_text(json.dumps(data))

297

298

def response(flow: http.HTTPFlow) -> None:

299

"""Modify incoming responses."""

300

# Add CORS headers

301

flow.response.headers["Access-Control-Allow-Origin"] = "*"

302

flow.response.headers["Access-Control-Allow-Methods"] = "GET,POST,PUT,DELETE"

303

304

# Modify JSON responses

305

if flow.response.headers.get("content-type", "").startswith("application/json"):

306

try:

307

data = flow.response.json()

308

data["proxy_processed"] = True

309

flow.response.set_text(json.dumps(data))

310

except ValueError:

311

pass # Not valid JSON

312

```

313

314

### Creating Responses Programmatically

315

316

```python

317

from mitmproxy import http

318

319

def request(flow: http.HTTPFlow) -> None:

320

"""Create custom responses."""

321

# Block specific requests

322

if "/blocked" in flow.request.path:

323

flow.response = http.Response.make(

324

status_code=403,

325

content="Access Denied",

326

headers={"Content-Type": "text/plain"}

327

)

328

329

# Redirect requests

330

elif "/old-path" in flow.request.path:

331

flow.response = http.Response.make(

332

status_code=301,

333

headers={"Location": "https://example.com/new-path"}

334

)

335

336

# Mock API responses

337

elif "/api/users" in flow.request.path and flow.request.method == "GET":

338

mock_data = {"users": [{"id": 1, "name": "John"}, {"id": 2, "name": "Jane"}]}

339

flow.response = http.Response.make(

340

status_code=200,

341

content=json.dumps(mock_data),

342

headers={"Content-Type": "application/json"}

343

)

344

```

345

346

### Advanced Flow Manipulation

347

348

```python

349

import time

350

from mitmproxy import http

351

352

def request(flow: http.HTTPFlow) -> None:

353

"""Advanced request handling."""

354

# Log detailed request information

355

print(f"Request: {flow.request.method} {flow.request.url}")

356

print(f"Headers: {dict(flow.request.headers)}")

357

print(f"Content-Length: {len(flow.request.content)}")

358

359

# Modify URL parameters

360

if flow.request.query:

361

# Add tracking parameter

362

flow.request.query["proxy_time"] = str(int(time.time()))

363

364

# Remove sensitive parameters

365

if "password" in flow.request.query:

366

del flow.request.query["password"]

367

368

# Handle different content types

369

content_type = flow.request.headers.get("content-type", "")

370

371

if "application/x-www-form-urlencoded" in content_type:

372

form_data = flow.request.urlencoded_form()

373

form_data["proxy_processed"] = "true"

374

# Note: Setting form data requires manual encoding

375

376

elif "multipart/form-data" in content_type:

377

form_data = flow.request.multipart_form()

378

print(f"Form fields: {list(form_data.keys())}")

379

380

def response(flow: http.HTTPFlow) -> None:

381

"""Advanced response handling."""

382

# Calculate response time

383

if flow.request.timestamp_start and flow.response.timestamp_end:

384

response_time = flow.response.timestamp_end - flow.request.timestamp_start

385

flow.response.headers["X-Response-Time"] = f"{response_time:.3f}s"

386

387

# Compress responses

388

if len(flow.response.content) > 1024:

389

if "gzip" not in flow.response.headers.get("content-encoding", ""):

390

# Note: Actual compression would require additional logic

391

flow.response.headers["X-Original-Size"] = str(len(flow.response.content))

392

```