mitmproxy/libmproxy/console/common.py
Aldo Cortesi 08fdd23e23 Refactor the way we display flows.
Use columns to make spacing nicer, and to ensure that long URLs don't bugger up
formatting when they spill into the next line.
2012-02-18 11:11:59 +13:00

169 lines
4.0 KiB
Python

import urwid
from .. import utils
VIEW_BODY_RAW = 0
VIEW_BODY_HEX = 1
VIEW_BODY_PRETTY = 2
BODY_VIEWS = {
VIEW_BODY_RAW: "raw",
VIEW_BODY_HEX: "hex",
VIEW_BODY_PRETTY: "pretty"
}
VIEW_FLOW_REQUEST = 0
VIEW_FLOW_RESPONSE = 1
def highlight_key(s, k):
l = []
parts = s.split(k, 1)
if parts[0]:
l.append(("text", parts[0]))
l.append(("key", k))
if parts[1]:
l.append(("text", parts[1]))
return l
KEY_MAX = 30
def format_keyvals(lst, key="key", val="text", indent=0):
"""
Format a list of (key, value) tuples.
If key is None, it's treated specially:
- We assume a sub-value, and add an extra indent.
- The value is treated as a pre-formatted list of directives.
"""
ret = []
if lst:
maxk = min(max(len(i[0]) for i in lst if i and i[0]), KEY_MAX)
for i, kv in enumerate(lst):
if kv is None:
ret.append(Text(""))
else:
ret.append(
urwid.Columns(
[
("fixed", indent, urwid.Text("")),
(
"fixed",
maxk,
urwid.Text([(key, kv[0] or "")])
),
urwid.Text([(val, kv[1])])
],
dividechars = 2
)
)
return ret
def shortcuts(k):
if k == " ":
k = "page down"
elif k == "j":
k = "down"
elif k == "k":
k = "up"
return k
def fcol(s, attr):
s = str(s)
return (
"fixed",
len(s),
urwid.Text(
[
(attr, s)
]
)
)
def format_flow(f, focus, extended=False, padding=2):
pile = []
req = []
if extended:
req.append(
fcol(
utils.format_timestamp(f.request.timestamp),
"highlight"
)
)
else:
req.append(fcol(">>" if focus else " ", "focus"))
if f.request.is_replay():
req.append(fcol("[replay]", "method"))
req.append(fcol(f.request.method, "method"))
preamble = sum(i[1] for i in req) + len(req) -1
req.append(
urwid.Text([
(
"text" if (f.response or f.error) else "title",
f.request.get_url(),
)
])
)
pile.append(urwid.Columns(req, dividechars=1))
resp = []
resp.append(
("fixed", preamble, urwid.Text(""))
)
if f.response or f.error:
resp.append(fcol("<-", "method"))
if f.response:
if f.response.is_replay():
resp.append("[replay]", "method")
if f.response.code in [200, 304]:
resp.append(fcol(f.response.code, "goodcode"))
else:
resp.append(fcol(f.response.code, "error"))
t = f.response.headers["content-type"]
if t:
t = t[0].split(";")[0]
resp.append(fcol(t, "text"))
if f.response.content:
resp.append(fcol(utils.pretty_size(len(f.response.content)), "text"))
elif f.error:
resp.append(
urwid.Text([
(
"error",
f.error.msg
)
])
)
pile.append(urwid.Columns(resp, dividechars=1))
return urwid.Pile(pile)
def int_version(v):
SIG = 3
v = urwid.__version__.split("-")[0].split(".")
x = 0
for i in range(min(SIG, len(v))):
x += int(v[i]) * 10**(SIG-i)
return x
# We have to do this to be portable over 0.9.8 and 0.9.9 If compatibility
# becomes a pain to maintain, we'll just mandate 0.9.9 or newer.
class WWrap(urwid.WidgetWrap):
if int_version(urwid.__version__) >= 990:
def set_w(self, x):
self._w = x
def get_w(self):
return self._w
w = property(get_w, set_w)