diff --git a/site_server.py b/site_server.py new file mode 100644 index 0000000..a1064eb --- /dev/null +++ b/site_server.py @@ -0,0 +1,104 @@ +import os +import sys +import time +import mimetypes + +SITE_DIR = os.path.expanduser("~/apps/tinyweb-site") +DATA_DIR = os.environ.get("TINYWEB_DATA_DIR") or os.path.expanduser("~/.tinyweb") +IDENTITY_FILE = "tinyweb-site_identity" + +APP_NAME = "tinyweb" +ASPECTS = ["server"] +RNS_REQUEST_PATH = "/tinyweb" + +import RNS + + +def load_or_create_identity(): + identity_path = os.path.join(DATA_DIR, IDENTITY_FILE) + if os.path.isfile(identity_path): + return RNS.Identity.from_file(identity_path) + identity = RNS.Identity() + os.makedirs(DATA_DIR, exist_ok=True) + identity.to_file(identity_path) + os.chmod(identity_path, 0o600) + return identity + + +def main(): + configdir = os.environ.get("RNS_CONFIG_DIR") + reticulum = RNS.Reticulum(configdir=configdir) + + identity = load_or_create_identity() + + destination = RNS.Destination( + identity, + RNS.Destination.IN, + RNS.Destination.SINGLE, + APP_NAME, + *ASPECTS, + ) + + destination.register_request_handler( + RNS_REQUEST_PATH, + response_generator=request_handler, + allow=RNS.Destination.ALLOW_ALL, + ) + + destination.announce() + dest_hash = destination.hash.hex() + print(f"tinyweb-site server running!") + print(f"Destination hash: <{dest_hash}>") + print(f"Add this hash to a TinyWeb instance as a mesh site to browse.") + + try: + while True: + time.sleep(1) + except KeyboardInterrupt: + print("\nShutting down...") + destination.unregister_request_handler() + + +def request_handler(path, data, request_id, link_id, remote_identity, requested_at): + if data is None: + data = {"method": "GET", "path": "/", "query": {}, "body": {}, "gateway_host": ""} + req_path = data.get("path", "/") + + if req_path in ("/", "/index.html") or not req_path.strip("/"): + fs_path = os.path.join(SITE_DIR, "index.html") + else: + fs_path = os.path.join(SITE_DIR, req_path.lstrip("/")) + + real_path = os.path.realpath(fs_path) + site_real = os.path.realpath(SITE_DIR) + + if not real_path.startswith(site_real + os.sep) and real_path != site_real: + body = f"
{req_path}
" + return {"status": 404, "content_type": "text/html; charset=utf-8", "body": body, "headers": {}} + + if not os.path.isfile(real_path): + real_path = os.path.join(SITE_DIR, "index.html") + + if not os.path.isfile(real_path): + body = f"Add a site to your index
" + f"Add a site to your index — URL or RNS destination hash
" f'