From 9509acc4909246cc4b54e1097f7e948156dde42c Mon Sep 17 00:00:00 2001 From: belikor Date: Sun, 15 Aug 2021 18:09:18 -0500 Subject: [PATCH] file_manager: raise new `InvalidStreamURLError` if the URL is invalid When using `lbrynet get URL`, if the URL is not a valid URL the function `url.URL.parse` will raise a `ValueError` exception which will produce a whole backtrace. For example, this is the case if we provide a channel name with a forward slash but without a stream name. ``` lbrynet get @Non-existing/ ``` ``` Traceback (most recent call last): File "/opt/git/lbry-sdk/lbry/file/file_manager.py", line 84, in download_from_uri if not URL.parse(uri).has_stream: File "/opt/git/lbry-sdk/lbry/schema/url.py", line 114, in parse raise ValueError('Invalid LBRY URL') ValueError: Invalid LBRY URL WARNING lbry.extras.daemon.daemon:1110: Error downloading Non-existing/: Invalid LBRY URL ``` Now we raise a new `InvalidStreamURLError` which can be trapped in the upper functions that use `url.URL.parse` such as `FileManager.download_from_uri`. If we do this the traceback won't be shown. ``` WARNING lbry.file.file_manager:252: Failed to download Non-existing/: Invalid LBRY stream URL: '@Non-existing/' WARNING lbry.extras.daemon.daemon:1110: Error downloading Non-existing/: Invalid LBRY stream URL: '@Non-existing/' ``` This handles the case when trying to download only "channel" parts without the claim part. ``` lbrynet get @Non-existing lbrynet get @Non-existing/ lbrynet get Non-existing/ ``` --- lbry/error/README.md | 1 + lbry/error/__init__.py | 10 ++++++++++ lbry/file/file_manager.py | 10 +++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/lbry/error/README.md b/lbry/error/README.md index 63bd77f3f..cc5ab7a3b 100644 --- a/lbry/error/README.md +++ b/lbry/error/README.md @@ -38,6 +38,7 @@ Code | Name | Message 114 | InputStringIsBlank | {argument} cannot be blank. 115 | EmptyPublishedFile | Cannot publish empty file: {file_path} 116 | MissingPublishedFile | File does not exist: {file_path} +117 | InvalidStreamURL | Invalid LBRY stream URL: '{url}' -- When an URL cannot be downloaded, such as '@Channel/' or a collection **2xx** | Configuration | Configuration errors. 201 | ConfigWrite | Cannot write configuration file '{path}'. -- When writing the default config fails on startup, such as due to permission issues. 202 | ConfigRead | Cannot find provided configuration file '{path}'. -- Can't open the config file user provided via command line args. diff --git a/lbry/error/__init__.py b/lbry/error/__init__.py index f8c9d3165..7e18f5bf9 100644 --- a/lbry/error/__init__.py +++ b/lbry/error/__init__.py @@ -105,6 +105,16 @@ class MissingPublishedFileError(InputValueError): super().__init__(f"File does not exist: {file_path}") +class InvalidStreamURLError(InputValueError): + """ + When an URL cannot be downloaded, such as '@Channel/' or a collection + """ + + def __init__(self, url): + self.url = url + super().__init__(f"Invalid LBRY stream URL: '{url}'") + + class ConfigurationError(BaseError): """ Configuration errors. diff --git a/lbry/file/file_manager.py b/lbry/file/file_manager.py index eafba2f11..6b398d975 100644 --- a/lbry/file/file_manager.py +++ b/lbry/file/file_manager.py @@ -5,6 +5,7 @@ from typing import Optional from aiohttp.web import Request from lbry.error import ResolveError, DownloadSDTimeoutError, InsufficientFundsError from lbry.error import ResolveTimeoutError, DownloadDataTimeoutError, KeyFeeAboveMaxAllowedError +from lbry.error import InvalidStreamURLError from lbry.stream.managed_stream import ManagedStream from lbry.torrent.torrent_manager import TorrentSource from lbry.utils import cache_concurrent @@ -81,8 +82,11 @@ class FileManager: payment = None try: # resolve the claim - if not URL.parse(uri).has_stream: - raise ResolveError("cannot download a channel claim, specify a /path") + try: + if not URL.parse(uri).has_stream: + raise InvalidStreamURLError(uri) + except ValueError: + raise InvalidStreamURLError(uri) try: resolved_result = await asyncio.wait_for( self.wallet_manager.ledger.resolve( @@ -244,7 +248,7 @@ class FileManager: raise error except Exception as err: # forgive data timeout, don't delete stream expected = (DownloadSDTimeoutError, DownloadDataTimeoutError, InsufficientFundsError, - KeyFeeAboveMaxAllowedError) + KeyFeeAboveMaxAllowedError, ResolveError, InvalidStreamURLError) if isinstance(err, expected): log.warning("Failed to download %s: %s", uri, str(err)) elif isinstance(err, asyncio.CancelledError):