Permalink
Browse files

Move export to addon, kill Python and Locust export

Also add a "raw" export format.

The Python and Locust exports are hard to maintain, their tests are extremely
brittle, they didn't have full test coverage, and are by my guess very rarely
used. I feel the Locust export should certainly be an externally maintained
addon. The Python/requests export can come back if someone cares enough, and it
can be structured in a way we can maintain.
  • Loading branch information...
cortesi committed Apr 30, 2017
1 parent befbe88 commit bcbe87bb0986819c83c3e2efc683194bbf9c6c50
@@ -7,6 +7,7 @@
from mitmproxy.addons import core
from mitmproxy.addons import cut
from mitmproxy.addons import disable_h2c
from mitmproxy.addons import export
from mitmproxy.addons import onboarding
from mitmproxy.addons import proxyauth
from mitmproxy.addons import replace
@@ -31,6 +32,7 @@ def default_addons():
clientplayback.ClientPlayback(),
cut.Cut(),
disable_h2c.DisableH2C(),
export.Export(),
onboarding.Onboarding(),
proxyauth.ProxyAuth(),
replace.Replace(),
@@ -0,0 +1,75 @@
import typing

from mitmproxy import command
from mitmproxy import flow
from mitmproxy import exceptions
from mitmproxy.utils import strutils
from mitmproxy.net.http.http1 import assemble

import pyperclip


def curl_command(f: flow.Flow) -> str:
if not hasattr(f, "request"):
raise exceptions.CommandError("Can't export flow with no request.")
data = "curl "
request = f.request.copy() # type: ignore
request.decode(strict=False)
for k, v in request.headers.items(multi=True):
data += "-H '%s:%s' " % (k, v)
if request.method != "GET":
data += "-X %s " % request.method
data += "'%s'" % request.url
if request.content:
data += " --data-binary '%s'" % strutils.bytes_to_escaped_str(
request.content,
escape_single_quotes=True
)
return data


def raw(f: flow.Flow) -> bytes:
if not hasattr(f, "request"):
raise exceptions.CommandError("Can't export flow with no request.")
return assemble.assemble_request(f.request) # type: ignore


formats = dict(
curl = curl_command,
raw = raw,
)


class Export():
@command.command("export.formats")
def formats(self) -> typing.Sequence[str]:
"""
Return a list of the supported export formats.
"""
return list(sorted(formats.keys()))

@command.command("export.file")
def file(self, fmt: str, f: flow.Flow, path: str) -> None:
"""
Export a flow to path.
"""
if fmt not in formats:
raise exceptions.CommandError("No such export format: %s" % fmt)
func = formats[fmt] # type: typing.Any
v = func(f)
with open(path, "wb") as fp:
if isinstance(v, bytes):
fp.write(v)
else:
fp.write(v.encode("utf-8"))

@command.command("export.clip")
def clip(self, fmt: str, f: flow.Flow) -> None:
"""
Export a flow to the system clipboard.
"""
if fmt not in formats:
raise exceptions.CommandError("No such export format: %s" % fmt)
func = formats[fmt] # type: typing.Any
v = strutils.always_str(func(f))
pyperclip.copy(v)
@@ -24,6 +24,8 @@ def typename(t: type, ret: bool) -> str:
return t.__name__
elif t == typing.Sequence[flow.Flow]:
return "[flow]" if ret else "flowspec"
elif t == typing.Sequence[str]:
return "[str]"
elif t == Cuts:
return "[cuts]" if ret else "cutspec"
elif t == flow.Flow:

This file was deleted.

Oops, something went wrong.
@@ -1,6 +1,8 @@
import typing
import urwid

from mitmproxy import exceptions
from mitmproxy import flow
from mitmproxy.tools.console import signals


@@ -23,5 +25,14 @@ def __call__(self, cmd):
except exceptions.CommandError as v:
signals.status_message.send(message=str(v))
else:
if type(ret) == str:
signals.status_message.send(message=ret)
if ret:
if type(ret) == typing.Sequence[flow.Flow]:
signals.status_message.send(
message="Command returned %s flows" % len(ret)
)
elif len(str(ret)) < 50:
signals.status_message.send(message=str(ret))
else:
signals.status_message.send(
message="Command returned too much data to display."
)
@@ -9,7 +9,6 @@
import mitmproxy.net
from functools import lru_cache
from mitmproxy.tools.console import signals
from mitmproxy import export
from mitmproxy.utils import human

try:
@@ -306,28 +305,6 @@ def ask_save_body(scope, flow):
signals.status_message.send(message="No content.")


def export_to_clip_or_file(key, scope, flow, writer):
"""
Export selected flow to clipboard or a file.
key: _c_ontent, _h_eaders+content, _u_rl,
cu_r_l_command, _p_ython_code,
_l_ocust_code, locust_t_ask
scope: None, _a_ll, re_q_uest, re_s_ponse
writer: copy_to_clipboard_or_prompt, ask_save_path
"""

for _, exp_key, exporter in export.EXPORTERS:
if key == exp_key:
if exporter is None: # 'c' & 'h'
if scope is None:
ask_scope_and_callback(flow, handle_flow_data, key, writer)
else:
handle_flow_data(scope, flow, key, writer)
else: # other keys
writer(exporter(flow))


@lru_cache(maxsize=800)
def raw_format_flow(f, flow):
f = dict(f)
@@ -2,8 +2,8 @@

from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals
from mitmproxy.tools.console import master
from mitmproxy.addons import view
from mitmproxy import export
import mitmproxy.tools.console.master # noqa


@@ -140,25 +140,7 @@ def mouse_event(self, size, event, button, col, row, focus):

def keypress(self, xxx_todo_changeme, key):
(maxcol,) = xxx_todo_changeme
key = common.shortcuts(key)
if key == "E":
signals.status_prompt_onekey.send(
self,
prompt = "Export to file",
keys = [(e[0], e[1]) for e in export.EXPORTERS],
callback = common.export_to_clip_or_file,
args = (None, self.flow, common.ask_save_path)
)
# elif key == "C":
# signals.status_prompt_onekey.send(
# self,
# prompt = "Export to clipboard",
# keys = [(e[0], e[1]) for e in export.EXPORTERS],
# callback = common.export_to_clip_or_file,
# args = (None, self.flow, common.copy_to_clipboard_or_prompt)
# )
else:
return key
return common.shortcuts(key)


class FlowListWalker(urwid.ListWalker):
@@ -203,9 +185,7 @@ def get_prev(self, pos):

class FlowListBox(urwid.ListBox):

def __init__(
self, master: "mitmproxy.tools.console.master.ConsoleMaster"
) -> None:
def __init__(self, master: master.ConsoleMaster) -> None:
self.master = master # type: "mitmproxy.tools.console.master.ConsoleMaster"
super().__init__(FlowListWalker(master))

Oops, something went wrong.

0 comments on commit bcbe87b

Please sign in to comment.