47 lines
1.5 KiB
Python
47 lines
1.5 KiB
Python
"""Read mitmproxy flow file, print unique endpoints by host/method/path."""
|
|
import sys, collections
|
|
from mitmproxy import io as miio
|
|
from mitmproxy.exceptions import FlowReadException
|
|
|
|
flow_file = sys.argv[1]
|
|
filter_host = sys.argv[2] if len(sys.argv) > 2 else None
|
|
|
|
stats = collections.Counter()
|
|
endpoints = collections.defaultdict(set)
|
|
hosts = collections.Counter()
|
|
status_codes = collections.Counter()
|
|
|
|
with open(flow_file, "rb") as f:
|
|
reader = miio.FlowReader(f)
|
|
try:
|
|
for flow in reader.stream():
|
|
if not hasattr(flow, "request"):
|
|
continue
|
|
req = flow.request
|
|
host = req.pretty_host
|
|
if filter_host and filter_host not in host:
|
|
continue
|
|
hosts[host] += 1
|
|
key = (req.method, req.path.split("?")[0])
|
|
endpoints[host].add(key)
|
|
stats[(req.method, host, req.path.split("?")[0])] += 1
|
|
if flow.response:
|
|
status_codes[flow.response.status_code] += 1
|
|
except FlowReadException as e:
|
|
print(f"[warn] flow truncated: {e}", file=sys.stderr)
|
|
|
|
print("=== Hosts ===")
|
|
for h, c in hosts.most_common():
|
|
print(f" {c:5d} {h}")
|
|
print()
|
|
print("=== Endpoints grouped by host ===")
|
|
for h in sorted(endpoints.keys()):
|
|
print(f"\n--- {h} ---")
|
|
for method, path in sorted(endpoints[h]):
|
|
count = stats[(method, h, path)]
|
|
print(f" [{count:3d}x] {method:6s} {path}")
|
|
print()
|
|
print("=== Status codes ===")
|
|
for code, c in status_codes.most_common():
|
|
print(f" {code}: {c}")
|