summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Hemberger <846186+hemberger@users.noreply.github.com>2023-04-23 04:41:23 (GMT)
committerGitHub <noreply@github.com>2023-04-23 04:41:23 (GMT)
commite38bebb9ee805df6848f42845e71c8da8a821ad3 (patch)
tree312191c65d55298bcab47e335ff1b82bddf5f4c3
parent0fd38917582aae0728e20d8a641e56d9be9270c7 (diff)
downloadcpython-e38bebb9ee805df6848f42845e71c8da8a821ad3.zip
cpython-e38bebb9ee805df6848f42845e71c8da8a821ad3.tar.gz
cpython-e38bebb9ee805df6848f42845e71c8da8a821ad3.tar.bz2
gh-81403: Fix for CacheFTPHandler in urllib (#13951)
bpo-37222: Fix for CacheFTPHandler in urllib A call to FTP.ntransfercmd must be followed by FTP.voidresp to clear the "end transfer" message. Without this, the client and server get out of sync, which will result in an error if the FTP instance is reused to open a second URL. This scenario occurs for even the most basic usage of CacheFTPHandler. Reverts the patch merged as a resolution to bpo-16270 and adds a test case for the CacheFTPHandler in test_urllib2net.py. Co-authored-by: Senthil Kumaran <senthil@python.org>
-rw-r--r--Lib/test/test_urllib2net.py2
-rw-r--r--Lib/urllib/request.py6
2 files changed, 8 insertions, 0 deletions
diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py
index 5da41c3..d8d882b 100644
--- a/Lib/test/test_urllib2net.py
+++ b/Lib/test/test_urllib2net.py
@@ -134,8 +134,10 @@ class OtherNetworkTests(unittest.TestCase):
# They do sometimes catch some major disasters, though.
def test_ftp(self):
+ # Testing the same URL twice exercises the caching in CacheFTPHandler
urls = [
'ftp://www.pythontest.net/README',
+ 'ftp://www.pythontest.net/README',
('ftp://www.pythontest.net/non-existent-file',
None, urllib.error.URLError),
]
diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
index 19e2e5b..5314b3f 100644
--- a/Lib/urllib/request.py
+++ b/Lib/urllib/request.py
@@ -2475,7 +2475,13 @@ class ftpwrapper:
return (ftpobj, retrlen)
def endtransfer(self):
+ if not self.busy:
+ return
self.busy = 0
+ try:
+ self.ftp.voidresp()
+ except ftperrors():
+ pass
def close(self):
self.keepalive = False