Add --kill option to mitmdump

If this option is passed all requests that are not part of a replayed
conversation are killed. If the option is not passed, such requests are passed
through to the server as usual.
This commit is contained in:
Aldo Cortesi 2011-02-21 11:08:35 +13:00
parent c3e3897071
commit fe99871df8
6 changed files with 40 additions and 11 deletions

View File

@ -6,11 +6,12 @@ class DumpError(Exception): pass
class Options(object): class Options(object):
__slots__ = [ __slots__ = [
"verbosity", "kill",
"wfile",
"request_script", "request_script",
"response_script", "response_script",
"replay", "replay",
"verbosity",
"wfile",
] ]
def __init__(self, **kwargs): def __init__(self, **kwargs):
for k, v in kwargs.items(): for k, v in kwargs.items():
@ -66,7 +67,15 @@ class DumpMaster(flow.FlowMaster):
f = flow.FlowMaster.handle_request(self, r) f = flow.FlowMaster.handle_request(self, r)
if self.o.request_script: if self.o.request_script:
self._runscript(f, self.o.request_script) self._runscript(f, self.o.request_script)
if not self.playback(f):
if self.o.replay:
pb = self.playback(f)
if not pb:
if self.o.kill:
self.state.kill_flow(f)
else:
r.ack()
else:
r.ack() r.ack()
def indent(self, n, t): def indent(self, n, t):

View File

@ -44,9 +44,10 @@ class ServerPlaybackState:
chronological order. chronological order.
""" """
for i in flows: for i in flows:
h = self._hash(i) if i.response:
l = self.fmap.setdefault(self._hash(i), []) h = self._hash(i)
l.append(i) l = self.fmap.setdefault(self._hash(i), [])
l.append(i)
def _hash(self, flow): def _hash(self, flow):
""" """

View File

@ -50,6 +50,9 @@ if __name__ == '__main__':
parser.add_option("-r", "--replay", parser.add_option("-r", "--replay",
action="store", dest="replay", default=None, action="store", dest="replay", default=None,
help="Replay server responses from a saved file.") help="Replay server responses from a saved file.")
parser.add_option("-k", "--kill",
action="store_true", dest="kill", default=False,
help="Kill extra requests during replay.")
options, args = parser.parse_args() options, args = parser.parse_args()
@ -65,6 +68,7 @@ if __name__ == '__main__':
request_script = options.request_script, request_script = options.request_script,
response_script = options.response_script, response_script = options.response_script,
replay = options.replay, replay = options.replay,
kill = options.kill
) )
if args: if args:
filt = " ".join(args) filt = " ".join(args)

View File

@ -26,19 +26,27 @@ class uDumpMaster(libpry.AutoTree):
def test_replay(self): def test_replay(self):
cs = StringIO() cs = StringIO()
o = dump.Options(replay="nonexistent") o = dump.Options(replay="nonexistent", kill=True)
libpry.raises(dump.DumpError, dump.DumpMaster, None, o, None, outfile=cs) libpry.raises(dump.DumpError, dump.DumpMaster, None, o, None, outfile=cs)
t = self.tmpdir() t = self.tmpdir()
p = os.path.join(t, "rep") p = os.path.join(t, "rep")
f = open(p, "w") f = open(p, "w")
fw = flow.FlowWriter(f) fw = flow.FlowWriter(f)
t = utils.tflow() t = utils.tflow_full()
t.response = utils.tresp(t.request)
fw.add(t) fw.add(t)
f.close() f.close()
o = dump.Options(replay=p) o = dump.Options(replay=p, kill=True)
m = dump.DumpMaster(None, o, None, outfile=cs) m = dump.DumpMaster(None, o, None, outfile=cs)
self._cycle(m, "content")
self._cycle(m, "content")
o = dump.Options(replay=p, kill=False)
m = dump.DumpMaster(None, o, None, outfile=cs)
self._cycle(m, "nonexistent")
def test_options(self): def test_options(self):
o = dump.Options(verbosity = 2) o = dump.Options(verbosity = 2)

View File

@ -19,10 +19,10 @@ class uServerPlaybackState(libpry.AutoTree):
def test_load(self): def test_load(self):
s = flow.ServerPlaybackState() s = flow.ServerPlaybackState()
r = utils.tflow() r = utils.tflow_full()
r.request.headers["key"] = ["one"] r.request.headers["key"] = ["one"]
r2 = utils.tflow() r2 = utils.tflow_full()
r2.request.headers["key"] = ["two"] r2.request.headers["key"] = ["two"]
s.load([r, r2]) s.load([r, r2])

View File

@ -22,3 +22,10 @@ def tflow():
return flow.Flow(r) return flow.Flow(r)
def tflow_full():
r = treq()
f = flow.Flow(r)
f.response = tresp(r)
return f