A response reached through a proxy can return a relative Location:

Location: ../new/

Modern HTTP allows a URI reference here. Resolve it against the URL that produced the response. If that URL was https://docs.example/catalog/old/, the reference above identifies https://docs.example/catalog/new/. The proxy's hostname is not the base.

For ordinary Python urllib requests, use its redirect handler rather than joining strings around the proxy endpoint:

opener = build_opener(ProxyHandler({
    "https": "http://proxy.example:8080",
}))
with opener.open("https://docs.example/catalog/old/",
                 timeout=15) as response:
    final_url = response.geturl()

For this public-document request with no proxy authentication, an HTTP candidate from the HTTP proxy list can replace the example endpoint when the route is permitted. The classes come from urllib.request. Its normal handler follows supported redirects within its limits. final_url describes the eventual resource URL, not the intermediary used to reach it.

Resolve first, then choose the next route

A redirect can change the destination host or scheme. A destination-based proxy policy therefore needs to evaluate that new URL too. A route that worked for the first host may not be the route for the next one.

When implementing redirect handling yourself, use URI-reference resolution with dot-segment handling. Preserve the method rules of the actual status code and impose a redirect limit. Appending Location to a hostname is not a substitute for that resolution algorithm.

If a redirect fails, retain the requested URL, response status, Location value and resolved next URL. Those four values usually show whether the failure belongs to URL construction or to the connection attempted afterward.

Erthyglow kevrennek