Skip to content

HTTP mounting

Sub-routers group related routes. Mount attaches them under a URL prefix without repeating the prefix on every route.

Example source: vow-examples/vow-web-server/mounted_api.vow

import lib.app
import lib.request
import lib.response
import lib.router
import lib.serve
fn user_by_id(req: request.Request) -> response.Response {
let id = request.param(req, "id");
let body = "{\"id\":\"" + id + "\"}";
return response.json(body);
}
fn api_health(_req: request.Request) -> response.Response {
return response.json("{\"api\":\"v1\"}");
}
fn main(caps: Caps) -> int {
let sub = router.router_get(
router.router_get(router.router_new(), "/health", api_health),
"/users/:id",
user_by_id
);
let a = app.mount(app.app(), "/api/v1", sub);
return match caps.net {
Some(cap) => serve.listen(a, cap, 8787),
None => 0 - 1,
};
}
Terminal window
./vow run vow-examples/vow-web-server/mounted_api.vow -- --grant net:
curl -sf http://127.0.0.1:8787/api/v1/health
curl -sf http://127.0.0.1:8787/api/v1/users/42
URL Handler Notes
GET /api/v1/health api_health Sub-router route
GET /api/v1/users/:id user_by_id :idparam(req, "id")
GET /api/v2/health 404 (no mount)

Mount strips the prefix before dispatching to the child router — child routes register as /health, /users/:id, not /api/v1/health.

assert app.try_handle(a, "GET /api/v1/users/99") == 200;
assert app.try_handle(a, "GET /api/v1/nope") == 404;