diff options
author | Matt Singleton <matt@xcolour.net> | 2022-01-16 20:56:29 -0600 |
---|---|---|
committer | Matt Singleton <matt@xcolour.net> | 2022-01-16 20:56:29 -0600 |
commit | 1ef62c2c3044b5b11dae92a08be5d83a780392b4 (patch) | |
tree | fe1a3f4a3a38e468ee050de50ab38dc67d810135 | |
parent | f02368a8f9218c7aa5b1f60730aeb30a7a4f790e (diff) |
handle error codes and network errors
-rw-r--r-- | TODO.md | 4 | ||||
-rwxr-xr-x | browser.py | 2 | ||||
-rw-r--r-- | error_template.html | 14 | ||||
-rw-r--r-- | gemini.py | 99 | ||||
-rw-r--r-- | page_template.html | 30 | ||||
-rw-r--r-- | style.css | 30 |
6 files changed, 93 insertions, 86 deletions
@@ -3,12 +3,12 @@ - [x] scroll - [ ] highlight and follow links - [x] forward and back - - [ ] url bar + - [x] url bar - [ ] search in page - [x] stdlib url parsing in gemini module - [x] nice typography - [x] html templates - [ ] deal with non utf8 charsets - [ ] handle all response codes - - [ ] errors (4x, 5x) + - [x] errors (4x, 5x) - [ ] search @@ -27,7 +27,7 @@ class GeminiSchemeHandler(QtWebEngineCore.QWebEngineUrlSchemeHandler): print(gem['status'], gem['meta']) buf = QtCore.QBuffer(parent=request) buf.open(QtCore.QIODevice.WriteOnly) - buf.write(gemini.gem2html(gem['body']).encode('utf8')) + buf.write(gemini.gem2html(gem).encode('utf8')) buf.seek(0) buf.close() request.reply(b'text/html', buf) diff --git a/error_template.html b/error_template.html new file mode 100644 index 0000000..3daacb7 --- /dev/null +++ b/error_template.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html lang="en"> + <html> + <head> + <meta charset="$charset"/> + <style type="text/css"> +$css + </style> + </head> + <body> + <h1>$status</h1> + <p>$meta</p> + </body> + </html> @@ -12,16 +12,31 @@ def htmlescape(text: str) -> str: return text.replace('<', '<').replace('>', '>') -def gem2html(gem: str) -> str: - template = string.Template(open('page_template.html').read()) - body = io.StringIO() - parser = fsm.Parser(gem.split('\n'), body) - parser.parse() - html = template.substitute( - body=body.getvalue(), - charset='utf-8', - lang='en', - ) +def gem2html(gem: dict) -> str: + params = { + 'charset': 'utf-8', + 'lang': 'en', + 'css': open('style.css').read() + } + if gem['status'][0] == '2': + template = string.Template(open('page_template.html').read()) + body = io.StringIO() + parser = fsm.Parser(gem['body'].split('\n'), body) + parser.parse() + params['body'] = body.getvalue() + else: + template = string.Template(open('error_template.html').read()) + if gem['status'] == '00': + params['status'] = 'CLIENT ERROR' + elif gem['status'][0] == '4': + params['status'] = gem['status'] + ' TEMPORARY FAILURE' + elif gem['status'][0] == '5': + params['status'] = gem['status'] + ' PERMANENT FAILURE' + else: + params['status'] = 'UNHANDLED STATUS {}'.format(gem['status']) + params['meta'] = gem['meta'] + + html = template.substitute(params) with open('latest.html', 'w') as fp: fp.write(html) return html @@ -42,8 +57,8 @@ def get(url: str, follow_redirects: bool = True) -> dict: while response['status'][0] == '3': count += 1 if count > 20: - raise Exception('Redirect loop') - print('redirect: {}'.format(response['meta'])) + return {'status': '00', 'meta': 'Too many redirects'} + print('{status} {meta}'.format(**response)) response = _get(response['meta']) return response @@ -72,30 +87,36 @@ def _get(url: str) -> dict: url_parts.fragment, )) } - context = ssl.create_default_context() - context.check_hostname = False - context.verify_mode = ssl.CERT_NONE - port = 1965 if url_parts.port is None else url_parts.port - with socket.create_connection((url_parts.hostname, port)) as sock: - with context.wrap_socket(sock, server_hostname=url_parts.hostname) as ssock: - ssock.sendall('{url}\r\n'.format(url=url).encode('utf8')) - fp = ssock.makefile(mode='rb') - header = fp.readline(1027) - parts = header.decode('utf8').split(None, 1) - status = parts[0] - if len(parts) == 1: - meta = '' - else: - meta = parts[1] - if status[0] != '2': - return { - 'status': status, - 'meta': meta.strip(), - } - meta_params = _parse_meta(meta) - body = fp.read() - return { - 'status': status, - 'meta': meta.strip(), - 'body': body.decode(meta_params.get('charset', 'utf8')), - } + try: + context = ssl.create_default_context() + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + port = 1965 if url_parts.port is None else url_parts.port + with socket.create_connection((url_parts.hostname, port)) as sock: + with context.wrap_socket(sock, server_hostname=url_parts.hostname) as ssock: + ssock.sendall('{url}\r\n'.format(url=url).encode('utf8')) + fp = ssock.makefile(mode='rb') + header = fp.readline(1027) + parts = header.decode('utf8').split(None, 1) + status = parts[0] + if len(parts) == 1: + meta = '' + else: + meta = parts[1] + if status[0] != '2': + return { + 'status': status, + 'meta': meta.strip(), + } + meta_params = _parse_meta(meta) + body = fp.read() + return { + 'status': status, + 'meta': meta.strip(), + 'body': body.decode(meta_params.get('charset', 'utf8')), + } + except Exception as ex: + return { + 'status': '00', + 'meta': '{}'.format(ex), + } diff --git a/page_template.html b/page_template.html index 2a4baf5..e049d56 100644 --- a/page_template.html +++ b/page_template.html @@ -4,35 +4,7 @@ <head> <meta charset="$charset"/> <style type="text/css"> -html { - font-size: 18px; - font-family: Garamond, Georgia, sans-serif; -} - -pre { - font-family: Courier, monospace; -} - -blockquote { - border-left: 5px solid #ddd; - padding: 0.6em 0.6em 0.2em; - font-style: italic; -} - -blockquote:before { - content: "\201C"; - display: inline-block; - padding-right: 0.4rem; - font-size: 4em; - line-height: 0; - vertical-align: -0.4em; - color: lightgrey; - margin-right: 0.1em; -} - -li.link::marker { - content: '⇒ '; -} +$css </style> </head> <body> @@ -1,29 +1,29 @@ html { - font-size: 18px; - font-family: Garamond, Georgia, sans-serif; + font-size: 18px; + font-family: Garamond, Georgia, sans-serif; } pre { - font-family: Courier, monospace; + font-family: Courier, monospace; } blockquote { - border-left: 5px solid #ddd; - padding: 0.6em 0.6em 0.2em; - font-style: italic; + border-left: 5px solid #ddd; + padding: 0.6em 0.6em 0.2em; + font-style: italic; } blockquote:before { - content: "\201C"; - display: inline-block; - padding-right: 0.4rem; - font-size: 4em; - line-height: 0; - vertical-align: -0.4em; - color: lightgrey; - margin-right: 0.1em; + content: "\201C"; + display: inline-block; + padding-right: 0.4rem; + font-size: 4em; + line-height: 0; + vertical-align: -0.4em; + color: lightgrey; + margin-right: 0.1em; } li.link::marker { - content: '⇒ '; + content: '⇒ '; } |