|
#!/usr/bin/env python3 |
|
|
|
import extism |
|
import json |
|
import os |
|
|
|
from uuid import uuid4 |
|
from random import sample, shuffle, randint |
|
|
|
|
|
ITEMS_URL = "/items" |
|
ELEMENTS = { |
|
"form-field": "./form_field.js" |
|
} |
|
SAMPLE = """ |
|
lorem ipsum dolor sit amet consectetur adipisicing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut enim ad minim veniam quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt mollit anim id est laborum |
|
""".strip().split(" ") |
|
|
|
ROOT_DIR = os.path.dirname(__file__) |
|
MANIFEST = { |
|
"wasm": [{ "path": "%s/enhance_ssr.wasm" % ROOT_DIR }] |
|
} |
|
STORE = {} |
|
|
|
# populate element definitions |
|
for name, filepath in ELEMENTS.items(): |
|
with open(os.path.join(ROOT_DIR, filepath), "r") as fh: |
|
ELEMENTS[name] = fh.read() |
|
|
|
# populate store |
|
for item in range(5): |
|
_id, *_ = str(uuid4()).split("-") |
|
desc = sample(SAMPLE, randint(3, 7)) |
|
shuffle(desc) |
|
STORE[_id] = { |
|
"done": False, |
|
"desc": " ".join(desc) |
|
} |
|
|
|
|
|
def handle_request(environ, start_response): |
|
method = environ["REQUEST_METHOD"] |
|
uri = environ.get("PATH_INFO", "") |
|
|
|
if method != "GET": |
|
start_response("405 Method Not Allowed", [("Content-Type", "text/plain")]) |
|
msg = "unsupported HTTP method\n\n".encode("utf-8") |
|
if method == "POST": |
|
return [msg, request_body(environ)] |
|
else: |
|
return [msg.strip()] |
|
|
|
if uri == "/": |
|
start_response("302 Found", [("Location", ITEMS_URL)]) |
|
return [] |
|
|
|
if uri == ITEMS_URL: |
|
return render_collection(environ, start_response) |
|
|
|
if uri.startswith("%s/" % ITEMS_URL): |
|
_id = uri[len(ITEMS_URL) + 1:] |
|
return render_entity(_id, environ, start_response) |
|
|
|
start_response("404 Not Found", [("Content-Type", "text/plain")]) |
|
return ["resource not found".encode("utf-8")] |
|
|
|
|
|
def render_collection(environ, start_response): |
|
params = { "prefix": ITEMS_URL } |
|
items = (""" |
|
<li> |
|
<form-field type="checkbox" name="done" caption="Done"></form-field> |
|
<a href="%(prefix)s/%(id)s">%(desc)s</a> |
|
</li> |
|
""".strip() % { **params, **item, "id": _id } for _id, item in STORE.items()) |
|
return render("200 OK", """ |
|
<h1>All Items</h1> |
|
<ul>%s</ul> |
|
""".strip() % "\n".join(items), environ, start_response) |
|
|
|
|
|
def render_entity(_id, environ, start_response): |
|
return render("200 OK", """ |
|
<h1>Item %s</h1> |
|
<p>%s</p> |
|
<form method="post" action="%s"> |
|
<form-field type="hidden" name="id"></form-field> |
|
<form-field type="checkbox" name="done" caption="Done"></form-field> |
|
<form-field name="desc" caption="Description"></form-field> |
|
</form> |
|
""".strip() % (_id, STORE[_id]["desc"], ITEMS_URL), environ, start_response) |
|
|
|
|
|
def render(status_line, template, environ, start_response): |
|
start_response(status_line, [("Content-Type", "text/html")]) |
|
data = { |
|
"markup": template, |
|
"elements": ELEMENTS, |
|
"initialState": {} |
|
} |
|
with extism.Plugin(MANIFEST, wasi=True) as plugin: #XXX: inefficient; repeated for each request |
|
res = plugin.call("ssr", json.dumps(data), ingest) |
|
return [res["document"].encode("utf-8")] |
|
|
|
|
|
def ingest(output): |
|
return json.loads(bytes(output).decode("utf-8")) |
|
|
|
|
|
def request_body(environ): |
|
try: |
|
payload_size = int(environ.get("CONTENT_LENGTH", 0)) |
|
except ValueError: |
|
payload_size = 0 |
|
return environ["wsgi.input"].read(payload_size) |
|
|
|
|
|
if __name__ == "__main__": |
|
from wsgiref.simple_server import make_server |
|
|
|
host = "localhost" |
|
port = 8080 |
|
|
|
srv = make_server(host, port, handle_request) |
|
print("→ http://%s:%s" % (host, port)) |
|
srv.serve_forever() |