Fix FTPDownloadHandler not closing connection after download

download_request() created an FTPClient but never called client.quit()
to close the control connection. On the CommandFailed path, protocol.close()
was also missing, which could leave an open file handle for local-filename
downloads.

Refactored to try/except/else/finally so protocol.close() is called in both
success and CommandFailed paths, and client.quit() is always awaited in the
finally block, with its own exception suppressed to avoid masking the original
error.

Fixes #7602

Co-authored-by: Claude
This commit is contained in:
Sriniketh24 2026-06-25 15:32:36 +05:30
parent dd4549e6f9
commit 31d69cc0e3
1 changed files with 13 additions and 6 deletions

View File

@ -113,15 +113,22 @@ class FTPDownloadHandler(BaseDownloadHandler):
try:
await maybe_deferred_to_future(client.retrieveFile(filepath, protocol))
except CommandFailed as e:
protocol.close()
message = str(e)
if m := _CODE_RE.search(message):
ftpcode = m.group()
httpcode = self.CODE_MAPPING.get(ftpcode, self.CODE_MAPPING["default"])
return Response(url=request.url, status=httpcode, body=message.encode())
raise
protocol.close()
headers = {"local filename": protocol.filename or b"", "size": protocol.size}
body = protocol.filename or protocol.body.read()
respcls = responsetypes.from_args(url=request.url, body=body)
# hints for Headers-related types may need to be fixed to not use AnyStr
return respcls(url=request.url, status=200, body=body, headers=headers) # type: ignore[arg-type]
else:
protocol.close()
headers = {"local filename": protocol.filename or b"", "size": protocol.size}
body = protocol.filename or protocol.body.read()
respcls = responsetypes.from_args(url=request.url, body=body)
# hints for Headers-related types may need to be fixed to not use AnyStr
return respcls(url=request.url, status=200, body=body, headers=headers) # type: ignore[arg-type]
finally:
try:
await maybe_deferred_to_future(client.quit())
except Exception:
pass