prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Away-from-origin redirects should add a new host header
  Prompted by #310
  
  Away-from-origin redirects currently remove the `Host` header, without adding a new one.
  I think we ought to be using `headers['Host'] = url.authority.encode("ascii")` instead of simply deleting the header.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `httpx/middleware.py`
  Content:
  ```
  1 import functools
  2 import typing
  3 from base64 import b64encode
  4 
  5 from .config import DEFAULT_MAX_REDIRECTS
  6 from .exceptions import RedirectBodyUnavailable, RedirectLoop, TooManyRedirects
  7 from .models import URL, AsyncRequest, AsyncResponse, Cookies, Headers
  8 from .status_codes import codes
  9 
  10 
  11 class BaseMiddleware:
  12     async def __call__(
  13         self, request: AsyncRequest, get_response: typing.Callable
  14     ) -> AsyncResponse:
  15         raise NotImplementedError  # pragma: no cover
  16 
  17 
  18 class BasicAuthMiddleware(BaseMiddleware):
  19     def __init__(
  20         self, username: typing.Union[str, bytes], password: typing.Union[str, bytes]
  21     ):
  22         if isinstance(username, str):
  23             username = username.encode("latin1")
  24 
  25         if isinstance(password, str):
  26             password = password.encode("latin1")
  27 
  28         userpass = b":".join((username, password))
  29         token = b64encode(userpass).decode().strip()
  30 
  31         self.authorization_header = f"Basic {token}"
  32 
  33     async def __call__(
  34         self, request: AsyncRequest, get_response: typing.Callable
  35     ) -> AsyncResponse:
  36         request.headers["Authorization"] = self.authorization_header
  37         return await get_response(request)
  38 
  39 
  40 class CustomAuthMiddleware(BaseMiddleware):
  41     def __init__(self, auth: typing.Callable[[AsyncRequest], AsyncRequest]):
  42         self.auth = auth
  43 
  44     async def __call__(
  45         self, request: AsyncRequest, get_response: typing.Callable
  46     ) -> AsyncResponse:
  47         request = self.auth(request)
  48         return await get_response(request)
  49 
  50 
  51 class RedirectMiddleware(BaseMiddleware):
  52     def __init__(
  53         self,
  54         allow_redirects: bool = True,
  55         max_redirects: int = DEFAULT_MAX_REDIRECTS,
  56         cookies: typing.Optional[Cookies] = None,
  57     ):
  58         self.allow_redirects = allow_redirects
  59         self.max_redirects = max_redirects
  60         self.cookies = cookies
  61         self.history: typing.List[AsyncResponse] = []
  62 
  63     async def __call__(
  64         self, request: AsyncRequest, get_response: typing.Callable
  65     ) -> AsyncResponse:
  66         if len(self.history) > self.max_redirects:
  67             raise TooManyRedirects()
  68         if request.url in (response.url for response in self.history):
  69             raise RedirectLoop()
  70 
  71         response = await get_response(request)
  72         response.history = list(self.history)
  73 
  74         if not response.is_redirect:
  75             return response
  76 
  77         self.history.append(response)
  78         next_request = self.build_redirect_request(request, response)
  79 
  80         if self.allow_redirects:
  81             return await self(next_request, get_response)
  82 
  83         response.call_next = functools.partial(self, next_request, get_response)
  84         return response
  85 
  86     def build_redirect_request(
  87         self, request: AsyncRequest, response: AsyncResponse
  88     ) -> AsyncRequest:
  89         method = self.redirect_method(request, response)
  90         url = self.redirect_url(request, response)
  91         headers = self.redirect_headers(request, url, method)  # TODO: merge headers?
  92         content = self.redirect_content(request, method)
  93         cookies = Cookies(self.cookies)
  94         cookies.update(request.cookies)
  95         return AsyncRequest(
  96             method=method, url=url, headers=headers, data=content, cookies=cookies
  97         )
  98 
  99     def redirect_method(self, request: AsyncRequest, response: AsyncResponse) -> str:
  100         """
  101         When being redirected we may want to change the method of the request
  102         based on certain specs or browser behavior.
  103         """
  104         method = request.method
  105 
  106         # https://tools.ietf.org/html/rfc7231#section-6.4.4
  107         if response.status_code == codes.SEE_OTHER and method != "HEAD":
  108             method = "GET"
  109 
  110         # Do what the browsers do, despite standards...
  111         # Turn 302s into GETs.
  112         if response.status_code == codes.FOUND and method != "HEAD":
  113             method = "GET"
  114 
  115         # If a POST is responded to with a 301, turn it into a GET.
  116         # This bizarre behaviour is explained in 'requests' issue 1704.
  117         if response.status_code == codes.MOVED_PERMANENTLY and method == "POST":
  118             method = "GET"
  119 
  120         return method
  121 
  122     def redirect_url(self, request: AsyncRequest, response: AsyncResponse) -> URL:
  123         """
  124         Return the URL for the redirect to follow.
  125         """
  126         location = response.headers["Location"]
  127 
  128         url = URL(location, allow_relative=True)
  129 
  130         # Facilitate relative 'Location' headers, as allowed by RFC 7231.
  131         # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')
  132         if url.is_relative_url:
  133             url = request.url.join(url)
  134 
  135         # Attach previous fragment if needed (RFC 7231 7.1.2)
  136         if request.url.fragment and not url.fragment:
  137             url = url.copy_with(fragment=request.url.fragment)
  138 
  139         return url
  140 
  141     def redirect_headers(self, request: AsyncRequest, url: URL, method: str) -> Headers:
  142         """
  143         Return the headers that should be used for the redirect request.
  144         """
  145         headers = Headers(request.headers)
  146 
  147         if url.origin != request.url.origin:
  148             # Strip Authorization headers when responses are redirected away from
  149             # the origin.
  150             del headers["Authorization"]
  151             del headers["Host"]
  152 
  153         if method != request.method and method == "GET":
  154             # If we've switch to a 'GET' request, then strip any headers which
  155             # are only relevant to the request body.
  156             del headers["Content-Length"]
  157             del headers["Transfer-Encoding"]
  158 
  159         return headers
  160 
  161     def redirect_content(self, request: AsyncRequest, method: str) -> bytes:
  162         """
  163         Return the body that should be used for the redirect request.
  164         """
  165         if method != request.method and method == "GET":
  166             return b""
  167         if request.is_streaming:
  168             raise RedirectBodyUnavailable()
  169         return request.content
  170
  ```
  --- 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/httpx/middleware.py b/httpx/middleware.py
  --- a/httpx/middleware.py
  +++ b/httpx/middleware.py
  @@ -148,7 +148,7 @@
               # Strip Authorization headers when responses are redirected away from
               # the origin.
               del headers["Authorization"]
  -            del headers["Host"]
  +            headers["Host"] = url.authority
   
           if method != request.method and method == "GET":
               # If we've switch to a 'GET' request, then strip any headers which
  
verification_info: {"golden_diff": "diff --git a/httpx/middleware.py b/httpx/middleware.py\n--- a/httpx/middleware.py\n+++ b/httpx/middleware.py\n@@ -148,7 +148,7 @@\n             # Strip Authorization headers when responses are redirected away from\n             # the origin.\n             del headers[\"Authorization\"]\n-            del headers[\"Host\"]\n+            headers[\"Host\"] = url.authority\n \n         if method != request.method and method == \"GET\":\n             # If we've switch to a 'GET' request, then strip any headers which\n", "issue": "Away-from-origin redirects should add a new host header\nPrompted by #310\r\n\r\nAway-from-origin redirects currently remove the `Host` header, without adding a new one.\r\nI think we ought to be using `headers['Host'] = url.authority.encode(\"ascii\")` instead of simply deleting the header.\n", "before_files": [{"content": "import functools\nimport typing\nfrom base64 import b64encode\n\nfrom .config import DEFAULT_MAX_REDIRECTS\nfrom .exceptions import RedirectBodyUnavailable, RedirectLoop, TooManyRedirects\nfrom .models import URL, AsyncRequest, AsyncResponse, Cookies, Headers\nfrom .status_codes import codes\n\n\nclass BaseMiddleware:\n    async def __call__(\n        self, request: AsyncRequest, get_response: typing.Callable\n    ) -> AsyncResponse:\n        raise NotImplementedError  # pragma: no cover\n\n\nclass BasicAuthMiddleware(BaseMiddleware):\n    def __init__(\n        self, username: typing.Union[str, bytes], password: typing.Union[str, bytes]\n    ):\n        if isinstance(username, str):\n            username = username.encode(\"latin1\")\n\n        if isinstance(password, str):\n            password = password.encode(\"latin1\")\n\n        userpass = b\":\".join((username, password))\n        token = b64encode(userpass).decode().strip()\n\n        self.authorization_header = f\"Basic {token}\"\n\n    async def __call__(\n        self, request: AsyncRequest, get_response: typing.Callable\n    ) -> AsyncResponse:\n        request.headers[\"Authorization\"] = self.authorization_header\n        return await get_response(request)\n\n\nclass CustomAuthMiddleware(BaseMiddleware):\n    def __init__(self, auth: typing.Callable[[AsyncRequest], AsyncRequest]):\n        self.auth = auth\n\n    async def __call__(\n        self, request: AsyncRequest, get_response: typing.Callable\n    ) -> AsyncResponse:\n        request = self.auth(request)\n        return await get_response(request)\n\n\nclass RedirectMiddleware(BaseMiddleware):\n    def __init__(\n        self,\n        allow_redirects: bool = True,\n        max_redirects: int = DEFAULT_MAX_REDIRECTS,\n        cookies: typing.Optional[Cookies] = None,\n    ):\n        self.allow_redirects = allow_redirects\n        self.max_redirects = max_redirects\n        self.cookies = cookies\n        self.history: typing.List[AsyncResponse] = []\n\n    async def __call__(\n        self, request: AsyncRequest, get_response: typing.Callable\n    ) -> AsyncResponse:\n        if len(self.history) > self.max_redirects:\n            raise TooManyRedirects()\n        if request.url in (response.url for response in self.history):\n            raise RedirectLoop()\n\n        response = await get_response(request)\n        response.history = list(self.history)\n\n        if not response.is_redirect:\n            return response\n\n        self.history.append(response)\n        next_request = self.build_redirect_request(request, response)\n\n        if self.allow_redirects:\n            return await self(next_request, get_response)\n\n        response.call_next = functools.partial(self, next_request, get_response)\n        return response\n\n    def build_redirect_request(\n        self, request: AsyncRequest, response: AsyncResponse\n    ) -> AsyncRequest:\n        method = self.redirect_method(request, response)\n        url = self.redirect_url(request, response)\n        headers = self.redirect_headers(request, url, method)  # TODO: merge headers?\n        content = self.redirect_content(request, method)\n        cookies = Cookies(self.cookies)\n        cookies.update(request.cookies)\n        return AsyncRequest(\n            method=method, url=url, headers=headers, data=content, cookies=cookies\n        )\n\n    def redirect_method(self, request: AsyncRequest, response: AsyncResponse) -> str:\n        \"\"\"\n        When being redirected we may want to change the method of the request\n        based on certain specs or browser behavior.\n        \"\"\"\n        method = request.method\n\n        # https://tools.ietf.org/html/rfc7231#section-6.4.4\n        if response.status_code == codes.SEE_OTHER and method != \"HEAD\":\n            method = \"GET\"\n\n        # Do what the browsers do, despite standards...\n        # Turn 302s into GETs.\n        if response.status_code == codes.FOUND and method != \"HEAD\":\n            method = \"GET\"\n\n        # If a POST is responded to with a 301, turn it into a GET.\n        # This bizarre behaviour is explained in 'requests' issue 1704.\n        if response.status_code == codes.MOVED_PERMANENTLY and method == \"POST\":\n            method = \"GET\"\n\n        return method\n\n    def redirect_url(self, request: AsyncRequest, response: AsyncResponse) -> URL:\n        \"\"\"\n        Return the URL for the redirect to follow.\n        \"\"\"\n        location = response.headers[\"Location\"]\n\n        url = URL(location, allow_relative=True)\n\n        # Facilitate relative 'Location' headers, as allowed by RFC 7231.\n        # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')\n        if url.is_relative_url:\n            url = request.url.join(url)\n\n        # Attach previous fragment if needed (RFC 7231 7.1.2)\n        if request.url.fragment and not url.fragment:\n            url = url.copy_with(fragment=request.url.fragment)\n\n        return url\n\n    def redirect_headers(self, request: AsyncRequest, url: URL, method: str) -> Headers:\n        \"\"\"\n        Return the headers that should be used for the redirect request.\n        \"\"\"\n        headers = Headers(request.headers)\n\n        if url.origin != request.url.origin:\n            # Strip Authorization headers when responses are redirected away from\n            # the origin.\n            del headers[\"Authorization\"]\n            del headers[\"Host\"]\n\n        if method != request.method and method == \"GET\":\n            # If we've switch to a 'GET' request, then strip any headers which\n            # are only relevant to the request body.\n            del headers[\"Content-Length\"]\n            del headers[\"Transfer-Encoding\"]\n\n        return headers\n\n    def redirect_content(self, request: AsyncRequest, method: str) -> bytes:\n        \"\"\"\n        Return the body that should be used for the redirect request.\n        \"\"\"\n        if method != request.method and method == \"GET\":\n            return b\"\"\n        if request.is_streaming:\n            raise RedirectBodyUnavailable()\n        return request.content\n", "path": "httpx/middleware.py"}], "after_files": [{"content": "import functools\nimport typing\nfrom base64 import b64encode\n\nfrom .config import DEFAULT_MAX_REDIRECTS\nfrom .exceptions import RedirectBodyUnavailable, RedirectLoop, TooManyRedirects\nfrom .models import URL, AsyncRequest, AsyncResponse, Cookies, Headers\nfrom .status_codes import codes\n\n\nclass BaseMiddleware:\n    async def __call__(\n        self, request: AsyncRequest, get_response: typing.Callable\n    ) -> AsyncResponse:\n        raise NotImplementedError  # pragma: no cover\n\n\nclass BasicAuthMiddleware(BaseMiddleware):\n    def __init__(\n        self, username: typing.Union[str, bytes], password: typing.Union[str, bytes]\n    ):\n        if isinstance(username, str):\n            username = username.encode(\"latin1\")\n\n        if isinstance(password, str):\n            password = password.encode(\"latin1\")\n\n        userpass = b\":\".join((username, password))\n        token = b64encode(userpass).decode().strip()\n\n        self.authorization_header = f\"Basic {token}\"\n\n    async def __call__(\n        self, request: AsyncRequest, get_response: typing.Callable\n    ) -> AsyncResponse:\n        request.headers[\"Authorization\"] = self.authorization_header\n        return await get_response(request)\n\n\nclass CustomAuthMiddleware(BaseMiddleware):\n    def __init__(self, auth: typing.Callable[[AsyncRequest], AsyncRequest]):\n        self.auth = auth\n\n    async def __call__(\n        self, request: AsyncRequest, get_response: typing.Callable\n    ) -> AsyncResponse:\n        request = self.auth(request)\n        return await get_response(request)\n\n\nclass RedirectMiddleware(BaseMiddleware):\n    def __init__(\n        self,\n        allow_redirects: bool = True,\n        max_redirects: int = DEFAULT_MAX_REDIRECTS,\n        cookies: typing.Optional[Cookies] = None,\n    ):\n        self.allow_redirects = allow_redirects\n        self.max_redirects = max_redirects\n        self.cookies = cookies\n        self.history: typing.List[AsyncResponse] = []\n\n    async def __call__(\n        self, request: AsyncRequest, get_response: typing.Callable\n    ) -> AsyncResponse:\n        if len(self.history) > self.max_redirects:\n            raise TooManyRedirects()\n        if request.url in (response.url for response in self.history):\n            raise RedirectLoop()\n\n        response = await get_response(request)\n        response.history = list(self.history)\n\n        if not response.is_redirect:\n            return response\n\n        self.history.append(response)\n        next_request = self.build_redirect_request(request, response)\n\n        if self.allow_redirects:\n            return await self(next_request, get_response)\n\n        response.call_next = functools.partial(self, next_request, get_response)\n        return response\n\n    def build_redirect_request(\n        self, request: AsyncRequest, response: AsyncResponse\n    ) -> AsyncRequest:\n        method = self.redirect_method(request, response)\n        url = self.redirect_url(request, response)\n        headers = self.redirect_headers(request, url, method)  # TODO: merge headers?\n        content = self.redirect_content(request, method)\n        cookies = Cookies(self.cookies)\n        cookies.update(request.cookies)\n        return AsyncRequest(\n            method=method, url=url, headers=headers, data=content, cookies=cookies\n        )\n\n    def redirect_method(self, request: AsyncRequest, response: AsyncResponse) -> str:\n        \"\"\"\n        When being redirected we may want to change the method of the request\n        based on certain specs or browser behavior.\n        \"\"\"\n        method = request.method\n\n        # https://tools.ietf.org/html/rfc7231#section-6.4.4\n        if response.status_code == codes.SEE_OTHER and method != \"HEAD\":\n            method = \"GET\"\n\n        # Do what the browsers do, despite standards...\n        # Turn 302s into GETs.\n        if response.status_code == codes.FOUND and method != \"HEAD\":\n            method = \"GET\"\n\n        # If a POST is responded to with a 301, turn it into a GET.\n        # This bizarre behaviour is explained in 'requests' issue 1704.\n        if response.status_code == codes.MOVED_PERMANENTLY and method == \"POST\":\n            method = \"GET\"\n\n        return method\n\n    def redirect_url(self, request: AsyncRequest, response: AsyncResponse) -> URL:\n        \"\"\"\n        Return the URL for the redirect to follow.\n        \"\"\"\n        location = response.headers[\"Location\"]\n\n        url = URL(location, allow_relative=True)\n\n        # Facilitate relative 'Location' headers, as allowed by RFC 7231.\n        # (e.g. '/path/to/resource' instead of 'http://domain.tld/path/to/resource')\n        if url.is_relative_url:\n            url = request.url.join(url)\n\n        # Attach previous fragment if needed (RFC 7231 7.1.2)\n        if request.url.fragment and not url.fragment:\n            url = url.copy_with(fragment=request.url.fragment)\n\n        return url\n\n    def redirect_headers(self, request: AsyncRequest, url: URL, method: str) -> Headers:\n        \"\"\"\n        Return the headers that should be used for the redirect request.\n        \"\"\"\n        headers = Headers(request.headers)\n\n        if url.origin != request.url.origin:\n            # Strip Authorization headers when responses are redirected away from\n            # the origin.\n            del headers[\"Authorization\"]\n            headers[\"Host\"] = url.authority\n\n        if method != request.method and method == \"GET\":\n            # If we've switch to a 'GET' request, then strip any headers which\n            # are only relevant to the request body.\n            del headers[\"Content-Length\"]\n            del headers[\"Transfer-Encoding\"]\n\n        return headers\n\n    def redirect_content(self, request: AsyncRequest, method: str) -> bytes:\n        \"\"\"\n        Return the body that should be used for the redirect request.\n        \"\"\"\n        if method != request.method and method == \"GET\":\n            return b\"\"\n        if request.is_streaming:\n            raise RedirectBodyUnavailable()\n        return request.content\n", "path": "httpx/middleware.py"}]}