diff --git a/mitmproxy/addons/script.py b/mitmproxy/addons/script.py index decd07596..a39ce5ce5 100644 --- a/mitmproxy/addons/script.py +++ b/mitmproxy/addons/script.py @@ -148,17 +148,25 @@ class ScriptLoader: @command.command("script.run") def script_run(self, flows: typing.Sequence[flow.Flow], path: mtypes.Path) -> None: """ - Run a script on the specified flows. The script is loaded with - default options, and all lifecycle events for each flow are - simulated. + Run a script on the specified flows. The script is configured with + the current options and all lifecycle events for each flow are + simulated. Note that the load event is not invoked. """ - try: - s = Script(path, False) - for f in flows: - for evt, arg in eventsequence.iterate(f): - ctx.master.addons.invoke_addon(s, evt, arg) - except exceptions.OptionsError as e: - script_error_handler(path, e, msg=str(e)) + if not os.path.isfile(path): + ctx.log.error('No such script: %s' % path) + return + mod = load_script(path) + if mod: + with addonmanager.safecall(): + ctx.master.addons.invoke_addon(mod, "running") + ctx.master.addons.invoke_addon( + mod, + "configure", + ctx.options.keys() + ) + for f in flows: + for evt, arg in eventsequence.iterate(f): + ctx.master.addons.invoke_addon(mod, evt, arg) def configure(self, updated): if "scripts" in updated: diff --git a/mitmproxy/controller.py b/mitmproxy/controller.py index 582a6683f..6e2190663 100644 --- a/mitmproxy/controller.py +++ b/mitmproxy/controller.py @@ -113,6 +113,8 @@ class Reply: def kill(self, force=False): self.send(exceptions.Kill, force) + if self._state == "taken": + self.commit() def send(self, msg, force=False): if self.state not in {"start", "taken"}: diff --git a/mitmproxy/net/tcp.py b/mitmproxy/net/tcp.py index 18429daa6..2496d47c7 100644 --- a/mitmproxy/net/tcp.py +++ b/mitmproxy/net/tcp.py @@ -1,4 +1,5 @@ import os +import errno import select import socket import sys @@ -585,6 +586,13 @@ class TCPServer: with self.handler_counter: try: self.handle_client_connection(connection, client_address) + except OSError as e: # pragma: no cover + # This catches situations where the underlying connection is + # closed beneath us. Syscalls on the connection object at this + # point returns EINVAL. If this happens, we close the socket and + # move on. + if not e.errno == errno.EINVAL: + raise except: self.handle_error(connection, client_address) finally: diff --git a/mitmproxy/tools/console/flowlist.py b/mitmproxy/tools/console/flowlist.py index e6bd1693c..a9e48af41 100644 --- a/mitmproxy/tools/console/flowlist.py +++ b/mitmproxy/tools/console/flowlist.py @@ -39,6 +39,14 @@ class FlowListWalker(urwid.ListWalker): def __init__(self, master): self.master = master + def positions(self, reverse=False): + # The stub implementation of positions can go once this issue is resolved: + # https://github.com/urwid/urwid/issues/294 + ret = range(len(self.master.view)) + if reverse: + return reversed(ret) + return ret + def view_changed(self): self._modified() diff --git a/test/mitmproxy/addons/test_script.py b/test/mitmproxy/addons/test_script.py index 573b36e76..05472d9a0 100644 --- a/test/mitmproxy/addons/test_script.py +++ b/test/mitmproxy/addons/test_script.py @@ -173,16 +173,14 @@ class TestCutTraceback: class TestScriptLoader: @pytest.mark.asyncio async def test_script_run(self, tdata): - rp = tdata.path( - "mitmproxy/data/addonscripts/recorder/recorder.py" - ) + rp = tdata.path("mitmproxy/data/addonscripts/recorder/recorder.py") sc = script.ScriptLoader() with taddons.context(sc) as tctx: sc.script_run([tflow.tflow(resp=True)], rp) await tctx.master.await_log("recorder response") debug = [i.msg for i in tctx.master.logs if i.level == "debug"] assert debug == [ - 'recorder load', 'recorder running', 'recorder configure', + 'recorder running', 'recorder configure', 'recorder requestheaders', 'recorder request', 'recorder responseheaders', 'recorder response' ] @@ -192,7 +190,7 @@ class TestScriptLoader: sc = script.ScriptLoader() with taddons.context(sc) as tctx: sc.script_run([tflow.tflow(resp=True)], "/") - assert await tctx.master.await_log("/: No such script") + assert await tctx.master.await_log("No such script") def test_simple(self, tdata): sc = script.ScriptLoader()