Merge pull request #2297 from cortesi/flowcmd

commands: view.order.options, view.marked.toggle, view.create
This commit is contained in:
Aldo Cortesi 2017-05-01 00:02:15 +12:00 committed by GitHub
commit 29ce5a83d2
7 changed files with 52 additions and 91 deletions

View File

@ -19,6 +19,7 @@ import mitmproxy.flow
from mitmproxy import flowfilter from mitmproxy import flowfilter
from mitmproxy import exceptions from mitmproxy import exceptions
from mitmproxy import command from mitmproxy import command
from mitmproxy import connections
from mitmproxy import ctx from mitmproxy import ctx
from mitmproxy import io from mitmproxy import io
from mitmproxy import http # noqa from mitmproxy import http # noqa
@ -201,7 +202,18 @@ class View(collections.Sequence):
self.sig_view_refresh.send(self) self.sig_view_refresh.send(self)
# API # API
def toggle_marked(self): @command.command("view.order.options")
def order_options(self) -> typing.Sequence[str]:
"""
A list of all the orders we support.
"""
return list(sorted(self.orders.keys()))
@command.command("view.marked.toggle")
def toggle_marked(self) -> None:
"""
Toggle whether to show marked views only.
"""
self.show_marked = not self.show_marked self.show_marked = not self.show_marked
self._refilter() self._refilter()
@ -341,6 +353,16 @@ class View(collections.Sequence):
raise exceptions.CommandError("Invalid flow filter: %s" % spec) raise exceptions.CommandError("Invalid flow filter: %s" % spec)
return [i for i in self._store.values() if filt(i)] return [i for i in self._store.values() if filt(i)]
@command.command("view.create")
def create(self, method: str, url: str) -> None:
req = http.HTTPRequest.make(method.upper(), url)
c = connections.ClientConnection.make_dummy(("", 0))
s = connections.ServerConnection.make_dummy((req.host, req.port))
f = http.HTTPFlow(c, s)
f.request = req
f.request.headers["Host"] = req.host
self.add([f])
# Event handlers # Event handlers
def configure(self, updated): def configure(self, updated):
if "view_filter" in updated: if "view_filter" in updated:

View File

@ -7,7 +7,6 @@ from mitmproxy import options
from mitmproxy import controller from mitmproxy import controller
from mitmproxy import eventsequence from mitmproxy import eventsequence
from mitmproxy import exceptions from mitmproxy import exceptions
from mitmproxy import connections
from mitmproxy import command from mitmproxy import command
from mitmproxy import http from mitmproxy import http
from mitmproxy import log from mitmproxy import log
@ -78,9 +77,6 @@ class Master:
self.start() self.start()
try: try:
while not self.should_exit.is_set(): while not self.should_exit.is_set():
# Don't choose a very small timeout in Python 2:
# https://github.com/mitmproxy/mitmproxy/issues/443
# TODO: Lower the timeout value if we move to Python 3.
self.tick(0.1) self.tick(0.1)
finally: finally:
self.shutdown() self.shutdown()
@ -109,22 +105,6 @@ class Master:
self.should_exit.set() self.should_exit.set()
self.addons.trigger("done") self.addons.trigger("done")
def create_request(self, method, url):
"""
Create a new artificial and minimalist request also adds it to flowlist.
Raises:
ValueError, if the url is malformed.
"""
req = http.HTTPRequest.make(method, url)
c = connections.ClientConnection.make_dummy(("", 0))
s = connections.ServerConnection.make_dummy((req.host, req.port))
f = http.HTTPFlow(c, s)
f.request = req
self.load_flow(f)
return f
def load_flow(self, f): def load_flow(self, f):
""" """
Loads a flow Loads a flow

View File

@ -2,7 +2,6 @@ import urwid
from mitmproxy.tools.console import common from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals from mitmproxy.tools.console import signals
from mitmproxy.addons import view
import mitmproxy.tools.console.master # noqa import mitmproxy.tools.console.master # noqa
@ -190,62 +189,6 @@ class FlowListBox(urwid.ListBox):
self.master = master # type: "mitmproxy.tools.console.master.ConsoleMaster" self.master = master # type: "mitmproxy.tools.console.master.ConsoleMaster"
super().__init__(FlowListWalker(master)) super().__init__(FlowListWalker(master))
def get_method_raw(self, k):
if k:
self.get_url(k)
def get_method(self, k):
if k == "e":
signals.status_prompt.send(
self,
prompt = "Method",
text = "",
callback = self.get_method_raw
)
else:
method = ""
for i in common.METHOD_OPTIONS:
if i[1] == k:
method = i[0].upper()
self.get_url(method)
def get_url(self, method):
signals.status_prompt.send(
prompt = "URL",
text = "http://www.example.com/",
callback = self.new_request,
args = (method,)
)
def new_request(self, url, method):
try:
f = self.master.create_request(method, url)
except ValueError as e:
signals.status_message.send(message = "Invalid URL: " + str(e))
return
self.master.view.focus.flow = f
def keypress(self, size, key): def keypress(self, size, key):
key = common.shortcuts(key) key = common.shortcuts(key)
if key == "M":
self.master.view.toggle_marked()
elif key == "n":
signals.status_prompt_onekey.send(
prompt = "Method",
keys = common.METHOD_OPTIONS,
callback = self.get_method
)
elif key == "o":
orders = [(i[1], i[0]) for i in view.orders]
lookup = dict([(i[0], i[1]) for i in view.orders])
def change_order(k):
self.master.options.console_order = lookup[k]
signals.status_prompt_onekey.send(
prompt = "Order",
keys = orders,
callback = change_order
)
else:
return urwid.ListBox.keypress(self, size, key) return urwid.ListBox.keypress(self, size, key)

View File

@ -189,6 +189,18 @@ def default_keymap(km):
km.add("l", "console.command cut.clip ", context="flowlist") km.add("l", "console.command cut.clip ", context="flowlist")
km.add("L", "console.command view.load ", context="flowlist") km.add("L", "console.command view.load ", context="flowlist")
km.add("m", "flow.mark.toggle @focus", context="flowlist") km.add("m", "flow.mark.toggle @focus", context="flowlist")
km.add("M", "view.marked.toggle", context="flowlist")
km.add(
"n",
"console.command view.create get https://google.com",
context="flowlist"
)
km.add(
"o",
"console.choose Order view.order.options "
"set console_order={choice}",
context="flowlist"
)
km.add("r", "replay.client @focus", context="flowlist") km.add("r", "replay.client @focus", context="flowlist")
km.add("S", "console.command 'replay.server '") km.add("S", "console.command 'replay.server '")
km.add("v", "set console_order_reversed=toggle", context="flowlist") km.add("v", "set console_order_reversed=toggle", context="flowlist")

View File

@ -137,6 +137,22 @@ def tdump(path, flows):
w.add(i) w.add(i)
def test_create():
v = view.View()
with taddons.context():
v.create("get", "http://foo.com")
assert len(v) == 1
assert v[0].request.url == "http://foo.com/"
v.create("get", "http://foo.com")
assert len(v) == 2
def test_orders():
v = view.View()
with taddons.context():
assert v.order_options()
def test_load(tmpdir): def test_load(tmpdir):
path = str(tmpdir.join("path")) path = str(tmpdir.join("path"))
v = view.View() v = view.View()

View File

@ -1,4 +1,3 @@
from unittest import mock
import urwid import urwid
import mitmproxy.tools.console.flowlist as flowlist import mitmproxy.tools.console.flowlist as flowlist
@ -14,13 +13,6 @@ class TestFlowlist:
o = options.Options(**opts) o = options.Options(**opts)
return console.master.ConsoleMaster(o, proxy.DummyServer()) return console.master.ConsoleMaster(o, proxy.DummyServer())
def test_new_request(self):
m = self.mkmaster()
x = flowlist.FlowListBox(m)
with mock.patch('mitmproxy.tools.console.signals.status_message.send') as mock_thing:
x.new_request("nonexistent url", "GET")
mock_thing.assert_called_once_with(message="Invalid URL: No hostname given")
def test_logbuffer_set_focus(self): def test_logbuffer_set_focus(self):
m = self.mkmaster() m = self.mkmaster()
b = flowlist.LogBufferBox(m) b = flowlist.LogBufferBox(m)

View File

@ -113,10 +113,6 @@ class TestFlowMaster:
with pytest.raises(Exception, match="live"): with pytest.raises(Exception, match="live"):
fm.replay_request(f) fm.replay_request(f)
def test_create_flow(self):
fm = master.Master(None, DummyServer())
assert fm.create_request("GET", "http://example.com/")
def test_all(self): def test_all(self):
s = tservers.TestState() s = tservers.TestState()
fm = master.Master(None, DummyServer()) fm = master.Master(None, DummyServer())