|
11 | 11 | from .utils import get_safe_text |
12 | 12 |
|
13 | 13 |
|
| 14 | +def _parse_headers(raw: str) -> Dict[str, str]: |
| 15 | + """Parse stored headers into a dict for backward compat. |
| 16 | +
|
| 17 | + Headers are stored as either: |
| 18 | + - list of [key, value] pairs (new format, preserves order) |
| 19 | + - dict (legacy format) |
| 20 | + Returns a dict in both cases. Duplicate keys are collapsed (last wins). |
| 21 | + """ |
| 22 | + parsed = json.loads(raw) |
| 23 | + if isinstance(parsed, list): |
| 24 | + return {k: v for k, v in parsed} |
| 25 | + return parsed |
| 26 | + |
| 27 | + |
14 | 28 | class SimpleRequest: |
15 | 29 | def __init__(self, method: str, url: str, headers: Dict[str, str], body: Optional[str]): |
16 | 30 | self.method = method |
@@ -93,9 +107,21 @@ def save_flow(self, flow: http.HTTPFlow): |
93 | 107 | flow.request.url, |
94 | 108 | flow.request.method, |
95 | 109 | status_code, |
96 | | - json.dumps(dict(flow.request.headers)), |
| 110 | + json.dumps( |
| 111 | + [ |
| 112 | + [k.decode("latin-1"), v.decode("latin-1")] |
| 113 | + for k, v in flow.request.headers.fields |
| 114 | + ], |
| 115 | + ), |
97 | 116 | req_body, |
98 | | - json.dumps(dict(flow.response.headers)) if flow.response else None, |
| 117 | + json.dumps( |
| 118 | + [ |
| 119 | + [k.decode("latin-1"), v.decode("latin-1")] |
| 120 | + for k, v in flow.response.headers.fields |
| 121 | + ], |
| 122 | + ) |
| 123 | + if flow.response |
| 124 | + else None, |
99 | 125 | resp_body, |
100 | 126 | flow.request.timestamp_start, |
101 | 127 | size, |
@@ -125,7 +151,7 @@ def get_summary( |
125 | 151 | for row in rows: |
126 | 152 | content_type = "unknown" |
127 | 153 | if row["response_headers"]: |
128 | | - headers = json.loads(row["response_headers"]) |
| 154 | + headers = _parse_headers(row["response_headers"]) |
129 | 155 | content_type = headers.get( |
130 | 156 | "content-type", |
131 | 157 | headers.get("Content-Type", "unknown"), |
@@ -153,8 +179,8 @@ def get_detail(self, flow_id: str) -> Optional[Dict[str, Any]]: |
153 | 179 | if not row: |
154 | 180 | return None |
155 | 181 |
|
156 | | - req_headers = json.loads(row["request_headers"]) |
157 | | - resp_headers = json.loads(row["response_headers"]) if row["response_headers"] else None |
| 182 | + req_headers = _parse_headers(row["request_headers"]) |
| 183 | + resp_headers = _parse_headers(row["response_headers"]) if row["response_headers"] else None |
158 | 184 |
|
159 | 185 | simple_request = SimpleRequest( |
160 | 186 | method=row["method"], |
@@ -234,12 +260,12 @@ def get_all_for_analysis(self, limit: int = 1000) -> List[Dict[str, Any]]: |
234 | 260 | "request": { |
235 | 261 | "url": row["url"], |
236 | 262 | "method": row["method"], |
237 | | - "headers": json.loads(row["request_headers"]), |
| 263 | + "headers": _parse_headers(row["request_headers"]), |
238 | 264 | "body": row["request_body"], |
239 | 265 | }, |
240 | 266 | "response": { |
241 | 267 | "status_code": row["status_code"], |
242 | | - "headers": json.loads(row["response_headers"]) |
| 268 | + "headers": _parse_headers(row["response_headers"]) |
243 | 269 | if row["response_headers"] |
244 | 270 | else {}, |
245 | 271 | "body": row["response_body"], |
@@ -269,12 +295,12 @@ def get_by_ids(self, flow_ids: List[str]) -> List[Dict[str, Any]]: |
269 | 295 | "request": { |
270 | 296 | "url": row["url"], |
271 | 297 | "method": row["method"], |
272 | | - "headers": json.loads(row["request_headers"]), |
| 298 | + "headers": _parse_headers(row["request_headers"]), |
273 | 299 | "body": row["request_body"], |
274 | 300 | }, |
275 | 301 | "response": { |
276 | 302 | "status_code": row["status_code"], |
277 | | - "headers": json.loads(row["response_headers"]) |
| 303 | + "headers": _parse_headers(row["response_headers"]) |
278 | 304 | if row["response_headers"] |
279 | 305 | else {}, |
280 | 306 | "body": row["response_body"], |
@@ -315,7 +341,7 @@ def get_flow_object(self, flow_id: str) -> Optional[SimpleRequest]: |
315 | 341 | if not row: |
316 | 342 | return None |
317 | 343 |
|
318 | | - headers = json.loads(row["request_headers"]) |
| 344 | + headers = _parse_headers(row["request_headers"]) |
319 | 345 | return SimpleRequest( |
320 | 346 | method=row["method"], |
321 | 347 | url=row["url"], |
|
0 commit comments