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
```