Servidor HTTP
Un servidor HTTP de producción nativo — sin framework que agregar (async hyper/tokio). Todo es deny-by-default, así que un servidor necesita require serve(port).
-- Doc example: the serve response contract. Helpers return {status, value}; the
-- runtime renders them. (A real `serve on` block doesn't terminate, so the doctest
-- asserts the response shapes the handlers give — see the prose for a full server.)
intent: "doc example: serve response contract"
print("ok → " + text(status of ok({"a": 1})) + ", fail(400) → " + text(status of fail(400, "bad")))
test "uniform response helpers carry a status + value"
assert_eq(status of ok({"a": 1}), 200)
assert_eq(status of created({"id": 1}), 201)
assert_eq(status of fail(400, "bad input"), 400)
assert_eq(status of not_found("missing"), 404)
assert_eq((value of fail(400, "bad input"))["error"], "bad input")
Rutas y params
require serve(8080)
serve on 8080
route "GET /products"
give sql("SELECT id, name, price FROM products")
route "GET /products/:id"
give sql("SELECT * FROM products WHERE id = ?", [params.id])
route "GET /files/*path" -- catch-all (profundidad variable)
give read_file(params.path)
Las rutas matchean por especificidad (exacto > :param > *catchall), no por orden de declaración.
Auth y validación
serve on 8080
auth with check_token
route "POST /products" requires auth
expect body {name: text, price: number} -- 400 si no coincide
give created(json of request)
El request y las respuestas
request tiene .method .path .body .json .headers .user. query y params son maps. Las respuestas usan los helpers uniformes — ok(x), created(x), fail(code, msg), not_found(msg), respond(text, content_type), redirect(url) — o give de un valor directo.
Incluido
- Paginación:
give paged("SELECT … ORDER BY id")— pushdown deLIMIT/OFFSET+COUNT(*)exacto. - SSE: un bloque
streamconsendpara server-sent events. - Rate limiting:
rate_limit N per window. - Archivos estáticos:
static "/assets" from "./static"(ETag/Range/gzip). Las rutas declaradas ganan sobre static — desde una ruta declarada, serví un asset binario conbinary(read_file_bytes(p), "image/png")(read_filea secas es lossy en UTF-8). Más en Frontend. - CORS:
cors "*". Negociación:content()sirve HTML/Markdown/JSON desde una sola fuente. - TLS / HTTPS automático vía flags del CLI (
--domain … --tls-auto); HTTP/2, vhosts, reverse proxy. - Observabilidad:
log/printllegan a la terminal con prefijo[serve].
Ver Frontend para páginas HTML.