Repository navigation
Conversation
…ttps URLs urllib.request could not authenticate with a proxy for an https URL using ProxyBasicAuthHandler or ProxyDigestAuthHandler: http.client raised a plain OSError when the proxy answered the CONNECT request with 407, so the http_error_407 handlers never ran. * http.client: add ProxyTunnelError, an OSError subclass carrying the code, reason and headers of the proxy's response. It holds no socket and can be pickled. * urllib.request: do_open() passes a 407 to CONNECT on to the error handlers, so the request is retried with Proxy-Authorization on the CONNECT. Other CONNECT failures still raise URLError. * Request.set_proxy() keeps the tunnel when a request is re-opened, so the retried request still sends the path, not the absolute URL. * ProxyDigestAuthHandler computes the digest over the CONNECT request (CONNECT host:port) when tunnelling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Documentation build overview
4 files changed± library/http.client.html± library/urllib.request.html± whatsnew/3.16.html± whatsnew/changelog.html |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Python's Proxy Handler when it sent an authentication request simply failed as discussed in gh-51540.
ProxyBasicAuthHandlerandProxyDigestAuthHandlercould not authenticate with a proxy for anhttpsURL.When the proxy answered the CONNECT request with
407 Proxy Authentication Required,http.clientraised a plainOSError,do_open()wrapped it inURLError, and thehttp_error_407handlers never ran. Only credentials embedded in the proxy URL worked (the 2009 fix on this issue).With this change, a 407 sent by the origin through an established tunnel is still handled like one from the proxy; the proxy credentials are sent only on the CONNECT, never to the origin. This is documented on both
http_error_407methods and covered by a test.Changes
http.client: addProxyTunnelError, anOSErrorsubclass raised when the proxy rejects CONNECT. It carriescode,reasonandheaders; the message is unchanged, soexcept OSErrorkeeps working. It holds no socket (the connection is closed before it is raised), which addresses the concern raised on the issue about exceptions that keep a socket open, and it can be pickled.urllib.request.AbstractHTTPHandler.do_open(): a 407 to CONNECT is returned as an empty-bodied response, so the error handlers run and the request is retried withProxy-Authorizationon the CONNECT. Without credentials the caller now getsHTTPError407 instead ofURLError. Other CONNECT failures still raiseURLError.Request.set_proxy(): re-opening a tunnelled request (as any retry does) switched it totype='http'with the absolute URL as selector, so the retried request inside the tunnel was sent asGET https://host/path. It now keeps the tunnel.AbstractDigestAuthHandler.get_authorization(): when tunnelling, the digest is computed over the CONNECT request (CONNECT host:port, RFC 7616 §3.4) rather than the request for the origin, so strict proxies accept it.🤖 Generated with Claude Code