rns browser, standalone site server, unified add form
- /rns/<hash>/<path> proxies pages over RNS with link rewriting - fetch_remote_page() in rns_client.py for generic RNS page fetching - mesh_sites table for persisting saved hashes - standalone site_server.py with its own RNS identity - tinyweb-site/index.html: SPA with RSS-aware nav (/rns/<hash>/ prefix) - unified /add form: single input accepts URL or 32-char RNS hash - RNS add indexes into pages table (fetch root page, extract title/desc) - rns:<hash> URLs displayed in browse/search, linked to /rns/<hash>/ - expand RNS whitelist: allow GET /, /about, /pages, /tags, /share
This commit is contained in:
parent
4468ba89ad
commit
48fcaf1627
8 changed files with 377 additions and 51 deletions
104
site_server.py
Normal file
104
site_server.py
Normal file
|
|
@ -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"<html><body><h1>404 Not Found</h1><p>{req_path}</p></body></html>"
|
||||
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"<html><body><h1>404 Not Found</h1></body></html>"
|
||||
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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue