Exemple #1
0
def format_flow(f,
                focus,
                extended=False,
                hostheader=False,
                cols=False,
                layout='default'):
    acked = False
    if f.reply and f.reply.state == "committed":
        acked = True
    d = dict(
        focus=focus,
        extended=extended,
        two_line=extended or cols < 100,
        cols=cols,
        intercepted=f.intercepted,
        acked=acked,
        req_timestamp=f.request.timestamp_start,
        req_is_replay=f.request.is_replay,
        req_method=f.request.method,
        req_promise='h2-pushed-stream' in f.metadata,
        req_url=f.request.pretty_url if hostheader else f.request.url,
        req_scheme=f.request.scheme,
        req_host=f.request.pretty_host if hostheader else f.request.host,
        req_path=f.request.path,
        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:
            content_len = len(f.response.raw_content)
            contentdesc = human.pretty_size(len(f.response.raw_content))
        elif f.response.raw_content is None:
            content_len = -1
            contentdesc = "[content missing]"
        else:
            content_len = -2
            contentdesc = "[no content]"

        duration = None
        if f.response.timestamp_end and f.request.timestamp_start:
            duration = max(
                [f.response.timestamp_end - f.request.timestamp_start, 0])

        d.update(
            dict(
                resp_code=f.response.status_code,
                resp_reason=f.response.reason,
                resp_is_replay=f.response.is_replay,
                resp_len=content_len,
                resp_ctype=f.response.headers.get("content-type"),
                resp_clen=contentdesc,
                duration=duration,
            ))

    if ((layout == 'default' and cols < 100) or layout == "list"):
        return raw_format_list(tuple(sorted(d.items())))
    else:
        return raw_format_table(tuple(sorted(d.items())))
Exemple #2
0
 def __repr__(self) -> str:
     if self.raw_content:
         ct = self.headers.get("content-type", "unknown content type")
         size = human.pretty_size(len(self.raw_content))
         details = f"{ct}, {size}"
     else:
         details = "no content"
     return f"Response({self.status_code}, {details})"
Exemple #3
0
    def _echo_response_line(self, flow: http.HTTPFlow) -> None:
        if flow.is_replay == "response":
            replay_str = "[replay]"
            replay = self.style(replay_str, fg="yellow", bold=True)
        else:
            replay_str = ""
            replay = ""

        assert flow.response
        code_int = flow.response.status_code
        code_color = None
        if 200 <= code_int < 300:
            code_color = "green"
        elif 300 <= code_int < 400:
            code_color = "magenta"
        elif 400 <= code_int < 600:
            code_color = "red"
        code = self.style(
            str(code_int),
            fg=code_color,
            bold=True,
            blink=(code_int == 418),
        )

        if not flow.response.is_http2:
            reason = flow.response.reason
        else:
            reason = http.status_codes.RESPONSES.get(flow.response.status_code, "")
        reason = self.style(
            strutils.escape_control_characters(reason),
            fg=code_color,
            bold=True
        )

        if flow.response.raw_content is None:
            size = "(content missing)"
        else:
            size = human.pretty_size(len(flow.response.raw_content))
        size = self.style(size, bold=True)

        http_version = ""
        if (
            not (flow.response.is_http10 or flow.response.is_http11)
            or flow.request.http_version != flow.response.http_version
        ):
            # Hide version for h1 <-> h1 connections.
            http_version = f"{flow.response.http_version} "

        arrows = self.style(" <<", bold=True)
        if ctx.options.flow_detail == 1:
            # This aligns the HTTP response code with the HTTP request method:
            # 127.0.0.1:59519: GET http://example.com/
            #               << 304 Not Modified 0b
            pad = max(0,
                      len(human.format_address(flow.client_conn.peername)) - (2 + len(http_version) + len(replay_str)))
            arrows = " " * pad + arrows

        self.echo(f"{replay}{arrows} {http_version}{code} {reason} {size}")
Exemple #4
0
 def __repr__(self):
     if self.raw_content:
         details = "{}, {}".format(
             self.headers.get("content-type", "unknown content type"),
             human.pretty_size(len(self.raw_content)))
     else:
         details = "no content"
     return "Response({status_code} {reason}, {details})".format(
         status_code=self.status_code, reason=self.reason, details=details)
Exemple #5
0
def test_pretty_size():
    assert human.pretty_size(0) == "0b"
    assert human.pretty_size(100) == "100b"
    assert human.pretty_size(1024) == "1.0k"
    assert human.pretty_size(1024 + 512) == "1.5k"
    assert human.pretty_size(1024 * 1024) == "1.0m"
    assert human.pretty_size(10 * 1024 * 1024) == "10.0m"
    assert human.pretty_size(100 * 1024 * 1024) == "100m"
Exemple #6
0
 def detail(self, flow):
     if flow.response.raw_content:
         details = "{}, {}".format(
             flow.response.headers.get("content-type",
                                       "unknown content type"),
             human.pretty_size(len(flow.response.raw_content)))
     else:
         details = "no content"
     return "Response({status_code} {reason}, {details})".format(
         status_code=flow.response.status_code,
         reason=flow.response.reason,
         details=details)
Exemple #7
0
def test_pretty_size():
    assert human.pretty_size(0) == "0b"
    assert human.pretty_size(100) == "100b"
    assert human.pretty_size(1024) == "1k"
    assert human.pretty_size(1024 + (1024 / 2.0)) == "1.5k"
    assert human.pretty_size(1024 * 1024) == "1m"
    assert human.pretty_size(10 * 1024 * 1024) == "10m"
Exemple #8
0
def test_pretty_size():
    assert human.pretty_size(0) == "0b"
    assert human.pretty_size(100) == "100b"
    assert human.pretty_size(1024) == "1k"
    assert human.pretty_size(1024 + (1024 / 2.0)) == "1.5k"
    assert human.pretty_size(1024 * 1024) == "1m"
    assert human.pretty_size(10 * 1024 * 1024) == "10m"
Exemple #9
0
 def __repr__(self):
     if self.raw_content:
         details = "{}, {}".format(
             self.headers.get("content-type", "unknown content type"),
             human.pretty_size(len(self.raw_content))
         )
     else:
         details = "no content"
     return "Response({status_code} {reason}, {details})".format(
         status_code=self.status_code,
         reason=self.reason,
         details=details
     )
Exemple #10
0
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 __repr__(self):
     vals = [
         "ws frame:",
         OPCODE.get_name(self.opcode, hex(self.opcode)).lower()
     ]
     flags = []
     for i in ["fin", "rsv1", "rsv2", "rsv3", "mask"]:
         if getattr(self, i):
             flags.append(i)
     if flags:
         vals.extend([":", "|".join(flags)])
     if self.masking_key:
         vals.append(":key=%s" % repr(self.masking_key))
     if self.payload_length:
         vals.append(" %s" % human.pretty_size(self.payload_length))
     return "".join(vals)
Exemple #12
0
    def _echo_response_line(self, flow):
        if flow.response.is_replay:
            replay = click.style("[replay] ", fg="yellow", bold=True)
        else:
            replay = ""

        code = flow.response.status_code
        code_color = None
        if 200 <= code < 300:
            code_color = "green"
        elif 300 <= code < 400:
            code_color = "magenta"
        elif 400 <= code < 600:
            code_color = "red"
        code = click.style(
            str(code),
            fg=code_color,
            bold=True,
            blink=(code == 418)
        )
        reason = click.style(
            strutils.escape_control_characters(flow.response.reason),
            fg=code_color,
            bold=True
        )

        if flow.response.raw_content is None:
            size = "(content missing)"
        else:
            size = human.pretty_size(len(flow.response.raw_content))
        size = click.style(size, bold=True)

        arrows = click.style(" <<", bold=True)
        if self.flow_detail == 1:
            # This aligns the HTTP response code with the HTTP request method:
            # 127.0.0.1:59519: GET http://example.com/
            #               << 304 Not Modified 0b
            arrows = " " * (len(repr(flow.client_conn.address)) - 2) + arrows

        line = "{replay}{arrows} {code} {reason} {size}".format(
            replay=replay,
            arrows=arrows,
            code=code,
            reason=reason,
            size=size
        )
        self.echo(line)
Exemple #13
0
    def get_status(self):
        r = []

        sreplay = self.master.addons.get("serverplayback")
        creplay = self.master.addons.get("clientplayback")

        if len(self.master.options.setheaders):
            r.append("[")
            r.append(("heading_key", "H"))
            r.append("eaders]")
        if len(self.master.options.replacements):
            r.append("[")
            r.append(("heading_key", "R"))
            r.append("eplacing]")
        if creplay.count():
            r.append("[")
            r.append(("heading_key", "cplayback"))
            r.append(":%s]" % creplay.count())
        if sreplay.count():
            r.append("[")
            r.append(("heading_key", "splayback"))
            r.append(":%s]" % sreplay.count())
        if self.master.options.ignore_hosts:
            r.append("[")
            r.append(("heading_key", "I"))
            r.append("gnore:%d]" % len(self.master.options.ignore_hosts))
        if self.master.options.tcp_hosts:
            r.append("[")
            r.append(("heading_key", "T"))
            r.append("CP:%d]" % len(self.master.options.tcp_hosts))
        if self.master.options.intercept:
            r.append("[")
            r.append(("heading_key", "i"))
            r.append(":%s]" % self.master.options.intercept)
        if self.master.options.filter:
            r.append("[")
            r.append(("heading_key", "f"))
            r.append(":%s]" % self.master.options.filter)
        if self.master.options.stickycookie:
            r.append("[")
            r.append(("heading_key", "t"))
            r.append(":%s]" % self.master.options.stickycookie)
        if self.master.options.stickyauth:
            r.append("[")
            r.append(("heading_key", "u"))
            r.append(":%s]" % self.master.options.stickyauth)
        if self.master.options.default_contentview != "auto":
            r.append("[")
            r.append(("heading_key", "M"))
            r.append(":%s]" % self.master.options.default_contentview)
        if self.master.options.console_order:
            r.append("[")
            r.append(("heading_key", "o"))
            r.append(":%s]" % self.master.options.console_order)

        opts = []
        if self.master.options.anticache:
            opts.append("anticache")
        if self.master.options.anticomp:
            opts.append("anticomp")
        if self.master.options.showhost:
            opts.append("showhost")
        if not self.master.options.refresh_server_playback:
            opts.append("norefresh")
        if self.master.options.replay_kill_extra:
            opts.append("killextra")
        if self.master.options.no_upstream_cert:
            opts.append("no-upstream-cert")
        if self.master.options.console_focus_follow:
            opts.append("following")
        if self.master.options.stream_large_bodies:
            opts.append(
                "stream:%s" %
                human.pretty_size(self.master.options.stream_large_bodies))

        if opts:
            r.append("[%s]" % (":".join(opts)))

        if self.master.options.mode in ["reverse", "upstream"]:
            dst = self.master.server.config.upstream_server
            r.append("[dest:%s]" % mitmproxy.net.http.url.unparse(
                dst.scheme, dst.address.host, dst.address.port))
        if self.master.options.scripts:
            r.append("[")
            r.append(("heading_key", "s"))
            r.append("cripts:%s]" % len(self.master.options.scripts))

        if self.master.options.streamfile:
            r.append("[W:%s]" % self.master.options.streamfile)

        return r
Exemple #14
0
    def get_status(self):
        r = []

        sreplay = self.master.addons.get("serverplayback")
        creplay = self.master.addons.get("clientplayback")

        if len(self.master.options.setheaders):
            r.append("[")
            r.append(("heading_key", "H"))
            r.append("eaders]")
        if len(self.master.options.replacements):
            r.append("[")
            r.append(("heading_key", "R"))
            r.append("eplacing]")
        if creplay.count():
            r.append("[")
            r.append(("heading_key", "cplayback"))
            r.append(":%s]" % creplay.count())
        if sreplay.count():
            r.append("[")
            r.append(("heading_key", "splayback"))
            r.append(":%s]" % sreplay.count())
        if self.master.options.ignore_hosts:
            r.append("[")
            r.append(("heading_key", "I"))
            r.append("gnore:%d]" % len(self.master.options.ignore_hosts))
        if self.master.options.tcp_hosts:
            r.append("[")
            r.append(("heading_key", "T"))
            r.append("CP:%d]" % len(self.master.options.tcp_hosts))
        if self.master.options.intercept:
            r.append("[")
            r.append(("heading_key", "i"))
            r.append(":%s]" % self.master.options.intercept)
        if self.master.options.filter:
            r.append("[")
            r.append(("heading_key", "f"))
            r.append(":%s]" % self.master.options.filter)
        if self.master.options.stickycookie:
            r.append("[")
            r.append(("heading_key", "t"))
            r.append(":%s]" % self.master.options.stickycookie)
        if self.master.options.stickyauth:
            r.append("[")
            r.append(("heading_key", "u"))
            r.append(":%s]" % self.master.options.stickyauth)
        if self.master.options.default_contentview != "auto":
            r.append("[")
            r.append(("heading_key", "M"))
            r.append(":%s]" % self.master.options.default_contentview)
        if self.master.options.order:
            r.append("[")
            r.append(("heading_key", "o"))
            r.append(":%s]" % self.master.options.order)

        opts = []
        if self.master.options.anticache:
            opts.append("anticache")
        if self.master.options.anticomp:
            opts.append("anticomp")
        if self.master.options.showhost:
            opts.append("showhost")
        if not self.master.options.refresh_server_playback:
            opts.append("norefresh")
        if self.master.options.replay_kill_extra:
            opts.append("killextra")
        if self.master.options.no_upstream_cert:
            opts.append("no-upstream-cert")
        if self.master.options.focus_follow:
            opts.append("following")
        if self.master.options.stream_large_bodies:
            opts.append(
                "stream:%s" % human.pretty_size(
                    self.master.options.stream_large_bodies
                )
            )

        if opts:
            r.append("[%s]" % (":".join(opts)))

        if self.master.options.mode in ["reverse", "upstream"]:
            dst = self.master.server.config.upstream_server
            r.append("[dest:%s]" % mitmproxy.net.http.url.unparse(
                dst.scheme,
                dst.address.host,
                dst.address.port
            ))
        if self.master.options.scripts:
            r.append("[")
            r.append(("heading_key", "s"))
            r.append("cripts:%s]" % len(self.master.options.scripts))

        if self.master.options.streamfile:
            r.append("[W:%s]" % self.master.options.streamfile)

        return r
Exemple #15
0
def format_size(num_bytes: int) -> typing.Tuple[str, str]:
    pretty_size = human.pretty_size(num_bytes)
    style = 'gradient_%02d' % int(99 - 100 *
                                  min(math.log2(1 + num_bytes) / 20, 0.99))
    return pretty_size, style
Exemple #16
0
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)