Skip to content

Commit ce2e971

Browse files
committed
[http- unzip_http] handle errors in retrieving URLs
Make error output user-friendly, instead of showing a traceback. for errors like: http.client.RemoteDisconnected: "Remote end closed connection without response" and ConnectionError ("[Errno 104] Connection reset by peer"). And urllib3.exceptions.MaxRetryError in get_range() on a closed connection. And HTTP status codes other than success in the zip file HEAD request.
1 parent efbe84e commit ce2e971

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

visidata/loaders/http.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import re
2+
import http.client
23

34
from visidata import Path, RepeatFile, vd, VisiData
45
from visidata.loaders.tsv import splitter
@@ -55,6 +56,8 @@ def openurl_http(vd, path, filetype=None):
5556
vd.fail(f'cannot open URL: HTTP Error {e.code}: {e.reason}')
5657
except urllib.error.URLError as e:
5758
vd.fail(f'cannot open URL: {e.reason}')
59+
except (http.client.HTTPException, ConnectionError) as e:
60+
vd.fail(f'cannot open URL: {e}')
5861

5962
filetype = filetype or vd.guessFiletype(path, response, funcprefix='guessurl_').get('filetype') # try guessing by url
6063
filetype = filetype or vd.guessFiletype(path, funcprefix='guess_').get('filetype') # try guessing by contents

visidata/loaders/unzip_http.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,13 @@ def namelist(self):
149149
return list(r.filename for r in self.infoiter())
150150

151151
def infoiter(self):
152-
resp = self.http.request('HEAD', self.url)
152+
urllib3 = vd.importExternal('urllib3')
153+
try:
154+
resp = self.http.request('HEAD', self.url)
155+
except urllib3.exceptions.HTTPError as e:
156+
vd.fail(f'cannot open URL: HTTP Error {e}')
157+
if not (200 <= resp.status <= 299):
158+
vd.fail(f'cannot open URL: status code {resp.status}')
153159
r = resp.headers.get('Accept-Ranges', '')
154160
if r != 'bytes':
155161
hostname = urllib.parse.urlparse(self.url).netloc
@@ -231,7 +237,11 @@ def extractall(self, path=None, members=None, pwd=None):
231237
self.extract(fn, path, pwd=pwd)
232238

233239
def get_range(self, start, n):
234-
return self.http.request('GET', self.url, headers={'Range': f'bytes={start}-{start+n-1}'}, preload_content=False)
240+
urllib3 = vd.importExternal('urllib3')
241+
try:
242+
return self.http.request('GET', self.url, headers={'Range': f'bytes={start}-{start+n-1}'}, preload_content=False)
243+
except urllib3.exceptions.HTTPError as e:
244+
vd.fail(f'cannot open range for URL: HTTP Error {e}')
235245

236246
def matching_files(self, *globs):
237247
for f in self.files.values():

0 commit comments

Comments
 (0)