Repository: mitmproxy/mitmproxy

Issue:
Body editing broken on master
<!-- Please use the mitmproxy forums (https://discourse.mitmproxy.org/) for support/how-to questions. Thanks! :) -->
##### Steps to reproduce the problem:
1. Fire up mitmproxy
2. Edit a request or response body
##### What is the expected behavior?

The edit should be reflected in the flow display
##### What went wrong?

The edit is not visible

---

Mitmproxy Version: -master
Operating System: osx



Discussion:

Resolving patch:
diff --git a/mitmproxy/console/flowview.py b/mitmproxy/console/flowview.py
--- a/mitmproxy/console/flowview.py
+++ b/mitmproxy/console/flowview.py
@@ -189,15 +189,21 @@ def content_view(self, viewmode, message):
                 limit = sys.maxsize
             else:
                 limit = contentviews.VIEW_CUTOFF
+
+            flow_modify_cache_invalidation = hash((
+                message.raw_content,
+                message.headers.fields,
+                getattr(message, "path", None),
+            ))
             return cache.get(
-                self._get_content_view,
+                # We move message into this partial function as it is not hashable.
+                lambda *args: self._get_content_view(message, *args),
                 viewmode,
-                message,
                 limit,
-                message  # Cache invalidation
+                flow_modify_cache_invalidation
             )
 
-    def _get_content_view(self, viewmode, message, max_lines, _):
+    def _get_content_view(self, message, viewmode, max_lines, _):
 
         try:
             content = message.content
diff --git a/netlib/http/message.py b/netlib/http/message.py
--- a/netlib/http/message.py
+++ b/netlib/http/message.py
@@ -32,9 +32,6 @@ def __eq__(self, other):
     def __ne__(self, other):
         return not self.__eq__(other)
 
-    def __hash__(self):
-        return hash(frozenset(self.__dict__.items()))
-
     def set_state(self, state):
         for k, v in state.items():
             if k == "headers":
@@ -77,9 +74,6 @@ def __eq__(self, other):
     def __ne__(self, other):
         return not self.__eq__(other)
 
-    def __hash__(self):
-        return hash(self.data) ^ 1
-
     def get_state(self):
         return self.data.get_state()
 
diff --git a/netlib/multidict.py b/netlib/multidict.py
--- a/netlib/multidict.py
+++ b/netlib/multidict.py
@@ -79,9 +79,6 @@ def __eq__(self, other):
     def __ne__(self, other):
         return not self.__eq__(other)
 
-    def __hash__(self):
-        return hash(self.fields)
-
     def get_all(self, key):
         """
         Return the list of all values for a given key.
@@ -241,6 +238,9 @@ def _immutable(self, *_):
 
     __delitem__ = set_all = insert = _immutable
 
+    def __hash__(self):
+        return hash(self.fields)
+
     def with_delitem(self, key):
         """
         Returns:


Test patch:
diff --git a/test/netlib/http/test_message.py b/test/netlib/http/test_message.py
--- a/test/netlib/http/test_message.py
+++ b/test/netlib/http/test_message.py
@@ -71,10 +71,6 @@ def test_eq_ne(self):
 
         assert resp != 0
 
-    def test_hash(self):
-        resp = tresp()
-        assert hash(resp)
-
     def test_serializable(self):
         resp = tresp()
         resp2 = http.Response.from_state(resp.get_state())
diff --git a/test/netlib/test_multidict.py b/test/netlib/test_multidict.py
--- a/test/netlib/test_multidict.py
+++ b/test/netlib/test_multidict.py
@@ -45,7 +45,7 @@ def test_getitem(self):
         assert md["foo"] == "bar"
 
         with tutils.raises(KeyError):
-            md["bar"]
+            assert md["bar"]
 
         md_multi = TMultiDict(
             [("foo", "a"), ("foo", "b")]
@@ -101,6 +101,15 @@ def test_ne(self):
         assert TMultiDict() != self._multi()
         assert TMultiDict() != 42
 
+    def test_hash(self):
+        """
+        If a class defines mutable objects and implements an __eq__() method,
+        it should not implement __hash__(), since the implementation of hashable
+        collections requires that a key's hash value is immutable.
+        """
+        with tutils.raises(TypeError):
+            assert hash(TMultiDict())
+
     def test_get_all(self):
         md = self._multi()
         assert md.get_all("foo") == ["bar"]
@@ -197,6 +206,9 @@ def test_modify(self):
         with tutils.raises(TypeError):
             md.add("foo", "bar")
 
+    def test_hash(self):
+        assert hash(TImmutableMultiDict())
+
     def test_with_delitem(self):
         md = TImmutableMultiDict([("foo", "bar")])
         assert md.with_delitem("foo").fields == ()