We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
UnicodeDecodeError when decoding bad headers
Someone (or some bot) was spamming my sever with requests to potential vulnerabilities.

One of the attacks is for a potential vulnerability in php, which sets the the `x-forwarded-for` header to the following value:
```
}__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\\0\\0\\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:56:"die(md5(DIRECTORY_SEPARATOR));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\\0\\0\\0connection";b:1;}\xf0\xfd\xfd\xfd, ...
```

This leads to this exception:

```
Exception in ASGI application

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py", line 385, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "/usr/local/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py", line 40, in __call__
    x_forwarded_for = headers[b"x-forwarded-for"].decode("ascii")
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf0 in position 427: ordinal not in range(128)
```

As it's due to malformed header from the client, I would expect this should be a 400 error instead?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `uvicorn/middleware/proxy_headers.py`
Content:
```
1 """
2 This middleware can be used when a known proxy is fronting the application,
3 and is trusted to be properly setting the `X-Forwarded-Proto` and
4 `X-Forwarded-For` headers with the connecting client information.
5 
6 Modifies the `client` and `scheme` information so that they reference
7 the connecting client, rather that the connecting proxy.
8 
9 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Proxies
10 """
11 
12 
13 class ProxyHeadersMiddleware:
14     def __init__(self, app, trusted_hosts="127.0.0.1"):
15         self.app = app
16         if isinstance(trusted_hosts, str):
17             self.trusted_hosts = [item.strip() for item in trusted_hosts.split(",")]
18         else:
19             self.trusted_hosts = trusted_hosts
20         self.always_trust = "*" in self.trusted_hosts
21 
22     async def __call__(self, scope, receive, send):
23         if scope["type"] in ("http", "websocket"):
24             client_addr = scope.get("client")
25             client_host = client_addr[0] if client_addr else None
26 
27             if self.always_trust or client_host in self.trusted_hosts:
28                 headers = dict(scope["headers"])
29 
30                 if b"x-forwarded-proto" in headers:
31                     # Determine if the incoming request was http or https based on
32                     # the X-Forwarded-Proto header.
33                     x_forwarded_proto = headers[b"x-forwarded-proto"].decode("ascii")
34                     scope["scheme"] = x_forwarded_proto.strip()
35 
36                 if b"x-forwarded-for" in headers:
37                     # Determine the client address from the last trusted IP in the
38                     # X-Forwarded-For header. We've lost the connecting client's port
39                     # information by now, so only include the host.
40                     x_forwarded_for = headers[b"x-forwarded-for"].decode("ascii")
41                     host = x_forwarded_for.split(",")[-1].strip()
42                     port = 0
43                     scope["client"] = (host, port)
44 
45         return await self.app(scope, receive, send)
46
```
--- 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/uvicorn/middleware/proxy_headers.py b/uvicorn/middleware/proxy_headers.py
--- a/uvicorn/middleware/proxy_headers.py
+++ b/uvicorn/middleware/proxy_headers.py
@@ -30,14 +30,14 @@
                 if b"x-forwarded-proto" in headers:
                     # Determine if the incoming request was http or https based on
                     # the X-Forwarded-Proto header.
-                    x_forwarded_proto = headers[b"x-forwarded-proto"].decode("ascii")
+                    x_forwarded_proto = headers[b"x-forwarded-proto"].decode("latin1")
                     scope["scheme"] = x_forwarded_proto.strip()
 
                 if b"x-forwarded-for" in headers:
                     # Determine the client address from the last trusted IP in the
                     # X-Forwarded-For header. We've lost the connecting client's port
                     # information by now, so only include the host.
-                    x_forwarded_for = headers[b"x-forwarded-for"].decode("ascii")
+                    x_forwarded_for = headers[b"x-forwarded-for"].decode("latin1")
                     host = x_forwarded_for.split(",")[-1].strip()
                     port = 0
                     scope["client"] = (host, port)

{"golden_diff": "diff --git a/uvicorn/middleware/proxy_headers.py b/uvicorn/middleware/proxy_headers.py\n--- a/uvicorn/middleware/proxy_headers.py\n+++ b/uvicorn/middleware/proxy_headers.py\n@@ -30,14 +30,14 @@\n                 if b\"x-forwarded-proto\" in headers:\n                     # Determine if the incoming request was http or https based on\n                     # the X-Forwarded-Proto header.\n-                    x_forwarded_proto = headers[b\"x-forwarded-proto\"].decode(\"ascii\")\n+                    x_forwarded_proto = headers[b\"x-forwarded-proto\"].decode(\"latin1\")\n                     scope[\"scheme\"] = x_forwarded_proto.strip()\n \n                 if b\"x-forwarded-for\" in headers:\n                     # Determine the client address from the last trusted IP in the\n                     # X-Forwarded-For header. We've lost the connecting client's port\n                     # information by now, so only include the host.\n-                    x_forwarded_for = headers[b\"x-forwarded-for\"].decode(\"ascii\")\n+                    x_forwarded_for = headers[b\"x-forwarded-for\"].decode(\"latin1\")\n                     host = x_forwarded_for.split(\",\")[-1].strip()\n                     port = 0\n                     scope[\"client\"] = (host, port)\n", "issue": "UnicodeDecodeError when decoding bad headers\nSomeone (or some bot) was spamming my sever with requests to potential vulnerabilities.\r\n\r\nOne of the attacks is for a potential vulnerability in php, which sets the the `x-forwarded-for` header to the following value:\r\n```\r\n}__test|O:21:\"JDatabaseDriverMysqli\":3:{s:2:\"fc\";O:17:\"JSimplepieFactory\":0:{}s:21:\"\\\\0\\\\0\\\\0disconnectHandlers\";a:1:{i:0;a:2:{i:0;O:9:\"SimplePie\":5:{s:8:\"sanitize\";O:20:\"JDatabaseDriverMysql\":0:{}s:8:\"feed_url\";s:56:\"die(md5(DIRECTORY_SEPARATOR));JFactory::getConfig();exit\";s:19:\"cache_name_function\";s:6:\"assert\";s:5:\"cache\";b:1;s:11:\"cache_class\";O:20:\"JDatabaseDriverMysql\":0:{}}i:1;s:4:\"init\";}}s:13:\"\\\\0\\\\0\\\\0connection\";b:1;}\\xf0\\xfd\\xfd\\xfd, ...\r\n```\r\n\r\nThis leads to this exception:\r\n\r\n```\r\nException in ASGI application\r\n\r\nTraceback (most recent call last):\r\n  File \"/usr/local/lib/python3.8/site-packages/uvicorn/protocols/http/httptools_impl.py\", line 385, in run_asgi\r\n    result = await app(self.scope, self.receive, self.send)\r\n  File \"/usr/local/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py\", line 40, in __call__\r\n    x_forwarded_for = headers[b\"x-forwarded-for\"].decode(\"ascii\")\r\nUnicodeDecodeError: 'ascii' codec can't decode byte 0xf0 in position 427: ordinal not in range(128)\r\n```\r\n\r\nAs it's due to malformed header from the client, I would expect this should be a 400 error instead?\n", "before_files": [{"content": "\"\"\"\nThis middleware can be used when a known proxy is fronting the application,\nand is trusted to be properly setting the `X-Forwarded-Proto` and\n`X-Forwarded-For` headers with the connecting client information.\n\nModifies the `client` and `scheme` information so that they reference\nthe connecting client, rather that the connecting proxy.\n\nhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Proxies\n\"\"\"\n\n\nclass ProxyHeadersMiddleware:\n    def __init__(self, app, trusted_hosts=\"127.0.0.1\"):\n        self.app = app\n        if isinstance(trusted_hosts, str):\n            self.trusted_hosts = [item.strip() for item in trusted_hosts.split(\",\")]\n        else:\n            self.trusted_hosts = trusted_hosts\n        self.always_trust = \"*\" in self.trusted_hosts\n\n    async def __call__(self, scope, receive, send):\n        if scope[\"type\"] in (\"http\", \"websocket\"):\n            client_addr = scope.get(\"client\")\n            client_host = client_addr[0] if client_addr else None\n\n            if self.always_trust or client_host in self.trusted_hosts:\n                headers = dict(scope[\"headers\"])\n\n                if b\"x-forwarded-proto\" in headers:\n                    # Determine if the incoming request was http or https based on\n                    # the X-Forwarded-Proto header.\n                    x_forwarded_proto = headers[b\"x-forwarded-proto\"].decode(\"ascii\")\n                    scope[\"scheme\"] = x_forwarded_proto.strip()\n\n                if b\"x-forwarded-for\" in headers:\n                    # Determine the client address from the last trusted IP in the\n                    # X-Forwarded-For header. We've lost the connecting client's port\n                    # information by now, so only include the host.\n                    x_forwarded_for = headers[b\"x-forwarded-for\"].decode(\"ascii\")\n                    host = x_forwarded_for.split(\",\")[-1].strip()\n                    port = 0\n                    scope[\"client\"] = (host, port)\n\n        return await self.app(scope, receive, send)\n", "path": "uvicorn/middleware/proxy_headers.py"}], "after_files": [{"content": "\"\"\"\nThis middleware can be used when a known proxy is fronting the application,\nand is trusted to be properly setting the `X-Forwarded-Proto` and\n`X-Forwarded-For` headers with the connecting client information.\n\nModifies the `client` and `scheme` information so that they reference\nthe connecting client, rather that the connecting proxy.\n\nhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Proxies\n\"\"\"\n\n\nclass ProxyHeadersMiddleware:\n    def __init__(self, app, trusted_hosts=\"127.0.0.1\"):\n        self.app = app\n        if isinstance(trusted_hosts, str):\n            self.trusted_hosts = [item.strip() for item in trusted_hosts.split(\",\")]\n        else:\n            self.trusted_hosts = trusted_hosts\n        self.always_trust = \"*\" in self.trusted_hosts\n\n    async def __call__(self, scope, receive, send):\n        if scope[\"type\"] in (\"http\", \"websocket\"):\n            client_addr = scope.get(\"client\")\n            client_host = client_addr[0] if client_addr else None\n\n            if self.always_trust or client_host in self.trusted_hosts:\n                headers = dict(scope[\"headers\"])\n\n                if b\"x-forwarded-proto\" in headers:\n                    # Determine if the incoming request was http or https based on\n                    # the X-Forwarded-Proto header.\n                    x_forwarded_proto = headers[b\"x-forwarded-proto\"].decode(\"latin1\")\n                    scope[\"scheme\"] = x_forwarded_proto.strip()\n\n                if b\"x-forwarded-for\" in headers:\n                    # Determine the client address from the last trusted IP in the\n                    # X-Forwarded-For header. We've lost the connecting client's port\n                    # information by now, so only include the host.\n                    x_forwarded_for = headers[b\"x-forwarded-for\"].decode(\"latin1\")\n                    host = x_forwarded_for.split(\",\")[-1].strip()\n                    port = 0\n                    scope[\"client\"] = (host, port)\n\n        return await self.app(scope, receive, send)\n", "path": "uvicorn/middleware/proxy_headers.py"}]}