diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/scadere/listen.py | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/src/scadere/listen.py b/src/scadere/listen.py index aa80c32..0777f4a 100644 --- a/src/scadere/listen.py +++ b/src/scadere/listen.py @@ -21,7 +21,7 @@ from functools import partial from urllib.parse import parse_qs, urljoin, urlsplit from xml.etree.ElementTree import (Element as xml_element, SubElement as xml_subelement, - indent, tostring as xml_to_string) + indent, tostring as str_from_xml) from . import __version__ @@ -84,13 +84,14 @@ async def handle(certs, base_url, reader, writer): """Handle HTTP request.""" summaries = tuple(cert.rstrip().split(maxsplit=5) for cert in certs.read_text().splitlines()) - lookup = {f'/{path(hostname, port, issuer, serial)}': + lookup = {urlsplit(urljoin(base_url, + path(hostname, port, issuer, serial))).path: (not_before, not_after, hostname, port, serial, issuer) for not_before, not_after, hostname, port, serial, issuer in summaries} request = await reader.readuntil(b'\r\n') url = request.removeprefix(b'GET ').rsplit(b' HTTP/', 1)[0] - url_parts = urlsplit(url.decode()) + url_parts = urlsplit(urljoin(base_url, url.decode())) domains = tuple(parse_qs(url_parts.query).get('domain', [''])) if not request.startswith(b'GET '): @@ -99,7 +100,9 @@ async def handle(certs, base_url, reader, writer): writer.close() await writer.wait_closed() return - elif url_parts.path == '/': # Atom feed + elif url.startswith(b'//'): # urljoin goes haywire + writer.write(b'HTTP/1.1 404 Not Found\r\n') + elif url_parts.path == urlsplit(base_url).path: # Atom feed writer.write(b'HTTP/1.1 200 OK\r\n') writer.write(b'Content-Type: application/atom+xml\r\n') feed = xml(('feed', {'xmlns': 'http://www.w3.org/2005/Atom'}, @@ -112,9 +115,10 @@ async def handle(certs, base_url, reader, writer): 'version': __version__}, 'Scadere'), *(entry(base_url, cert) - for cert in summaries if cert[2].endswith(domains)))) - content = xml_to_string(feed, 'unicode', xml_declaration=True, - default_namespace=None).encode() + for cert in lookup.values() + if cert[2].endswith(domains)))) + content = str_from_xml(feed, 'unicode', xml_declaration=True, + default_namespace=None).encode() writer.write(f'Content-Length: {len(content)}\r\n\r\n'.encode()) writer.write(content) elif url_parts.path in lookup: # accessible Atom entry's link/ID @@ -134,8 +138,8 @@ async def handle(certs, base_url, reader, writer): ('title', f'TLS certificate - {hostname}:{port}')), ('body', *body(not_before, not_after, hostname, port, serial, issuer)))) - content = xml_to_string(page, 'unicode', xml_declaration=True, - default_namespace=None).encode() + content = str_from_xml(page, 'unicode', xml_declaration=True, + default_namespace=None).encode() writer.write(f'Content-Length: {len(content)}\r\n\r\n'.encode()) writer.write(content) else: @@ -145,7 +149,7 @@ async def handle(certs, base_url, reader, writer): await writer.wait_closed() -async def listen(certs, base_url, host, port): +async def listen(certs, base_url, host, port): # pragma: no cover """Serve HTTP server for TLS certificate expirations' Atom feed.""" server = await start_server(partial(handle, certs, base_url), host, port) async with server: |