-- web-app — the storefront: writeonce-framework (via [deps]) + @table -- persistence. Every handler is a class satisfying Handler; the auth gate is -- a Middleware; the data layer is the language's own database — no ORM, no -- separate process, one binary. use env use json use framework use framework/http use framework/router -- decode target for POST /products, encode shape for every product answer typedef ProductView = { name: Text, price: Int, stock: Int } typedef NewOrder = { product: Text, qty: Int } fn view_json(name: Text, price: Int, stock: Int) -> Text { return json.encode(ProductView { name: name, price: price, stock: stock }); } class ListProducts { pad: Int fn handle(req: Req) -> Resp { let body = "["; let first = true; for p in from x in Product order by x.name select x { if first == false { body = body .. ","; } first = false; body = body .. view_json(p.name, p.price, p.stock); } return ok_json(body .. "]"); } } class ShowProduct { pad: Int fn handle(req: Req) -> Resp { let name = req.params["name"]; if name == nil { return bad_request("no name"); } let hits = from p in Product where p.name == name take 1 select p; if len(hits) == 0 { return not_found(); } let p = hits[0]; return ok_json(view_json(p.name, p.price, p.stock)); } } -- Accepts THREE bodies: multipart/form-data (curl -F), a form post -- (application/x-www-form-urlencoded), and JSON — same insert either way. fn create_product(name: Text, price: Int, stock: Int) -> Resp { let made = try insert Product { name: name, price: price, stock: stock } catch (e) nil; if made == nil { return conflict("product name already exists"); } return created_json(view_json(name, price, stock)); } class CreateProduct { pad: Int fn handle(req: Req) -> Resp { if media_type(req) == "multipart/form-data" { let ps = multipart_parts(req); if ps == nil { return bad_request("unreadable multipart body"); } let name = part_named(ps, "name"); if name == nil { return bad_request("multipart needs name, price, stock"); } let pstr = part_named(ps, "price"); if pstr == nil { return bad_request("multipart needs name, price, stock"); } let sstr = part_named(ps, "stock"); if sstr == nil { return bad_request("multipart needs name, price, stock"); } let price = parse_int(pstr); if price == nil { return bad_request("price must be a number"); } let stock = parse_int(sstr); if stock == nil { return bad_request("stock must be a number"); } return create_product(name, price, stock); } if media_type(req) == "application/x-www-form-urlencoded" { let f = form_values(req); if f == nil { return bad_request("unreadable form body"); } let name = f["name"]; if name == nil { return bad_request("form needs name, price, stock"); } let ps = f["price"]; if ps == nil { return bad_request("form needs name, price, stock"); } let ss = f["stock"]; if ss == nil { return bad_request("form needs name, price, stock"); } let price = parse_int(ps); if price == nil { return bad_request("price must be a number"); } let stock = parse_int(ss); if stock == nil { return bad_request("stock must be a number"); } return create_product(name, price, stock); } let v = json.decode(req.body) as ProductView; if v == nil { return bad_request("body must be {name, price, stock}"); } return create_product(v.name, v.price, v.stock); } } class CreateOrder { pad: Int fn handle(req: Req) -> Resp { let v = json.decode(req.body) as NewOrder; if v == nil { return bad_request("body must be {product, qty}"); } if v.qty < 1 { return bad_request("qty must be positive"); } let hits = from p in Product where p.name == v.product take 1 select p; if len(hits) == 0 { return not_found(); } insert Order { product: hits[0], qty: v.qty }; return created_json("{\"ok\":true}"); } } class DeleteProduct { pad: Int fn handle(req: Req) -> Resp { let name = req.params["name"]; if name == nil { return bad_request("no name"); } let hits = from p in Product where p.name == name take 1 select p; if len(hits) == 0 { return not_found(); } let gone = try delete hits[0] catch (e) nil; if gone == nil { return conflict("orders still reference this product"); } return ok_json("{\"deleted\":true}"); } } fn main(args: multi Text) -> Int { if len(args) < 1 { print_err("usage: web-app (WA_TOKEN and WO_DATA must be set)"); return 2; } let port = parse_int(args[0]); if port == nil { print_err("web-app: must be a number"); return 2; } let token = env.get("WA_TOKEN"); if token == nil { print_err("web-app: WA_TOKEN is required (the auth middleware's bearer token)"); return 2; } let app = App { middleware: [], routes: [] }; -- the framework's Bearer mechanism: constant-time compare, principal -- attached to req.principal for handlers that want "who is this" app.use_mw(Mw { m: BearerAuth { token: token, principal: "api" } }); app.get("/products", ListProducts { pad: 0 }); app.get("/products/:name", ShowProduct { pad: 0 }); app.post("/products", CreateProduct { pad: 0 }); app.post("/orders", CreateOrder { pad: 0 }); app.delete_("/products/:name", DeleteProduct { pad: 0 }); return app.serve("127.0.0.1", port); }