Repository: mitmproxy/mitmproxy

Issue:
Body editing is broken.
From @kajojify:

> Enter request-body/response-body editor, then leave it and try to interact with mitmproxy. 
Everything was ok with v3.0.0rc2, but v3.0.1 stops reacting on any button.

I can reproduce this on WSL - this needs to be fixed ASAP and probably warrants a bugfix release. I'm unfortunately super busy this weekend, so it'd be great if someone could take a closer look.


Discussion:
This is an URWID issue, reported here:

https://github.com/urwid/urwid/issues/285

Urwid seems to have had a bit of an internal revolution, and has seen two releases this year (last one before that in 2015!). This is great news. I'll chip in on the Urwid ticket to add our voice.

In the meantime, we should pin to 1.3.1, and cut a bugfix release. I'm on cafe wifi today, which means I can't do a release until this afternoon. Let's see if someone beats me to it.



Resolving patch:
diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py
--- a/mitmproxy/tools/console/master.py
+++ b/mitmproxy/tools/console/master.py
@@ -10,6 +10,7 @@
 import tempfile
 import traceback
 import typing  # noqa
+import contextlib
 
 import urwid
 
@@ -102,6 +103,16 @@ def cb(*_):
             return callback(*args)
         self.loop.set_alarm_in(seconds, cb)
 
+    @contextlib.contextmanager
+    def uistopped(self):
+        self.loop.stop()
+        try:
+            yield
+        finally:
+            self.loop.start()
+            self.loop.screen_size = None
+            self.loop.draw_screen()
+
     def spawn_editor(self, data):
         text = not isinstance(data, bytes)
         fd, name = tempfile.mkstemp('', "mproxy", text=text)
@@ -111,17 +122,16 @@ def spawn_editor(self, data):
         c = os.environ.get("EDITOR") or "vi"
         cmd = shlex.split(c)
         cmd.append(name)
-        self.ui.stop()
-        try:
-            subprocess.call(cmd)
-        except:
-            signals.status_message.send(
-                message="Can't start editor: %s" % " ".join(c)
-            )
-        else:
-            with open(name, "r" if text else "rb") as f:
-                data = f.read()
-        self.ui.start()
+        with self.uistopped():
+            try:
+                subprocess.call(cmd)
+            except:
+                signals.status_message.send(
+                    message="Can't start editor: %s" % " ".join(c)
+                )
+            else:
+                with open(name, "r" if text else "rb") as f:
+                    data = f.read()
         os.unlink(name)
         return data
 
@@ -153,14 +163,13 @@ def spawn_external_viewer(self, data, contenttype):
                 c = "less"
             cmd = shlex.split(c)
             cmd.append(name)
-        self.ui.stop()
-        try:
-            subprocess.call(cmd, shell=shell)
-        except:
-            signals.status_message.send(
-                message="Can't start external viewer: %s" % " ".join(c)
-            )
-        self.ui.start()
+        with self.uistopped():
+            try:
+                subprocess.call(cmd, shell=shell)
+            except:
+                signals.status_message.send(
+                    message="Can't start external viewer: %s" % " ".join(c)
+                )
         os.unlink(name)
 
     def set_palette(self, opts, updated):


Test patch: