prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Proxy Middleware grabs the last IP in `x-forwarded-for`, not the first
  https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For says the first IP in is a client IP, but ProxyHeadersMiddleware grabs the last IP:
  https://github.com/encode/uvicorn/blob/9d9f8820a8155e36dcb5e4d4023f470e51aa4e03/uvicorn/middleware/proxy_headers.py#L41
  
  --- 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("latin1")
  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("latin1")
  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()
  
  ```
  
golden_diff: 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
  @@ -8,17 +8,28 @@
   
   https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Proxies
   """
  +from typing import List
   
   
   class ProxyHeadersMiddleware:
       def __init__(self, app, trusted_hosts="127.0.0.1"):
           self.app = app
           if isinstance(trusted_hosts, str):
  -            self.trusted_hosts = [item.strip() for item in trusted_hosts.split(",")]
  +            self.trusted_hosts = {item.strip() for item in trusted_hosts.split(",")}
           else:
  -            self.trusted_hosts = trusted_hosts
  +            self.trusted_hosts = set(trusted_hosts)
           self.always_trust = "*" in self.trusted_hosts
   
  +    def get_trusted_client_host(
  +        self, x_forwarded_for_hosts
  +    ):  # type: (List[str]) -> str
  +        if self.always_trust:
  +            return x_forwarded_for_hosts[0]
  +
  +        for host in reversed(x_forwarded_for_hosts):
  +            if host not in self.trusted_hosts:
  +                return host
  +
       async def __call__(self, scope, receive, send):
           if scope["type"] in ("http", "websocket"):
               client_addr = scope.get("client")
  @@ -38,7 +49,10 @@
                       # 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("latin1")
  -                    host = x_forwarded_for.split(",")[-1].strip()
  +                    x_forwarded_for_hosts = [
  +                        item.strip() for item in x_forwarded_for.split(",")
  +                    ]
  +                    host = self.get_trusted_client_host(x_forwarded_for_hosts)
                       port = 0
                       scope["client"] = (host, port)
  
verification_info: {"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@@ -8,17 +8,28 @@\n \n https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Proxies\n \"\"\"\n+from typing import List\n \n \n class 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+            self.trusted_hosts = {item.strip() for item in trusted_hosts.split(\",\")}\n         else:\n-            self.trusted_hosts = trusted_hosts\n+            self.trusted_hosts = set(trusted_hosts)\n         self.always_trust = \"*\" in self.trusted_hosts\n \n+    def get_trusted_client_host(\n+        self, x_forwarded_for_hosts\n+    ):  # type: (List[str]) -> str\n+        if self.always_trust:\n+            return x_forwarded_for_hosts[0]\n+\n+        for host in reversed(x_forwarded_for_hosts):\n+            if host not in self.trusted_hosts:\n+                return host\n+\n     async def __call__(self, scope, receive, send):\n         if scope[\"type\"] in (\"http\", \"websocket\"):\n             client_addr = scope.get(\"client\")\n@@ -38,7 +49,10 @@\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+                    x_forwarded_for_hosts = [\n+                        item.strip() for item in x_forwarded_for.split(\",\")\n+                    ]\n+                    host = self.get_trusted_client_host(x_forwarded_for_hosts)\n                     port = 0\n                     scope[\"client\"] = (host, port)\n", "issue": "Proxy Middleware grabs the last IP in `x-forwarded-for`, not the first\nhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For says the first IP in is a client IP, but ProxyHeadersMiddleware grabs the last IP:\r\nhttps://github.com/encode/uvicorn/blob/9d9f8820a8155e36dcb5e4d4023f470e51aa4e03/uvicorn/middleware/proxy_headers.py#L41\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(\"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"}], "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\"\"\"\nfrom typing import List\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 = set(trusted_hosts)\n        self.always_trust = \"*\" in self.trusted_hosts\n\n    def get_trusted_client_host(\n        self, x_forwarded_for_hosts\n    ):  # type: (List[str]) -> str\n        if self.always_trust:\n            return x_forwarded_for_hosts[0]\n\n        for host in reversed(x_forwarded_for_hosts):\n            if host not in self.trusted_hosts:\n                return host\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                    x_forwarded_for_hosts = [\n                        item.strip() for item in x_forwarded_for.split(\",\")\n                    ]\n                    host = self.get_trusted_client_host(x_forwarded_for_hosts)\n                    port = 0\n                    scope[\"client\"] = (host, port)\n\n        return await self.app(scope, receive, send)\n", "path": "uvicorn/middleware/proxy_headers.py"}]}