From e948ce0a13a016add653d2909c3b891f258e491b Mon Sep 17 00:00:00 2001 From: Solderpunk Date: Mon, 24 Jun 2019 18:04:10 +0300 Subject: [PATCH] Follow redirects. --- gemini-demo.py | 56 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/gemini-demo.py b/gemini-demo.py index 8c6fcb9..28dffcf 100644 --- a/gemini-demo.py +++ b/gemini-demo.py @@ -8,6 +8,15 @@ import urllib.parse menu = [] hist = [] +def absolutise_url(base, relative): + # Absolutise relative links + if "://" not in relative: + # Python's URL tools somehow only work with known schemes? + base = base.replace("gemini://","http://") + relative = urllib.parse.urljoin(base, relative) + relative = relative.replace("http://", "gemini://") + return relative + while True: # Get input cmd = input("> ").strip() @@ -30,22 +39,30 @@ while True: if parsed_url.scheme != "gemini": print("Sorry, Gemini links only.") continue - # Do the Gemini transaction - try: - s = socket.create_connection((parsed_url.netloc, 1965)) - context = ssl.SSLContext() - context.check_hostname = False - context.verify_mode = ssl.CERT_NONE - s = context.wrap_socket(s, server_hostname = parsed_url.netloc) - s.sendall((parsed_url.path + '\r\n').encode("UTF-8")) - except: - print("Network error!") - continue - # Check header and fail if not okay - fp = s.makefile("rb") - header = fp.readline() - header = header.decode("UTF-8").strip() - status, mime = header.split("\t") + # Do the Gemini transaction, following redirects + while True: + try: + s = socket.create_connection((parsed_url.netloc, 1965)) + context = ssl.SSLContext() + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + s = context.wrap_socket(s, server_hostname = parsed_url.netloc) + s.sendall((parsed_url.path + '\r\n').encode("UTF-8")) + except: + print("Network error!") + continue + # Get header and check for redirects + fp = s.makefile("rb") + header = fp.readline() + header = header.decode("UTF-8").strip() + status, mime = header.split("\t") + # If this isn't a redirect, we're done + if not status.startswith("3"): + break + # Follow the redirect + url = absolutise_url(url, mime) + parsed_url = urllib.parse.urlparse(url) + # Fail if transaction was not successful if not status.startswith("2"): print("Error %s: %s" % (status, mime)) continue @@ -63,12 +80,7 @@ while True: for line in body.splitlines(): if line.startswith("\t") and line.count("\t") == 2: _, text, link_url = line.split("\t") - # Absolutise relative links - if "://" not in link_url: - # Python's URL tools somehow only work with known schemes? - base = url.replace("gemini://","http://") - link_url = urllib.parse.urljoin(base, link_url) - link_url = link_url.replace("http://", "gemini://") + link_url = absolutise_url(url, link_url) menu.append(link_url) print("[%d] %s" % (len(menu), text)) else: