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"

404 Not Found

{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"

404 Not Found

" return {"status": 404, "content_type": "text/html; charset=utf-8", "body": body, "headers": {}} with open(real_path, "rb") as f: content = f.read() content_type, _ = mimetypes.guess_type(real_path) if not content_type: content_type = "text/html; charset=utf-8" elif content_type.startswith("text/"): content_type += "; charset=utf-8" return { "status": 200, "content_type": content_type, "body": content.decode("utf-8", errors="replace"), "headers": {}, } if __name__ == "__main__": main()