We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Mitmdump option "--modify-headers" not working if any script added using "--scripts".
#### Problem Description
When using mitmdump with script specified using `--scripts` option - `--modify-headers` option is ignored.

#### Steps to reproduce the behavior:

**1.** Launch `mitmdump` with `--modify-headers`. 
My example: 
`mitmdump --set confdir=./.mitmproxy --flow-detail=2 --listen-port=8081 --modify-headers "/~q/Host/example.org"`
Output with `curl -x 127.0.0.1:8081 "http://www.trackip.net/ip?json"`:
```
127.0.0.1:50216: clientconnect
127.0.0.1:50216: GET http://www.trackip.net/ip?json
    User-Agent: curl/7.64.1
    Accept: */*
    Proxy-Connection: Keep-Alive
    Host: example.org
 << 404 Not Found 1.67k
    Date: Thu, 26 Nov 2020 10:06:22 GMT
    Content-Type: text/html; charset=UTF-8
    Transfer-Encoding: chunked
    Connection: keep-alive
    Set-Cookie: __cfduid=de786483d16a417b8768b01f604ef7f991606385181; expires=Sat, 26-Dec-20 10:06:21 GMT; path=/; domain=.example.org; HttpOnly; SameSite=Lax
    Lookup-Cache-Hit: 1
    Cache-Control: public, max-age=60
    Vary: Accept-Language, Accept-Encoding
    X-Cache: MISS
    X-Cache-Hits: 0
    CF-Cache-Status: MISS
    cf-request-id: 06a59dbd0500002d377c038000000001
    Report-To: {"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=NYIz48uJ3L6ZWGjd%2FEO4iNMvcCH0gsGhQhs4dpQ92t5e7W2I3wP1hp%2FoVqfbe94xjJbxqsuNcuvGp4dShFlFYVyn3W0hQX6RveNgJw%3D%3D"}],"group":"cf-nel","max_age":604800}
    NEL: {"report_to":"cf-nel","max_age":604800}
    X-Content-Type-Options: nosniff
    Server: cloudflare
    CF-RAY: 5f82cbdb3f422d37-KBP
127.0.0.1:50216: clientdisconnect
```
Header `Host` has been replaced with `example.org`, as expected.

**2.** Now launch `mitmdump` with `--modify-headers` and `--script`.
My example (using [jsondump.py](https://github.com/mitmproxy/mitmproxy/blob/master/examples/contrib/jsondump.py) script from `examples/contrib`): 
`mitmdump --set confdir=./.mitmproxy --flow-detail=2 --listen-port=8081 --modify-headers "/~q/Host/example.org" --scripts="/Users/ignisor/dev/proxy_lib/proxy/utils/jsondump.py"`
Output with `curl -x 127.0.0.1:8081 "http://www.trackip.net/ip?json"`:
```
Proxy server listening at http://*:8081
127.0.0.1:50412: clientconnect
127.0.0.1:50412: GET http://www.trackip.net/ip?json
    Host: www.trackip.net
    User-Agent: curl/7.64.1
    Accept: */*
    Proxy-Connection: Keep-Alive
 << 200 OK 76b
    Date: Thu, 26 Nov 2020 10:11:30 GMT
    Content-Type: text/plain
    Content-Length: 76
    Connection: keep-alive
    Set-Cookie: __cfduid=dd9e78e478768657490d8e5f8df1e870d1606385490; expires=Sat, 26-Dec-20 10:11:30 GMT; path=/; domain=.trackip.net; HttpOnly; SameSite=Lax
    CF-Cache-Status: DYNAMIC
    cf-request-id: 06a5a272a300003f0495bde000000001
    Report-To: {"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report?s=E3IAN%2BfUeGUIqX75SqBx%2FwUVisP1%2Fa7iRdHS7P6wUzZI1A6zSkhSqR6sKJ82sZo9tWkzTrtPYVQq6xozPGJ82Y34hSyPXP%2Fo%2FW7kC%2FFulUc%3D"}],"group":"cf-nel","max_age":604800}
    NEL: {"report_to":"cf-nel","max_age":604800}
    Server: cloudflare
    CF-RAY: 5f82d3643d183f04-KBP
127.0.0.1:50412: clientdisconnect
```
Header `Host` **not changed** and still `www.trackip.net`.


#### System Information

> Mitmproxy: 5.3.0
> Python:    3.9.0
> OpenSSL:   OpenSSL 1.1.1h  22 Sep 2020
> Platform:  macOS-10.16-x86_64-i386-64bit


--- 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/addons/modifyheaders.py`
Content:
```
1 import re
2 import typing
3 from pathlib import Path
4 
5 from mitmproxy import ctx, exceptions, flowfilter, http
6 from mitmproxy.net.http import Headers
7 from mitmproxy.utils import strutils
8 from mitmproxy.utils.spec import parse_spec
9 
10 
11 class ModifySpec(typing.NamedTuple):
12     matches: flowfilter.TFilter
13     subject: bytes
14     replacement_str: str
15 
16     def read_replacement(self) -> bytes:
17         """
18         Process the replacement str. This usually just involves converting it to bytes.
19         However, if it starts with `@`, we interpret the rest as a file path to read from.
20 
21         Raises:
22             - IOError if the file cannot be read.
23         """
24         if self.replacement_str.startswith("@"):
25             return Path(self.replacement_str[1:]).expanduser().read_bytes()
26         else:
27             # We could cache this at some point, but unlikely to be a problem.
28             return strutils.escaped_str_to_bytes(self.replacement_str)
29 
30 
31 def parse_modify_spec(option: str, subject_is_regex: bool) -> ModifySpec:
32     flow_filter, subject_str, replacement = parse_spec(option)
33 
34     subject = strutils.escaped_str_to_bytes(subject_str)
35     if subject_is_regex:
36         try:
37             re.compile(subject)
38         except re.error as e:
39             raise ValueError(f"Invalid regular expression {subject!r} ({e})")
40 
41     spec = ModifySpec(flow_filter, subject, replacement)
42 
43     try:
44         spec.read_replacement()
45     except OSError as e:
46         raise ValueError(f"Invalid file path: {replacement[1:]} ({e})")
47 
48     return spec
49 
50 
51 class ModifyHeaders:
52     def __init__(self):
53         self.replacements: typing.List[ModifySpec] = []
54 
55     def load(self, loader):
56         loader.add_option(
57             "modify_headers", typing.Sequence[str], [],
58             """
59             Header modify pattern of the form "[/flow-filter]/header-name/[@]header-value", where the
60             separator can be any character. The @ allows to provide a file path that is used to read
61             the header value string. An empty header-value removes existing header-name headers.
62             """
63         )
64 
65     def configure(self, updated):
66         self.replacements = []
67         if "modify_headers" in updated:
68             for option in ctx.options.modify_headers:
69                 try:
70                     spec = parse_modify_spec(option, False)
71                 except ValueError as e:
72                     raise exceptions.OptionsError(f"Cannot parse modify_headers option {option}: {e}") from e
73                 self.replacements.append(spec)
74 
75     def request(self, flow):
76         if not flow.reply.has_message:
77             self.run(flow, flow.request.headers)
78 
79     def response(self, flow):
80         if not flow.reply.has_message:
81             self.run(flow, flow.response.headers)
82 
83     def run(self, flow: http.HTTPFlow, hdrs: Headers) -> None:
84         # unset all specified headers
85         for spec in self.replacements:
86             if spec.matches(flow):
87                 hdrs.pop(spec.subject, None)
88 
89         # set all specified headers if the replacement string is not empty
90         for spec in self.replacements:
91             if spec.matches(flow):
92                 try:
93                     replacement = spec.read_replacement()
94                 except OSError as e:
95                     ctx.log.warn(f"Could not read replacement file: {e}")
96                     continue
97                 else:
98                     if replacement:
99                         hdrs.add(spec.subject, replacement)
100
```
--- 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/addons/modifyheaders.py b/mitmproxy/addons/modifyheaders.py
--- a/mitmproxy/addons/modifyheaders.py
+++ b/mitmproxy/addons/modifyheaders.py
@@ -63,8 +63,8 @@
         )
 
     def configure(self, updated):
-        self.replacements = []
         if "modify_headers" in updated:
+            self.replacements = []
             for option in ctx.options.modify_headers:
                 try:
                     spec = parse_modify_spec(option, False)

{"golden_diff": "diff --git a/mitmproxy/addons/modifyheaders.py b/mitmproxy/addons/modifyheaders.py\n--- a/mitmproxy/addons/modifyheaders.py\n+++ b/mitmproxy/addons/modifyheaders.py\n@@ -63,8 +63,8 @@\n         )\n \n     def configure(self, updated):\n-        self.replacements = []\n         if \"modify_headers\" in updated:\n+            self.replacements = []\n             for option in ctx.options.modify_headers:\n                 try:\n                     spec = parse_modify_spec(option, False)\n", "issue": "Mitmdump option \"--modify-headers\" not working if any script added using \"--scripts\".\n#### Problem Description\r\nWhen using mitmdump with script specified using `--scripts` option - `--modify-headers` option is ignored.\r\n\r\n#### Steps to reproduce the behavior:\r\n\r\n**1.** Launch `mitmdump` with `--modify-headers`. \r\nMy example: \r\n`mitmdump --set confdir=./.mitmproxy --flow-detail=2 --listen-port=8081 --modify-headers \"/~q/Host/example.org\"`\r\nOutput with `curl -x 127.0.0.1:8081 \"http://www.trackip.net/ip?json\"`:\r\n```\r\n127.0.0.1:50216: clientconnect\r\n127.0.0.1:50216: GET http://www.trackip.net/ip?json\r\n    User-Agent: curl/7.64.1\r\n    Accept: */*\r\n    Proxy-Connection: Keep-Alive\r\n    Host: example.org\r\n << 404 Not Found 1.67k\r\n    Date: Thu, 26 Nov 2020 10:06:22 GMT\r\n    Content-Type: text/html; charset=UTF-8\r\n    Transfer-Encoding: chunked\r\n    Connection: keep-alive\r\n    Set-Cookie: __cfduid=de786483d16a417b8768b01f604ef7f991606385181; expires=Sat, 26-Dec-20 10:06:21 GMT; path=/; domain=.example.org; HttpOnly; SameSite=Lax\r\n    Lookup-Cache-Hit: 1\r\n    Cache-Control: public, max-age=60\r\n    Vary: Accept-Language, Accept-Encoding\r\n    X-Cache: MISS\r\n    X-Cache-Hits: 0\r\n    CF-Cache-Status: MISS\r\n    cf-request-id: 06a59dbd0500002d377c038000000001\r\n    Report-To: {\"endpoints\":[{\"url\":\"https:\\\\/\\\\/a.nel.cloudflare.com\\\\/report?s=NYIz48uJ3L6ZWGjd%2FEO4iNMvcCH0gsGhQhs4dpQ92t5e7W2I3wP1hp%2FoVqfbe94xjJbxqsuNcuvGp4dShFlFYVyn3W0hQX6RveNgJw%3D%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}\r\n    NEL: {\"report_to\":\"cf-nel\",\"max_age\":604800}\r\n    X-Content-Type-Options: nosniff\r\n    Server: cloudflare\r\n    CF-RAY: 5f82cbdb3f422d37-KBP\r\n127.0.0.1:50216: clientdisconnect\r\n```\r\nHeader `Host` has been replaced with `example.org`, as expected.\r\n\r\n**2.** Now launch `mitmdump` with `--modify-headers` and `--script`.\r\nMy example (using [jsondump.py](https://github.com/mitmproxy/mitmproxy/blob/master/examples/contrib/jsondump.py) script from `examples/contrib`): \r\n`mitmdump --set confdir=./.mitmproxy --flow-detail=2 --listen-port=8081 --modify-headers \"/~q/Host/example.org\" --scripts=\"/Users/ignisor/dev/proxy_lib/proxy/utils/jsondump.py\"`\r\nOutput with `curl -x 127.0.0.1:8081 \"http://www.trackip.net/ip?json\"`:\r\n```\r\nProxy server listening at http://*:8081\r\n127.0.0.1:50412: clientconnect\r\n127.0.0.1:50412: GET http://www.trackip.net/ip?json\r\n    Host: www.trackip.net\r\n    User-Agent: curl/7.64.1\r\n    Accept: */*\r\n    Proxy-Connection: Keep-Alive\r\n << 200 OK 76b\r\n    Date: Thu, 26 Nov 2020 10:11:30 GMT\r\n    Content-Type: text/plain\r\n    Content-Length: 76\r\n    Connection: keep-alive\r\n    Set-Cookie: __cfduid=dd9e78e478768657490d8e5f8df1e870d1606385490; expires=Sat, 26-Dec-20 10:11:30 GMT; path=/; domain=.trackip.net; HttpOnly; SameSite=Lax\r\n    CF-Cache-Status: DYNAMIC\r\n    cf-request-id: 06a5a272a300003f0495bde000000001\r\n    Report-To: {\"endpoints\":[{\"url\":\"https:\\\\/\\\\/a.nel.cloudflare.com\\\\/report?s=E3IAN%2BfUeGUIqX75SqBx%2FwUVisP1%2Fa7iRdHS7P6wUzZI1A6zSkhSqR6sKJ82sZo9tWkzTrtPYVQq6xozPGJ82Y34hSyPXP%2Fo%2FW7kC%2FFulUc%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}\r\n    NEL: {\"report_to\":\"cf-nel\",\"max_age\":604800}\r\n    Server: cloudflare\r\n    CF-RAY: 5f82d3643d183f04-KBP\r\n127.0.0.1:50412: clientdisconnect\r\n```\r\nHeader `Host` **not changed** and still `www.trackip.net`.\r\n\r\n\r\n#### System Information\r\n\r\n> Mitmproxy: 5.3.0\r\n> Python:    3.9.0\r\n> OpenSSL:   OpenSSL 1.1.1h  22 Sep 2020\r\n> Platform:  macOS-10.16-x86_64-i386-64bit\r\n\n", "before_files": [{"content": "import re\nimport typing\nfrom pathlib import Path\n\nfrom mitmproxy import ctx, exceptions, flowfilter, http\nfrom mitmproxy.net.http import Headers\nfrom mitmproxy.utils import strutils\nfrom mitmproxy.utils.spec import parse_spec\n\n\nclass ModifySpec(typing.NamedTuple):\n    matches: flowfilter.TFilter\n    subject: bytes\n    replacement_str: str\n\n    def read_replacement(self) -> bytes:\n        \"\"\"\n        Process the replacement str. This usually just involves converting it to bytes.\n        However, if it starts with `@`, we interpret the rest as a file path to read from.\n\n        Raises:\n            - IOError if the file cannot be read.\n        \"\"\"\n        if self.replacement_str.startswith(\"@\"):\n            return Path(self.replacement_str[1:]).expanduser().read_bytes()\n        else:\n            # We could cache this at some point, but unlikely to be a problem.\n            return strutils.escaped_str_to_bytes(self.replacement_str)\n\n\ndef parse_modify_spec(option: str, subject_is_regex: bool) -> ModifySpec:\n    flow_filter, subject_str, replacement = parse_spec(option)\n\n    subject = strutils.escaped_str_to_bytes(subject_str)\n    if subject_is_regex:\n        try:\n            re.compile(subject)\n        except re.error as e:\n            raise ValueError(f\"Invalid regular expression {subject!r} ({e})\")\n\n    spec = ModifySpec(flow_filter, subject, replacement)\n\n    try:\n        spec.read_replacement()\n    except OSError as e:\n        raise ValueError(f\"Invalid file path: {replacement[1:]} ({e})\")\n\n    return spec\n\n\nclass ModifyHeaders:\n    def __init__(self):\n        self.replacements: typing.List[ModifySpec] = []\n\n    def load(self, loader):\n        loader.add_option(\n            \"modify_headers\", typing.Sequence[str], [],\n            \"\"\"\n            Header modify pattern of the form \"[/flow-filter]/header-name/[@]header-value\", where the\n            separator can be any character. The @ allows to provide a file path that is used to read\n            the header value string. An empty header-value removes existing header-name headers.\n            \"\"\"\n        )\n\n    def configure(self, updated):\n        self.replacements = []\n        if \"modify_headers\" in updated:\n            for option in ctx.options.modify_headers:\n                try:\n                    spec = parse_modify_spec(option, False)\n                except ValueError as e:\n                    raise exceptions.OptionsError(f\"Cannot parse modify_headers option {option}: {e}\") from e\n                self.replacements.append(spec)\n\n    def request(self, flow):\n        if not flow.reply.has_message:\n            self.run(flow, flow.request.headers)\n\n    def response(self, flow):\n        if not flow.reply.has_message:\n            self.run(flow, flow.response.headers)\n\n    def run(self, flow: http.HTTPFlow, hdrs: Headers) -> None:\n        # unset all specified headers\n        for spec in self.replacements:\n            if spec.matches(flow):\n                hdrs.pop(spec.subject, None)\n\n        # set all specified headers if the replacement string is not empty\n        for spec in self.replacements:\n            if spec.matches(flow):\n                try:\n                    replacement = spec.read_replacement()\n                except OSError as e:\n                    ctx.log.warn(f\"Could not read replacement file: {e}\")\n                    continue\n                else:\n                    if replacement:\n                        hdrs.add(spec.subject, replacement)\n", "path": "mitmproxy/addons/modifyheaders.py"}], "after_files": [{"content": "import re\nimport typing\nfrom pathlib import Path\n\nfrom mitmproxy import ctx, exceptions, flowfilter, http\nfrom mitmproxy.net.http import Headers\nfrom mitmproxy.utils import strutils\nfrom mitmproxy.utils.spec import parse_spec\n\n\nclass ModifySpec(typing.NamedTuple):\n    matches: flowfilter.TFilter\n    subject: bytes\n    replacement_str: str\n\n    def read_replacement(self) -> bytes:\n        \"\"\"\n        Process the replacement str. This usually just involves converting it to bytes.\n        However, if it starts with `@`, we interpret the rest as a file path to read from.\n\n        Raises:\n            - IOError if the file cannot be read.\n        \"\"\"\n        if self.replacement_str.startswith(\"@\"):\n            return Path(self.replacement_str[1:]).expanduser().read_bytes()\n        else:\n            # We could cache this at some point, but unlikely to be a problem.\n            return strutils.escaped_str_to_bytes(self.replacement_str)\n\n\ndef parse_modify_spec(option: str, subject_is_regex: bool) -> ModifySpec:\n    flow_filter, subject_str, replacement = parse_spec(option)\n\n    subject = strutils.escaped_str_to_bytes(subject_str)\n    if subject_is_regex:\n        try:\n            re.compile(subject)\n        except re.error as e:\n            raise ValueError(f\"Invalid regular expression {subject!r} ({e})\")\n\n    spec = ModifySpec(flow_filter, subject, replacement)\n\n    try:\n        spec.read_replacement()\n    except OSError as e:\n        raise ValueError(f\"Invalid file path: {replacement[1:]} ({e})\")\n\n    return spec\n\n\nclass ModifyHeaders:\n    def __init__(self):\n        self.replacements: typing.List[ModifySpec] = []\n\n    def load(self, loader):\n        loader.add_option(\n            \"modify_headers\", typing.Sequence[str], [],\n            \"\"\"\n            Header modify pattern of the form \"[/flow-filter]/header-name/[@]header-value\", where the\n            separator can be any character. The @ allows to provide a file path that is used to read\n            the header value string. An empty header-value removes existing header-name headers.\n            \"\"\"\n        )\n\n    def configure(self, updated):\n        if \"modify_headers\" in updated:\n            self.replacements = []\n            for option in ctx.options.modify_headers:\n                try:\n                    spec = parse_modify_spec(option, False)\n                except ValueError as e:\n                    raise exceptions.OptionsError(f\"Cannot parse modify_headers option {option}: {e}\") from e\n                self.replacements.append(spec)\n\n    def request(self, flow):\n        if not flow.reply.has_message:\n            self.run(flow, flow.request.headers)\n\n    def response(self, flow):\n        if not flow.reply.has_message:\n            self.run(flow, flow.response.headers)\n\n    def run(self, flow: http.HTTPFlow, hdrs: Headers) -> None:\n        # unset all specified headers\n        for spec in self.replacements:\n            if spec.matches(flow):\n                hdrs.pop(spec.subject, None)\n\n        # set all specified headers if the replacement string is not empty\n        for spec in self.replacements:\n            if spec.matches(flow):\n                try:\n                    replacement = spec.read_replacement()\n                except OSError as e:\n                    ctx.log.warn(f\"Could not read replacement file: {e}\")\n                    continue\n                else:\n                    if replacement:\n                        hdrs.add(spec.subject, replacement)\n", "path": "mitmproxy/addons/modifyheaders.py"}]}