def format_flow(f, focus, extended=False, hostheader=False, max_url_len=False): acked = False if f.reply and f.reply.state == "committed": acked = True d = dict( focus=focus, extended=extended, max_url_len=max_url_len, intercepted = f.intercepted, acked = acked, req_timestamp = f.request.timestamp_start, req_is_replay = f.request.is_replay, req_method = f.request.method, req_url = f.request.pretty_url if hostheader else f.request.url, req_http_version = f.request.http_version, err_msg = f.error.msg if f.error else None, marked = f.marked, ) if f.response: if f.response.raw_content: contentdesc = human.pretty_size(len(f.response.raw_content)) elif f.response.raw_content is None: contentdesc = "[content missing]" else: contentdesc = "[no content]" duration = 0 if f.response.timestamp_end and f.request.timestamp_start: duration = f.response.timestamp_end - f.request.timestamp_start roundtrip = human.pretty_duration(duration) d.update(dict( resp_code = f.response.status_code, resp_reason = f.response.reason, resp_is_replay = f.response.is_replay, resp_clen = contentdesc, roundtrip = roundtrip, )) t = f.response.headers.get("content-type") if t: d["resp_ctype"] = t.split(";")[0] else: d["resp_ctype"] = "" return raw_format_flow(tuple(sorted(d.items())), f)
def format_duration(duration: float) -> typing.Tuple[str, str]: pretty_duration = human.pretty_duration(duration) style = 'gradient_%02d' % int( 99 - 100 * min(math.log2(1 + 1000 * duration) / 12, 0.99)) return pretty_duration, style
def raw_format_table(f): f = dict(f) pile = [] req = [] cursor = [' ', 'focus'] if f['focus']: cursor[0] = '>' req.append(fcol(*cursor)) if f.get('resp_is_replay', False) or f.get('req_is_replay', False): req.append(fcol(SYMBOL_REPLAY, 'replay')) if f['marked']: req.append(fcol(SYMBOL_MARK, 'mark')) if f["two_line"]: req.append( TruncatedText(f["req_url"], colorize_url(f["req_url"]), 'left')) pile.append(urwid.Columns(req, dividechars=1)) req = [] req.append(fcol(' ', 'text')) if f["intercepted"] and not f["acked"]: uc = "intercept" elif "resp_code" in f or f["err_msg"] is not None: uc = "highlight" else: uc = "title" if f["extended"]: s = human.format_timestamp(f["req_timestamp"]) else: s = datetime.datetime.fromtimestamp( time.mktime(time.localtime( f["req_timestamp"]))).strftime("%H:%M:%S") req.append(fcol(s, uc)) methods = { 'GET': 'method_get', 'POST': 'method_post', 'DELETE': 'method_delete', 'HEAD': 'method_head', 'PUT': 'method_put' } uc = methods.get(f["req_method"], "method_other") if f['extended']: req.append(fcol(f["req_method"], uc)) if f["req_promise"]: req.append(fcol('PUSH_PROMISE', 'method_http2_push')) else: if f["req_promise"]: uc = 'method_http2_push' req.append(("fixed", 4, truncated_plain(f["req_method"], uc))) if f["two_line"]: req.append(fcol(f["req_http_version"], 'text')) else: schemes = { 'http': 'scheme_http', 'https': 'scheme_https', } req.append( fcol(fixlen(f["req_scheme"].upper(), 5), schemes.get(f["req_scheme"], "scheme_other"))) req.append(('weight', 0.25, TruncatedText(f["req_host"], colorize_host(f["req_host"]), 'right'))) req.append(('weight', 1.0, TruncatedText(f["req_path"], colorize_req(f["req_path"]), 'left'))) ret = (' ' * len(SYMBOL_RETURN), 'text') status = ('', 'text') content = ('', 'text') size = ('', 'text') duration = ('', 'text') if "resp_code" in f: codes = { 2: "code_200", 3: "code_300", 4: "code_400", 5: "code_500", } ccol = codes.get(f["resp_code"] // 100, "code_other") ret = (SYMBOL_RETURN, ccol) status = (str(f["resp_code"]), ccol) if f["resp_len"] < 0: if f["intercepted"] and f["resp_code"] and not f["acked"]: rc = "intercept" else: rc = "content_none" if f["resp_len"] == -1: contentdesc = "[content missing]" else: contentdesc = "[no content]" content = (contentdesc, rc) else: if f["resp_ctype"]: ctype = f["resp_ctype"].split(";")[0] if ctype.endswith('/javascript'): rc = 'content_script' elif ctype.startswith('text/'): rc = 'content_text' elif (ctype.startswith('image/') or ctype.startswith('video/') or ctype.startswith('font/') or "/x-font-" in ctype): rc = 'content_media' elif ctype.endswith('/json') or ctype.endswith('/xml'): rc = 'content_data' elif ctype.startswith('application/'): rc = 'content_raw' else: rc = 'content_other' content = (ctype, rc) rc = 'gradient_%02d' % int( 99 - 100 * min(math.log2(1 + f["resp_len"]) / 20, 0.99)) size_str = human.pretty_size(f["resp_len"]) if not f['extended']: # shorten to 5 chars max if len(size_str) > 5: size_str = size_str[0:4].rstrip('.') + size_str[-1:] size = (size_str, rc) if f['duration'] is not None: rc = 'gradient_%02d' % int( 99 - 100 * min(math.log2(1 + 1000 * f['duration']) / 12, 0.99)) duration = (human.pretty_duration(f['duration']), rc) elif f["err_msg"]: status = ('Err', 'error') content = f["err_msg"], 'error' if f["two_line"]: req.append(fcol(*ret)) req.append(fcol(fixlen(status[0], 3), status[1])) req.append(('weight', 0.15, truncated_plain(content[0], content[1], 'right'))) if f['extended']: req.append(fcol(*size)) else: req.append(fcol(fixlen_r(size[0], 5), size[1])) req.append(fcol(fixlen_r(duration[0], 5), duration[1])) pile.append(urwid.Columns(req, dividechars=1, min_width=15)) return urwid.Pile(pile)
def raw_format_list(f): f = dict(f) pile = [] req = [] if f["extended"]: req.append( fcol(human.format_timestamp(f["req_timestamp"]), "highlight")) else: req.append(fcol(">>" if f["focus"] else " ", "focus")) if f["marked"]: req.append(fcol(SYMBOL_MARK, "mark")) if f["req_is_replay"]: req.append(fcol(SYMBOL_REPLAY, "replay")) req.append(fcol(f["req_method"], "method")) preamble = sum(i[1] for i in req) + len(req) - 1 if f["intercepted"] and not f["acked"]: uc = "intercept" elif "resp_code" in f or "err_msg" in f: uc = "text" else: uc = "title" url = f["req_url"] if f["cols"] and len(url) > f["cols"]: url = url[:f["cols"]] + "…" if f["req_http_version"] not in ("HTTP/1.0", "HTTP/1.1"): url += " " + f["req_http_version"] req.append(urwid.Text([(uc, url)])) pile.append(urwid.Columns(req, dividechars=1)) resp = [] resp.append(("fixed", preamble, urwid.Text(""))) if "resp_code" in f: codes = { 2: "code_200", 3: "code_300", 4: "code_400", 5: "code_500", } ccol = codes.get(f["resp_code"] // 100, "code_other") resp.append(fcol(SYMBOL_RETURN, ccol)) if f["resp_is_replay"]: resp.append(fcol(SYMBOL_REPLAY, "replay")) resp.append(fcol(f["resp_code"], ccol)) if f["extended"]: resp.append(fcol(f["resp_reason"], ccol)) if f["intercepted"] and f["resp_code"] and not f["acked"]: rc = "intercept" else: rc = "text" if f["resp_ctype"]: resp.append(fcol(f["resp_ctype"], rc)) resp.append(fcol(f["resp_clen"], rc)) pretty_duration = human.pretty_duration(f["duration"]) resp.append(fcol(pretty_duration, rc)) elif f["err_msg"]: resp.append(fcol(SYMBOL_RETURN, "error")) resp.append(urwid.Text([("error", f["err_msg"])])) pile.append(urwid.Columns(resp, dividechars=1)) return urwid.Pile(pile)
def test_pretty_duration(): assert human.pretty_duration(0.00001) == "0ms" assert human.pretty_duration(0.0001) == "0ms" assert human.pretty_duration(0.001) == "1ms" assert human.pretty_duration(0.01) == "10ms" assert human.pretty_duration(0.1) == "100ms" assert human.pretty_duration(1) == "1.00s" assert human.pretty_duration(10) == "10.0s" assert human.pretty_duration(100) == "100s" assert human.pretty_duration(1000) == "1000s" assert human.pretty_duration(10000) == "10000s" assert human.pretty_duration(1.123) == "1.12s" assert human.pretty_duration(0.123) == "123ms"