Skip to content

Routing

Route registration returns an updated handle — reassign after each get / post / … call.

Function Registers
get(app, path, h) GET
post(app, path, h) POST
put(app, path, h) PUT
delete(app, path, h) DELETE
patch(app, path, h) PATCH
all(app, path, h) GET, POST, PUT, DELETE, PATCH on the same path

Works on both server() handles and router() handles.

Express

const app = express();
app.get('/echo', (req, res) => res.send('ok'));
app.all('/probe', (req, res) => res.send('ok'));

vow-web-server

import vws from vow_web_server
import vow_web_server.request
import vow_web_server.response
fn any_method(_req: request.Request) -> response.Response {
return vws.send("ok");
}
fn main(caps: Caps) -> int {
let rt = vws.runtime(caps);
var app = vws.server();
app = vws.all(app, "/echo", any_method);
return vws.serve(app, rt, 8787);
}

all registers five routes with the same handler — useful for catch-all endpoints or method-agnostic probes.

Use :name segments in the path pattern. The matched value is available via request.param(req, "name"):

Express

app.get('/users/:id', (req, res) => {
res.json({ id: req.params.id });
});

vow-web-server

fn user_by_id(req: request.Request) -> response.Response {
let id = vws.param(req, "id");
return vws.json("{\"id\":\"" + id + "\"}");
}
var app = vws.server();
app = vws.get(app, "/users/:id", user_by_id);

Query strings use request.query(req, "key") — separate from path params.

Build a standalone router, attach middleware, register routes, then mount under a prefix:

Express

const api = express.Router();
api.get('/health', apiHealth);
api.get('/users/:id', userById);
app.use('/api/v1', api);

vow-web-server

var api = vws.router();
api = vws.get(api, "/health", api_health);
api = vws.get(api, "/users/:id", user_by_id);
app = vws.use_middleware(app, "/api/v1", api);

A request to GET /api/v1/users/42 dispatches to user_by_id with param(req, "id") == "42". Middleware registered on the sub-router applies under the mount prefix.

Nested mounts work the same way — mount a router onto another router:

var admin = vws.router();
admin = vws.get(admin, "/stats", stats);
var api = vws.router();
api = vws.get(api, "/users", list_users);
api = vws.use_middleware(api, "/admin", admin);
app = vws.use_middleware(app, "/api/v1", api);
// GET /api/v1/admin/stats → stats

See HTTP mounting tutorial and vow-examples/vow-web-server/mounted_api.vow.

Situation Status Body
No route or mount matches the path 404 {"error":"not found"}
Path matches a route but HTTP method does not 405 {"error":"method not allowed"}

Example: register only GET /health. A POST /health returns 405; GET /nope returns 404.

Unit-test status codes without network I/O:

assert vws.try_handle(app, "GET /health") == 200;
assert vws.try_handle(app, "POST /health") == 405;
assert vws.try_handle(app, "GET /nope") == 404;

v0.1/v0.2 names remain as deprecated aliases:

Legacy v0.3 preferred
app() server()
router_new() router()
router_get(r, path, h) get(r, path, h) on a router handle
mount(a, prefix, sub) use_middleware(a, prefix, router)
router_try_dispatch(r, raw) try_handle(app, raw)
serve_loop(r, cap, port) serve(app, rt, port)

Prefer the v0.3 handle API for middleware integration and Express-like ergonomics.