diff --git a/visidata/loaders/archive.py b/visidata/loaders/archive.py index ffb156077..a3fab9ea7 100644 --- a/visidata/loaders/archive.py +++ b/visidata/loaders/archive.py @@ -77,6 +77,12 @@ def openZipFile(self, fp, *args, **kwargs): pwd = vd.input(f'{args[0].filename} is encrypted, enter password: ', display=False) return zip_open(*args, **kwargs, pwd=pwd.encode('utf-8')) vd.exceptionCaught(err) + except urllib.error.HTTPError as err: + if err.status is None: + vd.fail(f'cannot open URL: {err.msg}') + else: + vd.fail(f'cannot open URL: HTTP Error {err.status}: {err.msg}') + def openRow(self, row): fi, zpath = row diff --git a/visidata/loaders/unzip_http.py b/visidata/loaders/unzip_http.py index 30035b4e3..d2adb1307 100644 --- a/visidata/loaders/unzip_http.py +++ b/visidata/loaders/unzip_http.py @@ -52,6 +52,7 @@ import argparse import pathlib import urllib.parse +import urllib.error from visidata import vd @@ -149,7 +150,20 @@ def namelist(self): return list(r.filename for r in self.infoiter()) def infoiter(self): - resp = self.http.request('HEAD', self.url) + urllib3 = vd.importExternal('urllib3') + try: + resp = self.http.request('HEAD', self.url) + except urllib3.exceptions.HTTPError as e: + code = None + msg = f'urllib3.error.{e.__name__}' + hdrs = fp = None + # transform to HTTPError in urllib, instead of urllib3, to avoid caller needing urllib3 + raise urllib.error.HTTPError(self.url, code, msg, hdrs, fp) + if not (200 <= resp.status <= 299): + code = resp.status + msg = 'HEAD request status not in range 200-299' + hdrs = fp = None + raise urllib.error.HTTPError(self.url, code, msg, hdrs, fp) r = resp.headers.get('Accept-Ranges', '') if r != 'bytes': hostname = urllib.parse.urlparse(self.url).netloc @@ -231,7 +245,13 @@ def extractall(self, path=None, members=None, pwd=None): self.extract(fn, path, pwd=pwd) def get_range(self, start, n): - return self.http.request('GET', self.url, headers={'Range': f'bytes={start}-{start+n-1}'}, preload_content=False) + try: + return self.http.request('GET', self.url, headers={'Range': f'bytes={start}-{start+n-1}'}, preload_content=False) + except urllib3.exceptions.HTTPError as e: + code = None + msg = f'urllib3.error.{e.__name__}' + hdrs = fp = None + raise urllib.error.HTTPError(self.url, code, msg, hdrs, fp) def matching_files(self, *globs): for f in self.files.values():