| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
FTPHandler.ftp_open() resolved the host with socket.gethostbyname() before connecting. gethostbyname() is IPv4-only, so an ftp:// URL for an IPv6-only host failed there even when the server was reachable. As diagnosed on the tracker in 2009, ftp_open() has no need to resolve the host itself: it is passed to connect_ftp(), then to ftpwrapper, and on to ftplib.FTP.connect(). That uses socket.create_connection(), which resolves via getaddrinfo() and is IPv6-aware. Remove the pre-resolution and let the host flow through unresolved. An unresolvable host now raises socket.gaierror inside ftplib; gaierror is an OSError and therefore in ftplib.all_errors, so ftp_open()'s existing handler still turns it into URLError and callers see the same error type as before.
| Back | FazBrowse Home | New Git URL |
urllib.request.FTPHandler.ftp_open() pre-resolves the host with socket.gethostbyname() before connecting. That function is IPv4-only, so an ftp:// URL pointing at an IPv6-only host fails at the resolve step with a name-resolution error even though the server is reachable over IPv6.
As diagnosed on the tracker (bpo-1675455) back in 2009, ftp_open() has no need to resolve the host itself: it hands the host to connect_ftp(), then to ftpwrapper, and finally to ftplib.FTP.connect(), which connects through socket.create_connection() and resolves via getaddrinfo(). That path is already IPv6-aware. This change removes the pre-resolution so the host flows through unresolved and IPv6-only hosts work.
The one behavior to preserve is the exception type for a bad host. Previously an unresolvable host raised socket.gaierror from gethostbyname() and was turned into URLError. With the pre-resolution gone, the same gaierror is raised deeper, inside ftplib. Because socket.gaierror is a subclass of OSError and therefore a member of ftplib.all_errors, ftp_open()'s existing handler still catches it and re-raises it as URLError, so callers see exactly the same exception type as before.
Tests: test_ftp now asserts the original hostname reaches connect_ftp() rather than a pre-resolved IP; test_ftp_no_hostname_resolution tripwires socket.gethostbyname to prove ftp_open() never calls it; and test_ftp_gaierror asserts the gaierror -> URLError conversion still holds. All three fail on main and pass with this change.