Building web APIs with nyx-serve
What is nyx-serve?
nyx-serve is an HTTP framework for Nyx that gives you routing, middleware, JSON handling, and sessions out of the box. It follows the same architecture as the nyx-kv case study: a thread pool of workers processing requests from a shared channel.
The App, Request, and Response
Every nyx-serve application starts with three structs:
struct App { routes: Array, middlewares: Array, static_dir: String, } struct Request { method: String, path: String, query: Map, headers_flat: Array, body: String, form: Map, cookies: Map, params: Map, } struct Response { status: int, headers_flat: Array, body: String, }
Create an app, register routes, and start serving:
import "std/web" fn handle_index(req: Request) -> Response { return response_html(200, "<h1>Hello!</h1>") } fn main() { let app: App = app_new() app_get(app, "/", handle_index) serve_app(app, 3000, 64) }
Routing
Register handlers for each HTTP method:
app_get(app, "/users", list_users) app_post(app, "/users", create_user) app_put(app, "/users/{id}", update_user) app_delete(app, "/users/{id}", delete_user)
Route patterns support named parameters ({id}) and wildcards (/static/*). Named parameters are accessible via req.params:
fn get_user(req: Request) -> Response { let id: String = req.params.get("id") return response_text(200, "User: " + id) }
Middleware
Middleware functions run before your route handlers. Register them with app_use:
let app: App = app_new() app_use(app, mw_logging) // log every request app_use(app, mw_cors) // handle CORS preflight
nyx-serve ships with two built-in middleware functions:
mw_logging— logs every request with method, path, status, and latency.mw_cors— handles CORS preflight (OPTIONS) requests and injects the proper headers.
Configure CORS before registering the middleware:
cors_configure("*", "GET,POST,PUT,DELETE", "Content-Type,Authorization")
A middleware returns a Response with status: 0 to continue the chain, or a non-zero status to short-circuit (e.g. return 403 for unauthorized requests).
JSON APIs
Parse a JSON request body into a Map:
fn create_user(req: Request) -> Response { let data: Map = req_json(req) let name: String = data.get("name") // ... create user ... return response_json(201, "{\"ok\":true}") }
Build a JSON response from a Map:
fn get_status(req: Request) -> Response { let data: Map = Map.new() data.insert("status", "ok") data.insert("version", "1.0") return response_json_map(200, data) }
Sessions
Sessions are cookie-backed and stored in nyx-kv via RESP. Configure the connection first:
session_configure("127.0.0.1", 6380, 3600) // host, port, TTL in seconds
Use sessions in your handlers:
fn login(req: Request) -> Response { var resp: Response = response_text(200, "Logged in") let sid: String = session_start(req, resp) session_set(req, "user", "alice") return resp } fn profile(req: Request) -> Response { let user: String = session_get(req, "user") if user.length() == 0 { return response_text(401, "Not logged in") } return response_text(200, "Hello, " + user) }
Static files
Serve files from a directory with serve_static:
serve_static(app, "public")
Requests to /style.css will serve public/style.css. Wildcard routes like /learn/* can also be used for custom static serving logic.
Complete example: a todo API
import "std/web" var todos: Array = [] fn list_todos(req: Request) -> Response { let result: Map = Map.new() result.insert("count", int_to_string(todos.length())) return response_json_map(200, result) } fn add_todo(req: Request) -> Response { let data: Map = req_json(req) let title: String = data.get("title") todos.push(title) return response_json(201, "{\"ok\":true}") } fn main() { cors_configure("*", "GET,POST", "Content-Type") let app: App = app_new() app_use(app, mw_logging) app_use(app, mw_cors) app_get(app, "/todos", list_todos) app_post(app, "/todos", add_todo) serve_app(app, 3000, 64) }
Summary
app_new()creates an application;serve_app()starts it.- Register routes with
app_get,app_post,app_put,app_delete. - Middleware chain with
app_use()—mw_loggingandmw_corsbuilt in. - JSON:
req_json()parses request body,response_json_map()builds JSON response. - Sessions via
session_start,session_get,session_set,session_destroy. - Static files with
serve_static()and wildcard routes.