We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
query string arrays are not fully displayed
##### Steps to reproduce the problem:

1. visit through mitmproxy/mitmdump e.g. http://example.com/?first=value&arr[]=foo+bar&arr[]=baz
2. Check the query parameters in the request
3. Notice that they contain more data than mitmproxy/mitmdump shows

##### Any other comments? What have you tried so far?

The following script shows all the data:

```
#!/usr/bin/env python3

from urllib.parse import urlparse, parse_qs

url = "http://example.com/?first=value&arr[]=foo+bar&arr[]=baz"
parts = urlparse(url)
print(parse_qs(parts.query))
```

Output:
`{'first': ['value'], 'arr[]': ['foo bar', 'baz']}`

But mitmproxy/mitmdump only shows:
```
    first: value
    arr[]: foo bar
```

##### System information

<!-- Paste the output of "mitmproxy --version" here. -->

Mitmproxy: 3.0.4
Python:    3.5.2
OpenSSL:   OpenSSL 1.0.2g  1 Mar 2016
Platform:  Linux-4.10.0-42-generic-x86_64-with-Ubuntu-16.04-xenial

<!-- Please use the mitmproxy forums (https://discourse.mitmproxy.org/) for support/how-to questions. Thanks! :) -->


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mitmproxy/contentviews/base.py`
Content:
```
1 # Default view cutoff *in lines*
2 import typing
3 
4 KEY_MAX = 30
5 
6 TTextType = typing.Union[str, bytes]  # FIXME: This should be either bytes or str ultimately.
7 TViewLine = typing.List[typing.Tuple[str, TTextType]]
8 TViewResult = typing.Tuple[str, typing.Iterator[TViewLine]]
9 
10 
11 class View:
12     name: str = None
13     content_types: typing.List[str] = []
14 
15     def __call__(self, data: bytes, **metadata) -> TViewResult:
16         """
17         Transform raw data into human-readable output.
18 
19         Args:
20             data: the data to decode/format.
21             metadata: optional keyword-only arguments for metadata. Implementations must not
22                 rely on a given argument being present.
23 
24         Returns:
25             A (description, content generator) tuple.
26 
27             The content generator yields lists of (style, text) tuples, where each list represents
28             a single line. ``text`` is a unfiltered byte string which may need to be escaped,
29             depending on the used output.
30 
31         Caveats:
32             The content generator must not yield tuples of tuples,
33             because urwid cannot process that. You have to yield a *list* of tuples per line.
34         """
35         raise NotImplementedError()  # pragma: no cover
36 
37 
38 def format_dict(
39         d: typing.Mapping[TTextType, TTextType]
40 ) -> typing.Iterator[TViewLine]:
41     """
42     Helper function that transforms the given dictionary into a list of
43     [
44         ("key",   key  )
45         ("value", value)
46     ]
47     entries, where key is padded to a uniform width.
48     """
49 
50     max_key_len = max((len(k) for k in d.keys()), default=0)
51     max_key_len = min((max_key_len, KEY_MAX), default=0)
52     for key, value in d.items():
53         if isinstance(key, bytes):
54             key += b":"
55         else:
56             key += ":"
57         key = key.ljust(max_key_len + 2)
58         yield [
59             ("header", key),
60             ("text", value)
61         ]
62 
63 
64 def format_text(text: TTextType) -> typing.Iterator[TViewLine]:
65     """
66     Helper function that transforms bytes into the view output format.
67     """
68     for line in text.splitlines():
69         yield [("text", line)]
70
```

Path: `mitmproxy/contentviews/urlencoded.py`
Content:
```
1 from mitmproxy.net.http import url
2 from mitmproxy.coretypes import multidict
3 from . import base
4 
5 
6 class ViewURLEncoded(base.View):
7     name = "URL-encoded"
8     content_types = ["application/x-www-form-urlencoded"]
9 
10     def __call__(self, data, **metadata):
11         try:
12             data = data.decode("ascii", "strict")
13         except ValueError:
14             return None
15         d = url.decode(data)
16         return "URLEncoded form", base.format_dict(multidict.MultiDict(d))
17
```

Path: `mitmproxy/contentviews/query.py`
Content:
```
1 from typing import List  # noqa
2 
3 from . import base
4 
5 
6 class ViewQuery(base.View):
7     name = "Query"
8 
9     def __call__(self, data, **metadata):
10         query = metadata.get("query")
11         if query:
12             return "Query", base.format_dict(query)
13         else:
14             return "Query", base.format_text("")
15
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mitmproxy/contentviews/base.py b/mitmproxy/contentviews/base.py
--- a/mitmproxy/contentviews/base.py
+++ b/mitmproxy/contentviews/base.py
@@ -35,32 +35,52 @@
         raise NotImplementedError()  # pragma: no cover
 
 
-def format_dict(
-        d: typing.Mapping[TTextType, TTextType]
-) -> typing.Iterator[TViewLine]:
+def format_pairs(
+        items: typing.Iterable[typing.Tuple[TTextType, TTextType]]
+)-> typing.Iterator[TViewLine]:
+
     """
-    Helper function that transforms the given dictionary into a list of
+    Helper function that accepts a list of (k,v) pairs into a list of
     [
-        ("key",   key  )
+        ("key", key    )
         ("value", value)
     ]
-    entries, where key is padded to a uniform width.
+    where key is padded to a uniform width
     """
 
-    max_key_len = max((len(k) for k in d.keys()), default=0)
+    max_key_len = max((len(k[0]) for k in items), default=0)
     max_key_len = min((max_key_len, KEY_MAX), default=0)
-    for key, value in d.items():
+
+    for key, value in items:
         if isinstance(key, bytes):
+
             key += b":"
         else:
             key += ":"
+
         key = key.ljust(max_key_len + 2)
+
         yield [
             ("header", key),
             ("text", value)
         ]
 
 
+def format_dict(
+        d: typing.Mapping[TTextType, TTextType]
+) -> typing.Iterator[TViewLine]:
+    """
+    Helper function that transforms the given dictionary into a list of
+    [
+        ("key",   key  )
+        ("value", value)
+    ]
+    entries, where key is padded to a uniform width.
+    """
+
+    return format_pairs(d.items())
+
+
 def format_text(text: TTextType) -> typing.Iterator[TViewLine]:
     """
     Helper function that transforms bytes into the view output format.
diff --git a/mitmproxy/contentviews/query.py b/mitmproxy/contentviews/query.py
--- a/mitmproxy/contentviews/query.py
+++ b/mitmproxy/contentviews/query.py
@@ -9,6 +9,6 @@
     def __call__(self, data, **metadata):
         query = metadata.get("query")
         if query:
-            return "Query", base.format_dict(query)
+            return "Query", base.format_pairs(query.items(multi=True))
         else:
             return "Query", base.format_text("")
diff --git a/mitmproxy/contentviews/urlencoded.py b/mitmproxy/contentviews/urlencoded.py
--- a/mitmproxy/contentviews/urlencoded.py
+++ b/mitmproxy/contentviews/urlencoded.py
@@ -1,5 +1,4 @@
 from mitmproxy.net.http import url
-from mitmproxy.coretypes import multidict
 from . import base
 
 
@@ -13,4 +12,4 @@
         except ValueError:
             return None
         d = url.decode(data)
-        return "URLEncoded form", base.format_dict(multidict.MultiDict(d))
+        return "URLEncoded form", base.format_pairs(d)

{"golden_diff": "diff --git a/mitmproxy/contentviews/base.py b/mitmproxy/contentviews/base.py\n--- a/mitmproxy/contentviews/base.py\n+++ b/mitmproxy/contentviews/base.py\n@@ -35,32 +35,52 @@\n         raise NotImplementedError()  # pragma: no cover\n \n \n-def format_dict(\n-        d: typing.Mapping[TTextType, TTextType]\n-) -> typing.Iterator[TViewLine]:\n+def format_pairs(\n+        items: typing.Iterable[typing.Tuple[TTextType, TTextType]]\n+)-> typing.Iterator[TViewLine]:\n+\n     \"\"\"\n-    Helper function that transforms the given dictionary into a list of\n+    Helper function that accepts a list of (k,v) pairs into a list of\n     [\n-        (\"key\",   key  )\n+        (\"key\", key    )\n         (\"value\", value)\n     ]\n-    entries, where key is padded to a uniform width.\n+    where key is padded to a uniform width\n     \"\"\"\n \n-    max_key_len = max((len(k) for k in d.keys()), default=0)\n+    max_key_len = max((len(k[0]) for k in items), default=0)\n     max_key_len = min((max_key_len, KEY_MAX), default=0)\n-    for key, value in d.items():\n+\n+    for key, value in items:\n         if isinstance(key, bytes):\n+\n             key += b\":\"\n         else:\n             key += \":\"\n+\n         key = key.ljust(max_key_len + 2)\n+\n         yield [\n             (\"header\", key),\n             (\"text\", value)\n         ]\n \n \n+def format_dict(\n+        d: typing.Mapping[TTextType, TTextType]\n+) -> typing.Iterator[TViewLine]:\n+    \"\"\"\n+    Helper function that transforms the given dictionary into a list of\n+    [\n+        (\"key\",   key  )\n+        (\"value\", value)\n+    ]\n+    entries, where key is padded to a uniform width.\n+    \"\"\"\n+\n+    return format_pairs(d.items())\n+\n+\n def format_text(text: TTextType) -> typing.Iterator[TViewLine]:\n     \"\"\"\n     Helper function that transforms bytes into the view output format.\ndiff --git a/mitmproxy/contentviews/query.py b/mitmproxy/contentviews/query.py\n--- a/mitmproxy/contentviews/query.py\n+++ b/mitmproxy/contentviews/query.py\n@@ -9,6 +9,6 @@\n     def __call__(self, data, **metadata):\n         query = metadata.get(\"query\")\n         if query:\n-            return \"Query\", base.format_dict(query)\n+            return \"Query\", base.format_pairs(query.items(multi=True))\n         else:\n             return \"Query\", base.format_text(\"\")\ndiff --git a/mitmproxy/contentviews/urlencoded.py b/mitmproxy/contentviews/urlencoded.py\n--- a/mitmproxy/contentviews/urlencoded.py\n+++ b/mitmproxy/contentviews/urlencoded.py\n@@ -1,5 +1,4 @@\n from mitmproxy.net.http import url\n-from mitmproxy.coretypes import multidict\n from . import base\n \n \n@@ -13,4 +12,4 @@\n         except ValueError:\n             return None\n         d = url.decode(data)\n-        return \"URLEncoded form\", base.format_dict(multidict.MultiDict(d))\n+        return \"URLEncoded form\", base.format_pairs(d)\n", "issue": "query string arrays are not fully displayed\n##### Steps to reproduce the problem:\r\n\r\n1. visit through mitmproxy/mitmdump e.g. http://example.com/?first=value&arr[]=foo+bar&arr[]=baz\r\n2. Check the query parameters in the request\r\n3. Notice that they contain more data than mitmproxy/mitmdump shows\r\n\r\n##### Any other comments? What have you tried so far?\r\n\r\nThe following script shows all the data:\r\n\r\n```\r\n#!/usr/bin/env python3\r\n\r\nfrom urllib.parse import urlparse, parse_qs\r\n\r\nurl = \"http://example.com/?first=value&arr[]=foo+bar&arr[]=baz\"\r\nparts = urlparse(url)\r\nprint(parse_qs(parts.query))\r\n```\r\n\r\nOutput:\r\n`{'first': ['value'], 'arr[]': ['foo bar', 'baz']}`\r\n\r\nBut mitmproxy/mitmdump only shows:\r\n```\r\n    first: value\r\n    arr[]: foo bar\r\n```\r\n\r\n##### System information\r\n\r\n<!-- Paste the output of \"mitmproxy --version\" here. -->\r\n\r\nMitmproxy: 3.0.4\r\nPython:    3.5.2\r\nOpenSSL:   OpenSSL 1.0.2g  1 Mar 2016\r\nPlatform:  Linux-4.10.0-42-generic-x86_64-with-Ubuntu-16.04-xenial\r\n\r\n<!-- Please use the mitmproxy forums (https://discourse.mitmproxy.org/) for support/how-to questions. Thanks! :) -->\r\n\n", "before_files": [{"content": "# Default view cutoff *in lines*\nimport typing\n\nKEY_MAX = 30\n\nTTextType = typing.Union[str, bytes]  # FIXME: This should be either bytes or str ultimately.\nTViewLine = typing.List[typing.Tuple[str, TTextType]]\nTViewResult = typing.Tuple[str, typing.Iterator[TViewLine]]\n\n\nclass View:\n    name: str = None\n    content_types: typing.List[str] = []\n\n    def __call__(self, data: bytes, **metadata) -> TViewResult:\n        \"\"\"\n        Transform raw data into human-readable output.\n\n        Args:\n            data: the data to decode/format.\n            metadata: optional keyword-only arguments for metadata. Implementations must not\n                rely on a given argument being present.\n\n        Returns:\n            A (description, content generator) tuple.\n\n            The content generator yields lists of (style, text) tuples, where each list represents\n            a single line. ``text`` is a unfiltered byte string which may need to be escaped,\n            depending on the used output.\n\n        Caveats:\n            The content generator must not yield tuples of tuples,\n            because urwid cannot process that. You have to yield a *list* of tuples per line.\n        \"\"\"\n        raise NotImplementedError()  # pragma: no cover\n\n\ndef format_dict(\n        d: typing.Mapping[TTextType, TTextType]\n) -> typing.Iterator[TViewLine]:\n    \"\"\"\n    Helper function that transforms the given dictionary into a list of\n    [\n        (\"key\",   key  )\n        (\"value\", value)\n    ]\n    entries, where key is padded to a uniform width.\n    \"\"\"\n\n    max_key_len = max((len(k) for k in d.keys()), default=0)\n    max_key_len = min((max_key_len, KEY_MAX), default=0)\n    for key, value in d.items():\n        if isinstance(key, bytes):\n            key += b\":\"\n        else:\n            key += \":\"\n        key = key.ljust(max_key_len + 2)\n        yield [\n            (\"header\", key),\n            (\"text\", value)\n        ]\n\n\ndef format_text(text: TTextType) -> typing.Iterator[TViewLine]:\n    \"\"\"\n    Helper function that transforms bytes into the view output format.\n    \"\"\"\n    for line in text.splitlines():\n        yield [(\"text\", line)]\n", "path": "mitmproxy/contentviews/base.py"}, {"content": "from mitmproxy.net.http import url\nfrom mitmproxy.coretypes import multidict\nfrom . import base\n\n\nclass ViewURLEncoded(base.View):\n    name = \"URL-encoded\"\n    content_types = [\"application/x-www-form-urlencoded\"]\n\n    def __call__(self, data, **metadata):\n        try:\n            data = data.decode(\"ascii\", \"strict\")\n        except ValueError:\n            return None\n        d = url.decode(data)\n        return \"URLEncoded form\", base.format_dict(multidict.MultiDict(d))\n", "path": "mitmproxy/contentviews/urlencoded.py"}, {"content": "from typing import List  # noqa\n\nfrom . import base\n\n\nclass ViewQuery(base.View):\n    name = \"Query\"\n\n    def __call__(self, data, **metadata):\n        query = metadata.get(\"query\")\n        if query:\n            return \"Query\", base.format_dict(query)\n        else:\n            return \"Query\", base.format_text(\"\")\n", "path": "mitmproxy/contentviews/query.py"}], "after_files": [{"content": "# Default view cutoff *in lines*\nimport typing\n\nKEY_MAX = 30\n\nTTextType = typing.Union[str, bytes]  # FIXME: This should be either bytes or str ultimately.\nTViewLine = typing.List[typing.Tuple[str, TTextType]]\nTViewResult = typing.Tuple[str, typing.Iterator[TViewLine]]\n\n\nclass View:\n    name: str = None\n    content_types: typing.List[str] = []\n\n    def __call__(self, data: bytes, **metadata) -> TViewResult:\n        \"\"\"\n        Transform raw data into human-readable output.\n\n        Args:\n            data: the data to decode/format.\n            metadata: optional keyword-only arguments for metadata. Implementations must not\n                rely on a given argument being present.\n\n        Returns:\n            A (description, content generator) tuple.\n\n            The content generator yields lists of (style, text) tuples, where each list represents\n            a single line. ``text`` is a unfiltered byte string which may need to be escaped,\n            depending on the used output.\n\n        Caveats:\n            The content generator must not yield tuples of tuples,\n            because urwid cannot process that. You have to yield a *list* of tuples per line.\n        \"\"\"\n        raise NotImplementedError()  # pragma: no cover\n\n\ndef format_pairs(\n        items: typing.Iterable[typing.Tuple[TTextType, TTextType]]\n)-> typing.Iterator[TViewLine]:\n\n    \"\"\"\n    Helper function that accepts a list of (k,v) pairs into a list of\n    [\n        (\"key\", key    )\n        (\"value\", value)\n    ]\n    where key is padded to a uniform width\n    \"\"\"\n\n    max_key_len = max((len(k[0]) for k in items), default=0)\n    max_key_len = min((max_key_len, KEY_MAX), default=0)\n\n    for key, value in items:\n        if isinstance(key, bytes):\n\n            key += b\":\"\n        else:\n            key += \":\"\n\n        key = key.ljust(max_key_len + 2)\n\n        yield [\n            (\"header\", key),\n            (\"text\", value)\n        ]\n\n\ndef format_dict(\n        d: typing.Mapping[TTextType, TTextType]\n) -> typing.Iterator[TViewLine]:\n    \"\"\"\n    Helper function that transforms the given dictionary into a list of\n    [\n        (\"key\",   key  )\n        (\"value\", value)\n    ]\n    entries, where key is padded to a uniform width.\n    \"\"\"\n\n    return format_pairs(d.items())\n\n\ndef format_text(text: TTextType) -> typing.Iterator[TViewLine]:\n    \"\"\"\n    Helper function that transforms bytes into the view output format.\n    \"\"\"\n    for line in text.splitlines():\n        yield [(\"text\", line)]\n", "path": "mitmproxy/contentviews/base.py"}, {"content": "from mitmproxy.net.http import url\nfrom . import base\n\n\nclass ViewURLEncoded(base.View):\n    name = \"URL-encoded\"\n    content_types = [\"application/x-www-form-urlencoded\"]\n\n    def __call__(self, data, **metadata):\n        try:\n            data = data.decode(\"ascii\", \"strict\")\n        except ValueError:\n            return None\n        d = url.decode(data)\n        return \"URLEncoded form\", base.format_pairs(d)\n", "path": "mitmproxy/contentviews/urlencoded.py"}, {"content": "from typing import List  # noqa\n\nfrom . import base\n\n\nclass ViewQuery(base.View):\n    name = \"Query\"\n\n    def __call__(self, data, **metadata):\n        query = metadata.get(\"query\")\n        if query:\n            return \"Query\", base.format_pairs(query.items(multi=True))\n        else:\n            return \"Query\", base.format_text(\"\")\n", "path": "mitmproxy/contentviews/query.py"}]}