|
14 | 14 | from .utils import get_safe_text |
15 | 15 |
|
16 | 16 |
|
| 17 | +def _parse_headers(raw: str) -> Dict[str, str]: |
| 18 | + """Parse stored headers into a dict for backward compat. |
| 19 | +
|
| 20 | + Headers are stored as either: |
| 21 | + - list of [key, value] pairs (new format, preserves order) |
| 22 | + - dict (legacy format) |
| 23 | + Returns a dict in both cases. Duplicate keys are collapsed (last wins). |
| 24 | + """ |
| 25 | + parsed = json.loads(raw) |
| 26 | + if isinstance(parsed, list): |
| 27 | + return {k: v for k, v in parsed} |
| 28 | + return parsed |
| 29 | + |
| 30 | + |
17 | 31 | class SimpleRequest: |
18 | 32 | def __init__(self, method: str, url: str, headers: Dict[str, str], body: Optional[str]): |
19 | 33 | self.method = method |
@@ -96,9 +110,21 @@ def save_flow(self, flow: http.HTTPFlow): |
96 | 110 | flow.request.url, |
97 | 111 | flow.request.method, |
98 | 112 | status_code, |
99 | | - json.dumps(dict(flow.request.headers)), |
| 113 | + json.dumps( |
| 114 | + [ |
| 115 | + [k.decode("latin-1"), v.decode("latin-1")] |
| 116 | + for k, v in flow.request.headers.fields |
| 117 | + ], |
| 118 | + ), |
100 | 119 | req_body, |
101 | | - json.dumps(dict(flow.response.headers)) if flow.response else None, |
| 120 | + json.dumps( |
| 121 | + [ |
| 122 | + [k.decode("latin-1"), v.decode("latin-1")] |
| 123 | + for k, v in flow.response.headers.fields |
| 124 | + ], |
| 125 | + ) |
| 126 | + if flow.response |
| 127 | + else None, |
102 | 128 | resp_body, |
103 | 129 | flow.request.timestamp_start, |
104 | 130 | size, |
@@ -128,7 +154,7 @@ def get_summary( |
128 | 154 | for row in rows: |
129 | 155 | content_type = "unknown" |
130 | 156 | if row["response_headers"]: |
131 | | - headers = json.loads(row["response_headers"]) |
| 157 | + headers = _parse_headers(row["response_headers"]) |
132 | 158 | content_type = headers.get( |
133 | 159 | "content-type", |
134 | 160 | headers.get("Content-Type", "unknown"), |
@@ -156,8 +182,8 @@ def get_detail(self, flow_id: str) -> Optional[Dict[str, Any]]: |
156 | 182 | if not row: |
157 | 183 | return None |
158 | 184 |
|
159 | | - req_headers = json.loads(row["request_headers"]) |
160 | | - resp_headers = json.loads(row["response_headers"]) if row["response_headers"] else None |
| 185 | + req_headers = _parse_headers(row["request_headers"]) |
| 186 | + resp_headers = _parse_headers(row["response_headers"]) if row["response_headers"] else None |
161 | 187 |
|
162 | 188 | simple_request = SimpleRequest( |
163 | 189 | method=row["method"], |
@@ -237,12 +263,12 @@ def get_all_for_analysis(self, limit: int = 1000) -> List[Dict[str, Any]]: |
237 | 263 | "request": { |
238 | 264 | "url": row["url"], |
239 | 265 | "method": row["method"], |
240 | | - "headers": json.loads(row["request_headers"]), |
| 266 | + "headers": _parse_headers(row["request_headers"]), |
241 | 267 | "body": row["request_body"], |
242 | 268 | }, |
243 | 269 | "response": { |
244 | 270 | "status_code": row["status_code"], |
245 | | - "headers": json.loads(row["response_headers"]) |
| 271 | + "headers": _parse_headers(row["response_headers"]) |
246 | 272 | if row["response_headers"] |
247 | 273 | else {}, |
248 | 274 | "body": row["response_body"], |
@@ -272,12 +298,12 @@ def get_by_ids(self, flow_ids: List[str]) -> List[Dict[str, Any]]: |
272 | 298 | "request": { |
273 | 299 | "url": row["url"], |
274 | 300 | "method": row["method"], |
275 | | - "headers": json.loads(row["request_headers"]), |
| 301 | + "headers": _parse_headers(row["request_headers"]), |
276 | 302 | "body": row["request_body"], |
277 | 303 | }, |
278 | 304 | "response": { |
279 | 305 | "status_code": row["status_code"], |
280 | | - "headers": json.loads(row["response_headers"]) |
| 306 | + "headers": _parse_headers(row["response_headers"]) |
281 | 307 | if row["response_headers"] |
282 | 308 | else {}, |
283 | 309 | "body": row["response_body"], |
@@ -376,7 +402,7 @@ def get_flow_object(self, flow_id: str) -> Optional[SimpleRequest]: |
376 | 402 | if not row: |
377 | 403 | return None |
378 | 404 |
|
379 | | - headers = json.loads(row["request_headers"]) |
| 405 | + headers = _parse_headers(row["request_headers"]) |
380 | 406 | return SimpleRequest( |
381 | 407 | method=row["method"], |
382 | 408 | url=row["url"], |
|
0 commit comments