vix::App
vix::App is the main application object in Vix Core.
Use it to configure routes, middleware, templates, static files, server lifecycle, and application shutdown.
Public header
#include <vix.hpp>You can also include the app header directly:
#include <vix/app/App.hpp>What App provides
App is the high-level entry point for building a Vix HTTP application.
It provides:
- route registration
- route groups
- middleware
- protected route prefixes
- static file mounting
- template configuration
- server startup
- server shutdown
- access to the router
- access to the HTTP server
- access to the runtime executor
- access to configuration
Most applications only need to create one App.
vix::App app;Minimal app
#include <vix.hpp>
int main()
{
vix::App app;
app.get("/", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.text("Hello from Vix");
});
app.run(8080);
return 0;
}Run:
vix run main.cppThen open:
http://localhost:8080Expected response:
Hello from VixCreate an app
Create an app with the default executor:
vix::App app;The default app owns:
Config
Router
RuntimeExecutor
HTTPServerThe default constructor prepares the router, executor, HTTP server, logs, docs routes, access logs, static fallback, and internal benchmark route.
Register routes
Use the HTTP method helpers to register routes.
app.get("/", handler);
app.post("/users", handler);
app.put("/users/{id}", handler);
app.patch("/users/{id}", handler);
app.del("/users/{id}", handler);
app.head("/status", handler);
app.options("/status", handler);A route handler receives:
vix::Request &req
vix::Response &resExample:
#include <vix.hpp>
int main()
{
vix::App app;
app.get("/status", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.json({
{"status", "ok"}
});
});
app.run(8080);
return 0;
}Route parameters
Use {name} in a route path to capture a path parameter.
#include <vix.hpp>
int main()
{
vix::App app;
app.get("/users/{id}", [](vix::Request &req, vix::Response &res)
{
const std::string id = req.param("id");
res.json({
{"id", id}
});
});
app.run(8080);
return 0;
}Request:
GET /users/42Example response:
{
"id": "42"
}Return text
Use res.text(...).
app.get("/", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.text("Home");
});Return JSON
Use res.json(...).
app.get("/api/status", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.json({
{"status", "ok"},
{"runtime", "Vix.cpp"}
});
});Set status
Use res.status(...).
app.get("/forbidden", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.status(403).json({
{"error", "forbidden"}
});
});Redirect
Use res.redirect(...).
app.get("/old", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.redirect("/new");
});Register middleware
Use app.use(...) to register global middleware.
#include <vix.hpp>
int main()
{
vix::App app;
app.use([](vix::Request &req, vix::Response &res, vix::App::Next next)
{
(void)res;
vix::print("request:", req.method(), req.path());
next();
});
app.get("/", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.text("home");
});
app.run(8080);
return 0;
}Middleware receives:
vix::Request &req
vix::Response &res
vix::App::Next nextCall next() to continue to the next middleware or final route handler.
Prefix middleware
Use app.use(prefix, middleware) to apply middleware only to a path prefix.
app.use("/admin", [](vix::Request &req, vix::Response &res, vix::App::Next next)
{
const std::string token = req.header("Authorization");
if (token.empty())
{
res.status(401).json({
{"error", "missing authorization header"}
});
return;
}
next();
});This middleware applies to:
/admin
/admin/users
/admin/settingsIt does not apply to:
/api
/usersProtect a prefix
Use protect(...) as a clearer name for prefix middleware.
app.protect("/admin", [](vix::Request &req, vix::Response &res, vix::App::Next next)
{
const bool allowed = true;
if (!allowed)
{
res.status(403).json({
{"error", "forbidden"}
});
return;
}
next();
});Protect an exact path
Use protect_exact(...) when the middleware should apply only to one path.
app.protect_exact("/admin/settings", [](vix::Request &req, vix::Response &res, vix::App::Next next)
{
(void)req;
const bool allowed = true;
if (!allowed)
{
res.status(403).text("Forbidden");
return;
}
next();
});This applies only to:
/admin/settingsRoute groups
Use group(...) to organize routes under a shared prefix.
#include <vix.hpp>
int main()
{
vix::App app;
app.group("/api", [](auto &api)
{
api.get("/status", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.json({{"status", "ok"}});
});
api.post("/users", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.status(201).json({{"created", true}});
});
});
app.run(8080);
return 0;
}The routes become:
GET /api/status
POST /api/usersNested groups
Groups can be nested.
app.group("/api", [](auto &api)
{
api.group("/v1", [](auto &v1)
{
v1.get("/status", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.json({{"status", "ok"}});
});
});
});The route becomes:
GET /api/v1/statusGroup middleware
Middleware can be attached to a group.
app.group("/admin", [](auto &admin)
{
admin.use([](vix::Request &req, vix::Response &res, vix::App::Next next)
{
const bool allowed = true;
if (!allowed)
{
res.status(403).text("Forbidden");
return;
}
next();
});
admin.get("/dashboard", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.text("Admin dashboard");
});
});The middleware applies to routes under /admin.
Heavy routes
Use get_heavy or post_heavy for routes that may be CPU-heavy or database-heavy.
app.get_heavy("/reports", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.json({
{"report", "ready"}
});
});Heavy routes are registered with route metadata.
This allows the router and executor model to classify expensive routes separately when needed.
Static files
Use static_dir(...) to mount a directory.
#include <vix.hpp>
int main()
{
vix::App app;
app.static_dir("public", "/");
app.run(8080);
return 0;
}Example:
GET /style.csscan serve:
public/style.cssMount static files under a prefix:
app.static_dir("public/assets", "/assets");Example:
GET /assets/app.csscan serve:
public/assets/app.cssStatic file options
static_dir accepts more options.
app.static_dir(
"public",
"/",
"index.html",
true,
"public, max-age=3600",
true);Arguments:
root
mount
index_file
add_cache_control
cache_control
fallthroughTemplates
Use templates(...) to configure a template directory.
#include <vix.hpp>
int main()
{
vix::App app;
app.templates("views");
app.get("/", [](vix::Request &req, vix::Response &res)
{
(void)req;
vix::tmpl::Context ctx;
ctx.set("title", "Home");
res.render("index.html", ctx);
});
app.run(8080);
return 0;
}templates(...) initializes:
FileSystemLoader
Template Engine
TemplateViewCheck template support
Use has_views() to check whether templates are configured.
if (app.has_views())
{
vix::print("templates are ready");
}Use views() to access the template view facade.
auto &views = app.views();If templates(...) was not called, views() throws.
Run the app
Use run(...) to start the server and block until shutdown.
app.run(8080);Equivalent flow:
listen
wait
closeListen without blocking
Use listen(...) to start the server asynchronously.
#include <vix.hpp>
int main()
{
vix::App app;
app.get("/", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.text("hello");
});
app.listen(8080);
app.wait();
return 0;
}listen(...) starts the HTTP server in a separate thread.
wait() keeps the application alive until stop is requested.
Listen callback
You can pass a callback to listen.
app.listen(8080, []()
{
vix::print("server is listening");
});Use listen_port(...) when the callback needs the bound port.
app.listen_port(8080, [](int port)
{
vix::print("listening on port", port);
});This is useful when the app binds to port 0 and the operating system chooses a port.
Stop the app
Use close() to stop the server.
app.close();close() requests shutdown, stops the HTTP server, joins the server thread, and marks the app as stopped.
Shutdown callback
Use set_shutdown_callback(...) to run custom shutdown logic.
app.set_shutdown_callback([]()
{
vix::print("shutdown requested");
});Check running state
Use is_running().
if (app.is_running())
{
vix::print("app is running");
}Access configuration
Use config() to access the app configuration.
vix::App app;
app.config().setServerPort(8080);You can also run with an explicit config.
vix::config::Config cfg;
cfg.setServerPort(8080);
vix::App app;
app.run(cfg);Access router
Use router() to access the shared router.
auto router = app.router();This is useful for advanced integrations and tooling.
Access server
Use server() to access the underlying HTTP server.
auto &server = app.server();Most applications do not need direct server access.
Access executor
Use executor() to access the runtime executor.
auto &executor = app.executor();This is useful for advanced runtime or metrics integration.
Development mode
Use setDevMode(...) to mark the app as running in development mode.
app.setDevMode(true);Check it with:
if (app.isDevMode())
{
vix::print("dev mode");
}Development mode affects the runtime banner mode shown when the server starts.
App lifecycle
The typical lifecycle is:
construct App
register routes
register middleware
configure templates or static files
run or listen
wait
closerun(...) handles the common blocking lifecycle.
app.run(8080);listen(...) gives more control.
app.listen(8080);
app.wait();
app.close();Complete example
#include <vix.hpp>
int main()
{
vix::App app;
app.use([](vix::Request &req, vix::Response &res, vix::App::Next next)
{
(void)res;
vix::print(req.method(), req.path());
next();
});
app.get("/", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.text("Welcome to Vix");
});
app.get("/users/{id}", [](vix::Request &req, vix::Response &res)
{
res.json({
{"id", req.param("id")}
});
});
app.group("/api", [](auto &api)
{
api.get("/status", [](vix::Request &req, vix::Response &res)
{
(void)req;
res.json({
{"status", "ok"},
{"server", "Vix.cpp"}
});
});
});
app.static_dir("public", "/assets");
app.run(8080);
return 0;
}API summary
| API | Purpose |
|---|---|
App() | Create an app with the default executor. |
run(port) | Start the server and block until shutdown. |
listen(port) | Start the server asynchronously. |
wait() | Wait until shutdown is requested. |
close() | Stop the server and release resources. |
get(path, handler) | Register a GET route. |
post(path, handler) | Register a POST route. |
put(path, handler) | Register a PUT route. |
patch(path, handler) | Register a PATCH route. |
del(path, handler) | Register a DELETE route. |
head(path, handler) | Register a HEAD route. |
options(path, handler) | Register an OPTIONS route. |
get_heavy(path, handler) | Register a heavy GET route. |
post_heavy(path, handler) | Register a heavy POST route. |
use(middleware) | Register global middleware. |
use(prefix, middleware) | Register prefix middleware. |
protect(prefix, middleware) | Protect a prefix. |
protect_exact(path, middleware) | Protect one exact path. |
group(prefix, fn) | Register grouped routes. |
static_dir(root, mount) | Mount static files. |
templates(directory) | Configure template rendering. |
has_views() | Check whether templates are configured. |
views() | Access the template view. |
config() | Access app configuration. |
router() | Access the router. |
server() | Access the HTTP server. |
executor() | Access the runtime executor. |
setDevMode(value) | Enable or disable development mode. |
is_running() | Check whether the app is running. |
set_shutdown_callback(cb) | Register shutdown logic. |
Next steps
Read the next pages: