We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Improper handling of Punycode
#### Problem Description
Can't open an address like `https://стопкоронавирус.рф/` through `mitmproxy` or other applications. My upstream proxy receives a CONNECT request to https://СЃС‚РѕРїРєРѕСЂРѕРЅР°РІРёСЂСѓСЃ.СЂС„:443 instead. As the current run of `mitmproxy` was supposed to be just a test, it was configured only to forward all requests as-is to the upstream proxy, so this rules out any and all issues that could arise from my tinkering. Note: the actual URL that the browser opens is `https://xn--80aesfpebagmfblc0a.xn--p1ai` in this case.

Did it fail to properly encode the resulting authority? My upstream proxy normally has no issues with opening Puny-encoded URLs. I can verify that by opening that URL bypassing `mitmproxy`. It looks like it uses the wrong encoding, as it reminds me of the time when Unicode was not widespread and so this is how text in Russian would display when the text encoding wasn't set correctly.

#### Steps to reproduce the behavior:
1. Configure `mitmproxy` to forward all requests as-is to the upstream proxy that optionally can report what requests it receives. This includes no HTTPS decryption.
2. Navigate your browser to `https://стопкоронавирус.рф/`.
3. Check what the authority part of the URL the upstream proxy gets, it should be mangled.

#### System Information
Paste the output of "mitmproxy --version" here.

```Mitmproxy: 8.0.0 binary
Python:    3.10.2
OpenSSL:   OpenSSL 1.1.1n  15 Mar 2022
Platform:  Windows-10-10.0.19043-SP0
```

--- 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/proxy/layers/http/_upstream_proxy.py`
Content:
```
1 import time
2 from typing import Optional
3 
4 from h11._receivebuffer import ReceiveBuffer
5 
6 from mitmproxy import http, connection
7 from mitmproxy.net.http import http1
8 from mitmproxy.proxy import commands, context, layer, tunnel
9 from mitmproxy.proxy.layers.http._hooks import HttpConnectUpstreamHook
10 from mitmproxy.proxy.layers import tls
11 from mitmproxy.utils import human
12 
13 
14 class HttpUpstreamProxy(tunnel.TunnelLayer):
15     buf: ReceiveBuffer
16     send_connect: bool
17     conn: connection.Server
18     tunnel_connection: connection.Server
19 
20     def __init__(
21         self, ctx: context.Context, tunnel_conn: connection.Server, send_connect: bool
22     ):
23         super().__init__(ctx, tunnel_connection=tunnel_conn, conn=ctx.server)
24         self.buf = ReceiveBuffer()
25         self.send_connect = send_connect
26 
27     @classmethod
28     def make(cls, ctx: context.Context, send_connect: bool) -> tunnel.LayerStack:
29         spec = ctx.server.via
30         assert spec
31         assert spec.scheme in ("http", "https")
32 
33         http_proxy = connection.Server(spec.address)
34 
35         stack = tunnel.LayerStack()
36         if spec.scheme == "https":
37             http_proxy.alpn_offers = tls.HTTP1_ALPNS
38             http_proxy.sni = spec.address[0]
39             stack /= tls.ServerTLSLayer(ctx, http_proxy)
40         stack /= cls(ctx, http_proxy, send_connect)
41 
42         return stack
43 
44     def start_handshake(self) -> layer.CommandGenerator[None]:
45         if not self.send_connect:
46             return (yield from super().start_handshake())
47         assert self.conn.address
48         flow = http.HTTPFlow(self.context.client, self.tunnel_connection)
49         flow.request = http.Request(
50             host=self.conn.address[0],
51             port=self.conn.address[1],
52             method=b"CONNECT",
53             scheme=b"",
54             authority=f"{self.conn.address[0]}:{self.conn.address[1]}".encode(),
55             path=b"",
56             http_version=b"HTTP/1.1",
57             headers=http.Headers(),
58             content=b"",
59             trailers=None,
60             timestamp_start=time.time(),
61             timestamp_end=time.time(),
62         )
63         yield HttpConnectUpstreamHook(flow)
64         raw = http1.assemble_request(flow.request)
65         yield commands.SendData(self.tunnel_connection, raw)
66 
67     def receive_handshake_data(
68         self, data: bytes
69     ) -> layer.CommandGenerator[tuple[bool, Optional[str]]]:
70         if not self.send_connect:
71             return (yield from super().receive_handshake_data(data))
72         self.buf += data
73         response_head = self.buf.maybe_extract_lines()
74         if response_head:
75             response_head = [
76                 bytes(x) for x in response_head
77             ]  # TODO: Make url.parse compatible with bytearrays
78             try:
79                 response = http1.read_response_head(response_head)
80             except ValueError as e:
81                 proxyaddr = human.format_address(self.tunnel_connection.address)
82                 yield commands.Log(f"{proxyaddr}: {e}")
83                 return False, f"Error connecting to {proxyaddr}: {e}"
84             if 200 <= response.status_code < 300:
85                 if self.buf:
86                     yield from self.receive_data(bytes(self.buf))
87                     del self.buf
88                 return True, None
89             else:
90                 proxyaddr = human.format_address(self.tunnel_connection.address)
91                 raw_resp = b"\n".join(response_head)
92                 yield commands.Log(f"{proxyaddr}: {raw_resp!r}", level="debug")
93                 return (
94                     False,
95                     f"Upstream proxy {proxyaddr} refused HTTP CONNECT request: {response.status_code} {response.reason}",
96                 )
97         else:
98             return False, None
99
```
--- 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/proxy/layers/http/_upstream_proxy.py b/mitmproxy/proxy/layers/http/_upstream_proxy.py
--- a/mitmproxy/proxy/layers/http/_upstream_proxy.py
+++ b/mitmproxy/proxy/layers/http/_upstream_proxy.py
@@ -46,12 +46,13 @@
             return (yield from super().start_handshake())
         assert self.conn.address
         flow = http.HTTPFlow(self.context.client, self.tunnel_connection)
+        authority = self.conn.address[0].encode("idna") + f":{self.conn.address[1]}".encode()
         flow.request = http.Request(
             host=self.conn.address[0],
             port=self.conn.address[1],
             method=b"CONNECT",
             scheme=b"",
-            authority=f"{self.conn.address[0]}:{self.conn.address[1]}".encode(),
+            authority=authority,
             path=b"",
             http_version=b"HTTP/1.1",
             headers=http.Headers(),

{"golden_diff": "diff --git a/mitmproxy/proxy/layers/http/_upstream_proxy.py b/mitmproxy/proxy/layers/http/_upstream_proxy.py\n--- a/mitmproxy/proxy/layers/http/_upstream_proxy.py\n+++ b/mitmproxy/proxy/layers/http/_upstream_proxy.py\n@@ -46,12 +46,13 @@\n             return (yield from super().start_handshake())\n         assert self.conn.address\n         flow = http.HTTPFlow(self.context.client, self.tunnel_connection)\n+        authority = self.conn.address[0].encode(\"idna\") + f\":{self.conn.address[1]}\".encode()\n         flow.request = http.Request(\n             host=self.conn.address[0],\n             port=self.conn.address[1],\n             method=b\"CONNECT\",\n             scheme=b\"\",\n-            authority=f\"{self.conn.address[0]}:{self.conn.address[1]}\".encode(),\n+            authority=authority,\n             path=b\"\",\n             http_version=b\"HTTP/1.1\",\n             headers=http.Headers(),\n", "issue": "Improper handling of Punycode\n#### Problem Description\r\nCan't open an address like `https://\u0441\u0442\u043e\u043f\u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441.\u0440\u0444/` through `mitmproxy` or other applications. My upstream proxy receives a CONNECT request to https://\u0421\u0403\u0421\u201a\u0420\u0455\u0420\u0457\u0420\u0454\u0420\u0455\u0421\u0402\u0420\u0455\u0420\u0405\u0420\u00b0\u0420\u0406\u0420\u0451\u0421\u0402\u0421\u0453\u0421\u0403.\u0421\u0402\u0421\u201e:443 instead. As the current run of `mitmproxy` was supposed to be just a test, it was configured only to forward all requests as-is to the upstream proxy, so this rules out any and all issues that could arise from my tinkering. Note: the actual URL that the browser opens is `https://xn--80aesfpebagmfblc0a.xn--p1ai` in this case.\r\n\r\nDid it fail to properly encode the resulting authority? My upstream proxy normally has no issues with opening Puny-encoded URLs. I can verify that by opening that URL bypassing `mitmproxy`. It looks like it uses the wrong encoding, as it reminds me of the time when Unicode was not widespread and so this is how text in Russian would display when the text encoding wasn't set correctly.\r\n\r\n#### Steps to reproduce the behavior:\r\n1. Configure `mitmproxy` to forward all requests as-is to the upstream proxy that optionally can report what requests it receives. This includes no HTTPS decryption.\r\n2. Navigate your browser to `https://\u0441\u0442\u043e\u043f\u043a\u043e\u0440\u043e\u043d\u0430\u0432\u0438\u0440\u0443\u0441.\u0440\u0444/`.\r\n3. Check what the authority part of the URL the upstream proxy gets, it should be mangled.\r\n\r\n#### System Information\r\nPaste the output of \"mitmproxy --version\" here.\r\n\r\n```Mitmproxy: 8.0.0 binary\r\nPython:    3.10.2\r\nOpenSSL:   OpenSSL 1.1.1n  15 Mar 2022\r\nPlatform:  Windows-10-10.0.19043-SP0\r\n```\n", "before_files": [{"content": "import time\nfrom typing import Optional\n\nfrom h11._receivebuffer import ReceiveBuffer\n\nfrom mitmproxy import http, connection\nfrom mitmproxy.net.http import http1\nfrom mitmproxy.proxy import commands, context, layer, tunnel\nfrom mitmproxy.proxy.layers.http._hooks import HttpConnectUpstreamHook\nfrom mitmproxy.proxy.layers import tls\nfrom mitmproxy.utils import human\n\n\nclass HttpUpstreamProxy(tunnel.TunnelLayer):\n    buf: ReceiveBuffer\n    send_connect: bool\n    conn: connection.Server\n    tunnel_connection: connection.Server\n\n    def __init__(\n        self, ctx: context.Context, tunnel_conn: connection.Server, send_connect: bool\n    ):\n        super().__init__(ctx, tunnel_connection=tunnel_conn, conn=ctx.server)\n        self.buf = ReceiveBuffer()\n        self.send_connect = send_connect\n\n    @classmethod\n    def make(cls, ctx: context.Context, send_connect: bool) -> tunnel.LayerStack:\n        spec = ctx.server.via\n        assert spec\n        assert spec.scheme in (\"http\", \"https\")\n\n        http_proxy = connection.Server(spec.address)\n\n        stack = tunnel.LayerStack()\n        if spec.scheme == \"https\":\n            http_proxy.alpn_offers = tls.HTTP1_ALPNS\n            http_proxy.sni = spec.address[0]\n            stack /= tls.ServerTLSLayer(ctx, http_proxy)\n        stack /= cls(ctx, http_proxy, send_connect)\n\n        return stack\n\n    def start_handshake(self) -> layer.CommandGenerator[None]:\n        if not self.send_connect:\n            return (yield from super().start_handshake())\n        assert self.conn.address\n        flow = http.HTTPFlow(self.context.client, self.tunnel_connection)\n        flow.request = http.Request(\n            host=self.conn.address[0],\n            port=self.conn.address[1],\n            method=b\"CONNECT\",\n            scheme=b\"\",\n            authority=f\"{self.conn.address[0]}:{self.conn.address[1]}\".encode(),\n            path=b\"\",\n            http_version=b\"HTTP/1.1\",\n            headers=http.Headers(),\n            content=b\"\",\n            trailers=None,\n            timestamp_start=time.time(),\n            timestamp_end=time.time(),\n        )\n        yield HttpConnectUpstreamHook(flow)\n        raw = http1.assemble_request(flow.request)\n        yield commands.SendData(self.tunnel_connection, raw)\n\n    def receive_handshake_data(\n        self, data: bytes\n    ) -> layer.CommandGenerator[tuple[bool, Optional[str]]]:\n        if not self.send_connect:\n            return (yield from super().receive_handshake_data(data))\n        self.buf += data\n        response_head = self.buf.maybe_extract_lines()\n        if response_head:\n            response_head = [\n                bytes(x) for x in response_head\n            ]  # TODO: Make url.parse compatible with bytearrays\n            try:\n                response = http1.read_response_head(response_head)\n            except ValueError as e:\n                proxyaddr = human.format_address(self.tunnel_connection.address)\n                yield commands.Log(f\"{proxyaddr}: {e}\")\n                return False, f\"Error connecting to {proxyaddr}: {e}\"\n            if 200 <= response.status_code < 300:\n                if self.buf:\n                    yield from self.receive_data(bytes(self.buf))\n                    del self.buf\n                return True, None\n            else:\n                proxyaddr = human.format_address(self.tunnel_connection.address)\n                raw_resp = b\"\\n\".join(response_head)\n                yield commands.Log(f\"{proxyaddr}: {raw_resp!r}\", level=\"debug\")\n                return (\n                    False,\n                    f\"Upstream proxy {proxyaddr} refused HTTP CONNECT request: {response.status_code} {response.reason}\",\n                )\n        else:\n            return False, None\n", "path": "mitmproxy/proxy/layers/http/_upstream_proxy.py"}], "after_files": [{"content": "import time\nfrom typing import Optional\n\nfrom h11._receivebuffer import ReceiveBuffer\n\nfrom mitmproxy import http, connection\nfrom mitmproxy.net.http import http1\nfrom mitmproxy.proxy import commands, context, layer, tunnel\nfrom mitmproxy.proxy.layers.http._hooks import HttpConnectUpstreamHook\nfrom mitmproxy.proxy.layers import tls\nfrom mitmproxy.utils import human\n\n\nclass HttpUpstreamProxy(tunnel.TunnelLayer):\n    buf: ReceiveBuffer\n    send_connect: bool\n    conn: connection.Server\n    tunnel_connection: connection.Server\n\n    def __init__(\n        self, ctx: context.Context, tunnel_conn: connection.Server, send_connect: bool\n    ):\n        super().__init__(ctx, tunnel_connection=tunnel_conn, conn=ctx.server)\n        self.buf = ReceiveBuffer()\n        self.send_connect = send_connect\n\n    @classmethod\n    def make(cls, ctx: context.Context, send_connect: bool) -> tunnel.LayerStack:\n        spec = ctx.server.via\n        assert spec\n        assert spec.scheme in (\"http\", \"https\")\n\n        http_proxy = connection.Server(spec.address)\n\n        stack = tunnel.LayerStack()\n        if spec.scheme == \"https\":\n            http_proxy.alpn_offers = tls.HTTP1_ALPNS\n            http_proxy.sni = spec.address[0]\n            stack /= tls.ServerTLSLayer(ctx, http_proxy)\n        stack /= cls(ctx, http_proxy, send_connect)\n\n        return stack\n\n    def start_handshake(self) -> layer.CommandGenerator[None]:\n        if not self.send_connect:\n            return (yield from super().start_handshake())\n        assert self.conn.address\n        flow = http.HTTPFlow(self.context.client, self.tunnel_connection)\n        authority = self.conn.address[0].encode(\"idna\") + f\":{self.conn.address[1]}\".encode()\n        flow.request = http.Request(\n            host=self.conn.address[0],\n            port=self.conn.address[1],\n            method=b\"CONNECT\",\n            scheme=b\"\",\n            authority=authority,\n            path=b\"\",\n            http_version=b\"HTTP/1.1\",\n            headers=http.Headers(),\n            content=b\"\",\n            trailers=None,\n            timestamp_start=time.time(),\n            timestamp_end=time.time(),\n        )\n        yield HttpConnectUpstreamHook(flow)\n        raw = http1.assemble_request(flow.request)\n        yield commands.SendData(self.tunnel_connection, raw)\n\n    def receive_handshake_data(\n        self, data: bytes\n    ) -> layer.CommandGenerator[tuple[bool, Optional[str]]]:\n        if not self.send_connect:\n            return (yield from super().receive_handshake_data(data))\n        self.buf += data\n        response_head = self.buf.maybe_extract_lines()\n        if response_head:\n            response_head = [\n                bytes(x) for x in response_head\n            ]  # TODO: Make url.parse compatible with bytearrays\n            try:\n                response = http1.read_response_head(response_head)\n            except ValueError as e:\n                proxyaddr = human.format_address(self.tunnel_connection.address)\n                yield commands.Log(f\"{proxyaddr}: {e}\")\n                return False, f\"Error connecting to {proxyaddr}: {e}\"\n            if 200 <= response.status_code < 300:\n                if self.buf:\n                    yield from self.receive_data(bytes(self.buf))\n                    del self.buf\n                return True, None\n            else:\n                proxyaddr = human.format_address(self.tunnel_connection.address)\n                raw_resp = b\"\\n\".join(response_head)\n                yield commands.Log(f\"{proxyaddr}: {raw_resp!r}\", level=\"debug\")\n                return (\n                    False,\n                    f\"Upstream proxy {proxyaddr} refused HTTP CONNECT request: {response.status_code} {response.reason}\",\n                )\n        else:\n            return False, None\n", "path": "mitmproxy/proxy/layers/http/_upstream_proxy.py"}]}