diff --git a/README.md b/README.md
index 2533a5a..1766f79 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
# Vix.cpp
-
@@ -45,7 +45,7 @@ but engineered **from day one** for:
> **Run applications like Node/Deno/Bun
> with C++ speed, control, and predictability.**
-Vix is not just a backend framework.
+Vix is not just a backend framework.
It is a **runtime layer** for real-world distributed systems.
---
@@ -106,7 +106,7 @@ Vix.cpp is designed to remove overhead, unpredictability, and GC pauses.
int main() {
Vix::App app;
- app.get("/", [](auto&, auto& res){
+ app.get("/", [](Request&, Response& res){
res.send("Hello from Vix.cpp π");
});
diff --git a/docs/examples/delete_user.md b/docs/examples/delete_user.md
index 2bad24c..9dec9fe 100644
--- a/docs/examples/delete_user.md
+++ b/docs/examples/delete_user.md
@@ -5,17 +5,17 @@
#include
#include
-using namespace Vix;
-namespace J = Vix::json;
+using namespace vix;
+namespace J = vix::json;
int main()
{
App app;
// DELETE /users/{id}
- app.del("/users/{id}", [](auto &, auto &res, auto ¶ms)
+ app.del("/users/{id}", [](Request &req, Response &res)
{
- const std::string id = params["id"];
+ const std::string id = req.param("id");
// In a real app you'd remove the resource from DB or memory here
res.json({
@@ -25,5 +25,6 @@ int main()
}); });
app.run(8080);
+ return 0;
}
```
diff --git a/docs/examples/hello_routes.md b/docs/examples/hello_routes.md
index a39003f..607fbfc 100644
--- a/docs/examples/hello_routes.md
+++ b/docs/examples/hello_routes.md
@@ -4,13 +4,13 @@ Minimal GET routes and path params.
```cpp
#include
-using namespace Vix;
+using namespace vix;
int main()
{
App app;
- app.get("/hello", [](auto &, auto &res)
+ app.get("/hello", [](Request &, Response &res)
{ res.json({"message", "Hello, Vix!"}); });
app.run(8080);
diff --git a/docs/examples/json_builders_routes.md b/docs/examples/json_builders_routes.md
index bdce868..a4eae2a 100644
--- a/docs/examples/json_builders_routes.md
+++ b/docs/examples/json_builders_routes.md
@@ -4,33 +4,34 @@
#include
#include
-using namespace Vix;
-namespace J = Vix::json;
+using namespace vix;
+namespace J = vix::json;
int main()
{
App app;
// GET /hello -> {"message": "Hello, World!"}
- app.get("/hello", [](auto &, auto &res)
- { res.json({"message", "Hello, World!"}); });
+ app.get("/hello", [](Request &, Response &res){
+ res.json({"message", "Hello, World!"});
+ });
// GET /users/{id} -> {"user": {"id": "...", "active": true}}
- app.get("/users/{id}", [](auto &, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
- res.json({
- "user", J::obj({
- "id", id,
- "active", true
- })
- }); });
+ app.get("/users/{id}", [](Request &req, Response &res){
+ const std::string id = req.param("id");
+ res.json({
+ "user", J::obj({
+ "id", id,
+ "active", true
+ })
+ });
+ });
// GET /roles -> {"roles": ["admin", "editor", "viewer"]}
- app.get("/roles", [](auto &, auto &res)
- { res.json({"roles", J::array({"admin", "editor", "viewer"})}); });
+ app.get("/roles", [](Request &, Response &res){
+ res.json({"roles", J::array({"admin", "editor", "viewer"})});
+ });
app.run(8080);
- return 0;
}
```
diff --git a/docs/examples/logger_context_and_uuid.md b/docs/examples/logger_context_and_uuid.md
deleted file mode 100644
index f198ff9..0000000
--- a/docs/examples/logger_context_and_uuid.md
+++ /dev/null
@@ -1,57 +0,0 @@
-# Example β json_builders_routes
-
-```cpp
-#include
-#include
-#include
-
-using namespace Vix::orm;
-
-int main(int argc, char **argv)
-{
- std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
- std::string user = (argc > 2 ? argv[2] : "root");
- std::string pass = (argc > 3 ? argv[3] : "");
- std::string db = (argc > 4 ? argv[4] : "vixdb");
-
- try
- {
- ConnectionPool pool{host, user, pass, db};
-
- Transaction tx(pool);
- auto &c = tx.conn();
-
- auto st = c.prepare("INSERT INTO users(name,email,age) VALUES(?,?,?)");
-
- struct Row
- {
- const char *name;
- const char *email;
- int age;
- };
- std::vector rows = {
- {"Zoe", "zoe@example.com", 23},
- {"Mina", "mina@example.com", 31},
- {"Omar", "omar@example.com", 35},
- };
-
- std::uint64_t total = 0;
- for (const auto &r : rows)
- {
- st->bind(1, r.name);
- st->bind(2, r.email);
- st->bind(3, r.age);
- total += st->exec();
- }
-
- tx.commit();
- std::cout << "[OK] inserted rows = " << total << "\n";
- return 0;
- }
- catch (const std::exception &e)
- {
- std::cerr << "[ERR] " << e.what() << "\n";
- return 1;
- }
-}
-```
diff --git a/docs/examples/overview.md b/docs/examples/overview.md
index 92d2a1f..da37134 100644
--- a/docs/examples/overview.md
+++ b/docs/examples/overview.md
@@ -180,7 +180,7 @@ int main()
// Basic JSON response (auto send)
app.get("/", [](Request req, Response res) {
- return vix::json::o("message", "Hello from Vix");
+ res.send("message", "Hello from Vix");
});
// Path params + return {status, payload}
app.get("/users/{id}", [](Request req, Response res) {
diff --git a/docs/examples/post_create_user.md b/docs/examples/post_create_user.md
index b110b3e..d9c633f 100644
--- a/docs/examples/post_create_user.md
+++ b/docs/examples/post_create_user.md
@@ -5,25 +5,24 @@
#include
#include
-using namespace Vix;
-namespace J = Vix::json;
+using namespace vix;
+namespace J = vix::json;
int main()
{
App app;
// POST /users
- app.post("/users", [](auto &req, auto &res)
+ app.post("/users", [](Request &req, Response &res)
{
try {
- // Parse body as nlohmann::json for simplicity (still supported)
- auto body = nlohmann::json::parse(req.body());
+ auto body = json::Json::parse(req.body());
const std::string name = body.value("name", "");
const std::string email = body.value("email", "");
const int age = body.value("age", 0);
- res.status(http::status::created).json({
+ res.status(200).json({
"action", "create",
"status", "created",
"user", J::obj({
@@ -34,7 +33,7 @@ int main()
});
}
catch (...) {
- res.status(http::status::bad_request).json({
+ res.status(400).json({
"error", "Invalid JSON"
});
} });
diff --git a/docs/examples/put_update_user.md b/docs/examples/put_update_user.md
index 6e076e1..06c2a7d 100644
--- a/docs/examples/put_update_user.md
+++ b/docs/examples/put_update_user.md
@@ -5,21 +5,20 @@
#include
#include
-using namespace Vix;
-namespace J = Vix::json;
+using namespace vix;
+namespace J = vix::json;
int main()
{
App app;
// PUT /users/{id}
- app.put("/users/{id}", [](auto &req, auto &res, auto ¶ms)
+ app.put("/users/{id}", [](Request &req, Response &res)
{
- const std::string id = params["id"];
+ const std::string id = req.param("id");
try {
- // Parsing with nlohmann::json for input is fine (Vix supports it internally)
- auto body = nlohmann::json::parse(req.body());
+ auto body = json::Json::parse(req.body());
const std::string name = body.value("name", "");
const std::string email = body.value("email", "");
@@ -37,7 +36,7 @@ int main()
});
}
catch (...) {
- res.status(http::status::bad_request).json({
+ res.status(400).json({
"error", "Invalid JSON"
});
} });
diff --git a/docs/examples/user_crud_with_validation.md b/docs/examples/user_crud_with_validation.md
index 4e967af..ecc62f2 100644
--- a/docs/examples/user_crud_with_validation.md
+++ b/docs/examples/user_crud_with_validation.md
@@ -23,10 +23,10 @@
#include
#include
-using namespace Vix;
-namespace J = Vix::json;
+using namespace vix;
+namespace J = vix::json;
using njson = nlohmann::json;
-using namespace Vix::utils;
+using namespace vix::utils;
// --------------------------- Data Model -------------------------------------
struct User
@@ -110,7 +110,7 @@ int main()
App app;
// CREATE (POST /users)
- app.post("/users", [](auto &req, auto &res)
+ app.post("/users", [](Request &req, Response &res)
{
njson body;
try {
@@ -172,9 +172,9 @@ int main()
}); });
// READ (GET /users/{id})
- app.get("/users/{id}", [](auto & /*req*/, auto &res, auto ¶ms)
+ app.get("/users/{id}", [](Request &req, Response &res)
{
- const std::string id = params["id"];
+ const std::string id = req.param("id");
std::lock_guard lock(g_mtx);
auto it = g_users.find(id);
if (it == g_users.end()) {
@@ -188,9 +188,9 @@ int main()
}); });
// UPDATE (PUT /users/{id})
- app.put("/users/{id}", [](auto &req, auto &res, auto ¶ms)
+ app.put("/users/{id}", [](Request &req, Response &res)
{
- const std::string id = params["id"];
+ const std::string id = req.param("id");
njson body;
try {
@@ -226,9 +226,9 @@ int main()
}); });
// DELETE (DELETE /users/{id})
- app.del("/users/{id}", [](auto & /*req*/, auto &res, auto ¶ms)
+ app.del("/users/{id}", [](Request &req, Response &res)
{
- const std::string id = params["id"];
+ const std::string id = req.param("id");
std::lock_guard lock(g_mtx);
const auto n = g_users.erase(id);
if (!n) {
@@ -244,8 +244,5 @@ int main()
// Lancement
app.run(8080);
- return 0;
}
-
-
```
diff --git a/docs/introduction.md b/docs/introduction.md
index 9949f47..5d5df9c 100644
--- a/docs/introduction.md
+++ b/docs/introduction.md
@@ -1,6 +1,6 @@
# Introduction to Vix.cpp
-Vix.cpp is a nextβgeneration **C++20** web backend framework focused on **speed**, **modularity**, and **developer ergonomics**.
+Vix.cpp is a nextβgeneration **C++20** web backend framework focused on **speed**, **modularity**, and **developer ergonomics**.
Inspired by ideas from **FastAPI**, **Vue.js**, and **React**, it brings a clean, expressive style to native C++ while retaining zeroβoverhead abstractions and lowβlevel control.
---
@@ -19,19 +19,19 @@ Inspired by ideas from **FastAPI**, **Vue.js**, and **React**, it brings a clean
## Core Ideas
-1. **Small, sharp core**
+1. **Small, sharp core**
The core (`App`, router, request/response, HTTP server) stays tiny and predictable. Everything else is optβin.
-2. **Simple routing**
+2. **Simple routing**
Declarative routes with path parameters: `app.get("/users/{id}", handler);`
-3. **JSONβfirst**
+3. **JSONβfirst**
Seamless helpers around _nlohmann/json_ via `Vix::json` (builders, small utilities, safe conversions).
-4. **Composability**
+4. **Composability**
Middleware, utilities (Logger, UUID, Time, Env), and an optional ORM layer (MySQL / SQLite) integrate without tight coupling.
-5. **Pragmatism**
+5. **Pragmatism**
Clean, incremental APIs; clear error messages; predictable defaults; portable builds (CMake).
---
@@ -44,8 +44,8 @@ using namespace Vix;
int main() {
App app;
- app.get("/", [](auto&, auto& res) {
- res.json({ "message", "Hello world" });
+ app.get("/", [](Request&, Response& res) {
+ res.send("message", "Hello world");
});
app.run(8080);
}
@@ -107,7 +107,7 @@ cmake --build build-rel -j
./build-rel/hello_routes
```
-For platformβspecific setup (Linux/macOS/Windows), see **[Installation](./installation.md)**.
+For platformβspecific setup (Linux/macOS/Windows), see **[Installation](./installation.md)**.
For packaging, sanitizers, and compile_commands.json, see **[Build & Packaging](./build.md)**.
---
@@ -149,5 +149,5 @@ For details and status, see **[Architecture](./architecture.md)** and module pag
## Contributing & License
-Contributions are welcome! Please read **CONTRIBUTING.md**.
+Contributions are welcome! Please read **CONTRIBUTING.md**.
Licensed under **MIT** β see **LICENSE**.
diff --git a/docs/modules/core.md b/docs/modules/core.md
index 238fd5a..c1fc3a4 100644
--- a/docs/modules/core.md
+++ b/docs/modules/core.md
@@ -5,8 +5,8 @@


-> **vix.cpp/core** β The foundational module of the [**Vix.cpp**](https://github.com/vixcpp/vix) framework.
-> Provides the high-performance HTTP server, router, middleware system, and base runtime.
+> **vix.cpp/core** β The foundational module of the [**Vix.cpp**](https://github.com/vixcpp/vix) framework.
+> Provides the high-performance HTTP server, router, middleware system, and base runtime.
> Every other Vix module builds on top of this layer.
---
@@ -79,22 +79,22 @@ cmake --build build -j$(nproc)
#include
int main() {
- Vix::App app;
+ vix::App app;
- app.get("/hello", [](auto&, auto& res) {
- res.json({{"message", "Hello, World!"}});
+ app.get("/hello", [](Request&, Response& res) {
+ res.send("message", "Hello, World!");
});
- app.get("/users/{id}", [](auto&, auto& res, auto& params) {
- res.json({{"user_id", params["id"]}});
+ app.get("/users/{id}", [](Request& req, Response& res) {
+ res.json({{"user_id", req.param("id")}});
});
app.run(8080);
}
```
-β
Supports `GET`, `POST`, `PUT`, `DELETE`
-β
Automatic path parameter extraction
+β
Supports `GET`, `POST`, `PUT`, `DELETE`
+β
Automatic path parameter extraction
β
Helper methods: `res.json()`, `res.text()`, `res.status()`
---
@@ -148,5 +148,5 @@ Transfer/sec: 18.25MB
## π§Ύ License
-**MIT License** Β© [Gaspard Kirira](https://github.com/gkirira)
+**MIT License** Β© [Gaspard Kirira](https://github.com/gkirira)
See [LICENSE](../../LICENSE) for details.
diff --git a/docs/modules/json.md b/docs/modules/json.md
index fd2cb50..133ad02 100644
--- a/docs/modules/json.md
+++ b/docs/modules/json.md
@@ -5,14 +5,14 @@


-> **vix.cpp/json** β A high-level JSON utility library built on top of [nlohmann/json](https://github.com/nlohmann/json).
+> **vix.cpp/json** β A high-level JSON utility library built on top of [nlohmann/json](https://github.com/nlohmann/json).
> Provides expressive, concise, and safe helpers for working with JSON in C++.
---
## π Overview
-The **Vix JSON module** offers a lightweight abstraction over `nlohmann::json`,
+The **Vix JSON module** offers a lightweight abstraction over `nlohmann::json`,
designed for simplicity and expressiveness. It adds helpers for:
- Fast JSON object/array construction (`o()`, `a()`, `kv()`)
@@ -37,7 +37,7 @@ designed for simplicity and expressiveness. It adds helpers for:
#include
#include
-using namespace Vix::json;
+using namespace vix::json;
int main() {
auto user = o(
@@ -65,11 +65,20 @@ int main() {
## π§± JSON Builders
```cpp
-auto obj1 = o("id", 1, "name", "Vix", "active", true);
-auto arr1 = a(1, 2, 3, 4);
+#include
+#include
+using namespace vix::json;
+
+int main()
+{
+ Json obj1 = o("id", 1, "name", "Vix", "active", true);
+ Json arr1 = a(1, 2, 3, 4);
-auto obj2 = kv({{"key1", "val1"}, {"key2", 2}});
-std::cout << dumps(obj1, 2) << "\n" << dumps(arr1, 2);
+ Json obj2 = kv({{"key1", "val1"}, {"key2", 2}});
+
+ std::cout << dumps(obj1, 2) << "\n"
+ << dumps(arr1, 2) << std::endl;
+}
```
**Example Output**
@@ -88,10 +97,28 @@ std::cout << dumps(obj1, 2) << "\n" << dumps(arr1, 2);
## πΎ JSON File Operations
```cpp
-auto j = loads(R"({"a":1,"b":[10,20]})");
-dump_file("out.json", j, 2);
-auto j2 = load_file("out.json");
-std::cout << dumps(j2, 2) << "\n";
+#include
+#include
+using namespace vix::json;
+
+int main()
+{
+ Json j = loads(R"({"a":1,"b":[10,20]})");
+ dump_file("out.json", j, 2);
+ Json j2 = load_file("out.json");
+ std::cout << dumps(j2, 2) << std::endl;
+}
+```
+**Output**
+
+```json
+{
+ "a": 1,
+ "b": [
+ 10,
+ 20
+ ]
+}
```
**Features**
@@ -105,15 +132,24 @@ std::cout << dumps(j2, 2) << "\n";
## π§ JPath Access
```cpp
-Json j = obj();
-jset(j, "user.langs[2]", "cpp");
-jset(j, "user.profile.name", "Gaspard");
-jset(j, R"(user["display.name"])", "Ada L.");
+#include
+#include
+
+using namespace vix::json;
-if (auto v = jget(j, "user.langs[2]")) {
- std::cout << v->get() << "\n"; // cpp
+int main()
+{
+ Json j = obj();
+ jset(j, "user.langs[2]", "cpp");
+ jset(j, "user.profile.name", "Gaspard");
+ jset(j, R"(user["display.name"])", "Ada L.");
+
+ if (auto v = jget(j, "user.langs[2]"))
+ {
+ std::cout << v->get() << "\n";
+ }
+ std::cout << dumps(j, 2) << "\n";
}
-std::cout << dumps(j, 2) << "\n";
```
**Output**
@@ -160,14 +196,22 @@ This module is automatically included when you build the umbrella **Vix.cpp** pr
```cpp
#include
-using namespace Vix::json;
+using namespace vix::json;
auto j = o("framework", "Vix.cpp", "version", "1.7.0");
```
+**Output**
+
+```json
+{
+ "framework": "Vix.cpp",
+ "version": "1.7.0",
+}
+```
---
## π§Ύ License
-**MIT License** Β© [Gaspard Kirira](https://github.com/gkirira)
+**MIT License** Β© [Gaspard Kirira](https://github.com/gkirira)
See [LICENSE](../../LICENSE) for details.
diff --git a/docs/modules/orm.md b/docs/modules/orm.md
index a762914..86006e8 100644
--- a/docs/modules/orm.md
+++ b/docs/modules/orm.md
@@ -109,35 +109,91 @@ Example: Simple CRUD (examples/users_crud.cpp)
```cpp
#include
+#include
+#include
+
#include
+#include
+#include
-struct User {
+struct User
+{
std::int64_t id{};
std::string name;
std::string email;
int age{};
};
-namespace Vix::orm {
-template<> struct Mapper {
- static std::vector> toInsertParams(const User& u) {
- return {{"name", u.name}, {"email", u.email}, {"age", u.age}};
- }
- static std::vector> toUpdateParams(const User& u) {
- return {{"name", u.name}, {"email", u.email}, {"age", u.age}};
+namespace vix::orm
+{
+ template <>
+ struct Mapper
+ {
+ static User fromRow(const ResultRow &) { return {}; } // pending
+
+ static std::vector>
+ toInsertParams(const User &u)
+ {
+ return {
+ {"name", u.name},
+ {"email", u.email},
+ {"age", u.age},
+ };
+ }
+
+ static std::vector>
+ toUpdateParams(const User &u)
+ {
+ return {
+ {"name", u.name},
+ {"email", u.email},
+ {"age", u.age},
+ };
+ }
+ };
+} // namespace vix::orm
+
+int main(int argc, char **argv)
+{
+ using namespace vix::orm;
+
+ std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
+ std::string user = (argc > 2 ? argv[2] : "root");
+ std::string pass = (argc > 3 ? argv[3] : "");
+ std::string db = (argc > 4 ? argv[4] : "vixdb");
+
+ try
+ {
+ auto factory = make_mysql_factory(host, user, pass, db);
+
+ PoolConfig cfg;
+ cfg.min = 1;
+ cfg.max = 8;
+
+ ConnectionPool pool{factory, cfg};
+ pool.warmup();
+
+ BaseRepository repo{pool, "users"};
+
+ // Create
+ std::int64_t id = static_cast(
+ repo.create(User{0, "Bob", "gaspardkirira@example.com", 30}));
+ std::cout << "[OK] create β id=" << id << "\n";
+
+ // Update
+ repo.updateById(id, User{id, "Adastra", "adastra@example.com", 31});
+ std::cout << "[OK] update β id=" << id << "\n";
+
+ // Delete
+ repo.removeById(id);
+ std::cout << "[OK] delete β id=" << id << "\n";
+
+ return 0;
}
-};
-}
-
-int main() {
- using namespace Vix::orm;
- try {
- ConnectionPool pool{"tcp://127.0.0.1:3306", "root", "", "vixdb"};
- BaseRepository users{pool, "users"};
- auto id = users.create(User{0, "Alice", "alice@example.com", 28});
- std::cout << "[OK] Insert user β id=" << id << std::endl;
- } catch (const std::exception& e) {
- std::cerr << "[ERR] " << e.what() << std::endl;
+ catch (const std::exception &e)
+ {
+ std::cerr << "[ERR] " << e.what() << "\n";
+ return 1;
}
}
```
@@ -209,23 +265,11 @@ CREATE TABLE IF NOT EXISTS users (
# π§© Example Migration
-```cpp
-#include
-
-class CreateProductsTable : public Vix::orm::Migration {
-public:
- std::string id() const override { return "2025_10_01_create_products"; }
-
- void up(Vix::orm::Connection& c) override {
- auto st = c.prepare("CREATE TABLE products (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255))");
- st->exec();
- }
-
- void down(Vix::orm::Connection& c) override {
- auto st = c.prepare("DROP TABLE IF EXISTS products");
- st->exec();
- }
-};
+```bash
+vix orm migrate --db blog_db --dir ./migrations
+vix orm rollback --steps 1 --db blog_db --dir ./migrations
+vix orm status --db blog_db
+VIX_ORM_DB=blog_db vix orm migrate --dir ./migrations
```
# π§° Installation & Integration (for Vix.cpp)
diff --git a/docs/modules/utils.md b/docs/modules/utils.md
index b61881a..d716bd2 100644
--- a/docs/modules/utils.md
+++ b/docs/modules/utils.md
@@ -5,14 +5,14 @@


-> **vix.cpp/utils** β Foundational utility layer for the **Vix.cpp** framework.
+> **vix.cpp/utils** β Foundational utility layer for the **Vix.cpp** framework.
> Includes environment management, logging, validation, UUIDs, timestamps, and build metadata.
---
## π Overview
-The **Utils module** provides lightweight, reusable helpers used throughout Vix.cpp and standalone C++ apps.
+The **Utils module** provides lightweight, reusable helpers used throughout Vix.cpp and standalone C++ apps.
It is designed to simplify configuration, logging, and validation with zero runtime dependencies beyond `spdlog`.
---
@@ -36,7 +36,7 @@ It is designed to simplify configuration, logging, and validation with zero runt
#include
#include
#include
-using namespace Vix::utils;
+using namespace vix::utils;
int main() {
std::cout << "version=" << version() << "\n";
@@ -63,7 +63,7 @@ uuid4=550e8400-e29b-41d4-a716-446655440000
#include
#include
#include
-using namespace Vix::utils;
+using namespace vix::utils;
using Vix::Logger;
int main() {
@@ -99,7 +99,7 @@ int main() {
#include
#include
#include
-using namespace Vix::utils;
+using namespace vix::utils;
using Vix::Logger;
int main() {
@@ -168,5 +168,5 @@ cmake --build build -j$(nproc)
## π§Ύ License
-**MIT License** Β© [Gaspard Kirira](https://github.com/gkirira)
+**MIT License** Β© [Gaspard Kirira](https://github.com/gkirira)
See [LICENSE](../../LICENSE) for details.
diff --git a/docs/orm/error_handling.md b/docs/orm/error_handling.md
index d1f8d65..18a56d1 100644
--- a/docs/orm/error_handling.md
+++ b/docs/orm/error_handling.md
@@ -14,9 +14,6 @@ int main(int argc, char **argv)
{
// Intentionally wrong DB name to show error
auto raw = make_mysql_conn("tcp://127.0.0.1:3306", "root", "", "db_does_not_exist");
- MySQLConnection c{raw};
- auto st = c.prepare("SELECT 1");
- st->exec();
std::cout << "[INFO] This message may not be reached if connection fails.\n";
}
catch (const DBError &e)
diff --git a/examples/auth/api_key_app_simple.cpp b/examples/auth/api_key_app_simple.cpp
index ff7e2bb..3d93b59 100644
--- a/examples/auth/api_key_app_simple.cpp
+++ b/examples/auth/api_key_app_simple.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// api_key_app_simple.cpp β API Key auth example (Vix.cpp)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file api_key_app_simple.cpp β API Key auth example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run api_key_app_simple.cpp
//
@@ -27,49 +37,49 @@ using namespace vix;
static void print_help()
{
- std::cout
- << "Vix API Key example running:\n"
- << " http://localhost:8080/\n"
- << " http://localhost:8080/secure\n\n"
- << "Valid key:\n"
- << " secret\n\n"
- << "Try:\n"
- << " curl -i http://localhost:8080/secure\n"
- << " curl -i -H \"x-api-key: wrong\" http://localhost:8080/secure\n"
- << " curl -i -H \"x-api-key: secret\" http://localhost:8080/secure\n"
- << " curl -i \"http://localhost:8080/secure?api_key=wrong\"\n"
- << " curl -i \"http://localhost:8080/secure?api_key=secret\"\n\n";
+ std::cout
+ << "Vix API Key example running:\n"
+ << " http://localhost:8080/\n"
+ << " http://localhost:8080/secure\n\n"
+ << "Valid key:\n"
+ << " secret\n\n"
+ << "Try:\n"
+ << " curl -i http://localhost:8080/secure\n"
+ << " curl -i -H \"x-api-key: wrong\" http://localhost:8080/secure\n"
+ << " curl -i -H \"x-api-key: secret\" http://localhost:8080/secure\n"
+ << " curl -i \"http://localhost:8080/secure?api_key=wrong\"\n"
+ << " curl -i \"http://localhost:8080/secure?api_key=secret\"\n\n";
}
int main()
{
- App app;
+ App app;
- // ---------------------------------------------------------------------
- // API key protection (preset)
- // - Header: x-api-key
- // - Query : ?api_key=
- // - Allowed key: "secret"
- // ---------------------------------------------------------------------
- app.use("/secure", middleware::app::api_key_dev("secret"));
- // app.use(
- // "/secure",
- // middleware::app::api_key_auth({
- // .header = "x-api-key",
- // .query_param = "api_key",
- // .allowed_keys = {"secret"},
- // }));
+ // ---------------------------------------------------------------------
+ // API key protection (preset)
+ // - Header: x-api-key
+ // - Query : ?api_key=
+ // - Allowed key: "secret"
+ // ---------------------------------------------------------------------
+ app.use("/secure", middleware::app::api_key_dev("secret"));
+ // app.use(
+ // "/secure",
+ // middleware::app::api_key_auth({
+ // .header = "x-api-key",
+ // .query_param = "api_key",
+ // .allowed_keys = {"secret"},
+ // }));
- // ---------------------------------------------------------------------
- // Routes
- // ---------------------------------------------------------------------
- app.get("/", [](Request &, Response &res)
- { res.send(
- "API Key example:\n"
- " /secure requires x-api-key: secret OR ?api_key=secret\n"); });
+ // ---------------------------------------------------------------------
+ // Routes
+ // ---------------------------------------------------------------------
+ app.get("/", [](Request &, Response &res)
+ { res.send(
+ "API Key example:\n"
+ " /secure requires x-api-key: secret OR ?api_key=secret\n"); });
- app.get("/secure", [](Request &req, Response &res)
- {
+ app.get("/secure", [](Request &req, Response &res)
+ {
auto &key = req.state();
res.json({
@@ -77,7 +87,7 @@ int main()
"api_key", key.value
}); });
- print_help();
- app.run(8080);
- return 0;
+ print_help();
+ app.run(8080);
+ return 0;
}
diff --git a/examples/auth/generate_token/jwt_gen.cpp b/examples/auth/generate_token/jwt_gen.cpp
index e740191..bb635b4 100644
--- a/examples/auth/generate_token/jwt_gen.cpp
+++ b/examples/auth/generate_token/jwt_gen.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// jwt_gen.cpp β generate HS256 JWT tokens for rbac_app_simple.cpp (Vix.cpp)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file jwt_gen.cpp β generate HS256 JWT tokens for rbac_app_simple.cpp (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Build:
// g++ -std=c++20 jwt_gen.cpp -lssl -lcrypto -O2 && ./a.out
//
@@ -21,78 +31,78 @@
static std::string b64url_encode(const unsigned char *data, size_t len)
{
- std::string b64;
- b64.resize(4 * ((len + 2) / 3));
-
- int out_len = EVP_EncodeBlock(
- reinterpret_cast(&b64[0]),
- data,
- static_cast(len));
-
- b64.resize(static_cast(out_len));
-
- for (char &c : b64)
- {
- if (c == '+')
- c = '-';
- else if (c == '/')
- c = '_';
- }
- while (!b64.empty() && b64.back() == '=')
- b64.pop_back();
-
- return b64;
+ std::string b64;
+ b64.resize(4 * ((len + 2) / 3));
+
+ int out_len = EVP_EncodeBlock(
+ reinterpret_cast(&b64[0]),
+ data,
+ static_cast(len));
+
+ b64.resize(static_cast(out_len));
+
+ for (char &c : b64)
+ {
+ if (c == '+')
+ c = '-';
+ else if (c == '/')
+ c = '_';
+ }
+ while (!b64.empty() && b64.back() == '=')
+ b64.pop_back();
+
+ return b64;
}
static std::string hmac_sha256_b64url(std::string_view msg, std::string_view secret)
{
- unsigned int out_len = 0;
- unsigned char out[EVP_MAX_MD_SIZE];
-
- HMAC(EVP_sha256(),
- secret.data(),
- static_cast(secret.size()),
- reinterpret_cast(msg.data()),
- msg.size(),
- out,
- &out_len);
-
- return b64url_encode(out, static_cast(out_len));
+ unsigned int out_len = 0;
+ unsigned char out[EVP_MAX_MD_SIZE];
+
+ HMAC(EVP_sha256(),
+ secret.data(),
+ static_cast(secret.size()),
+ reinterpret_cast(msg.data()),
+ msg.size(),
+ out,
+ &out_len);
+
+ return b64url_encode(out, static_cast(out_len));
}
static std::string make_jwt_hs256(const nlohmann::json &payload, const std::string &secret)
{
- nlohmann::json header = {{"alg", "HS256"}, {"typ", "JWT"}};
+ nlohmann::json header = {{"alg", "HS256"}, {"typ", "JWT"}};
- const std::string h = header.dump();
- const std::string p = payload.dump();
+ const std::string h = header.dump();
+ const std::string p = payload.dump();
- const std::string h64 = b64url_encode(reinterpret_cast(h.data()), h.size());
- const std::string p64 = b64url_encode(reinterpret_cast(p.data()), p.size());
+ const std::string h64 = b64url_encode(reinterpret_cast(h.data()), h.size());
+ const std::string p64 = b64url_encode(reinterpret_cast(p.data()), p.size());
- const std::string signing = h64 + "." + p64;
- const std::string sig = hmac_sha256_b64url(signing, secret);
+ const std::string signing = h64 + "." + p64;
+ const std::string sig = hmac_sha256_b64url(signing, secret);
- return signing + "." + sig;
+ return signing + "." + sig;
}
int main()
{
- const std::string secret = "dev_secret";
-
- nlohmann::json ok = {
- {"sub", "user123"},
- {"roles", {"admin"}},
- {"perms", {"products:write", "orders:read"}}};
-
- nlohmann::json no_perm = {
- {"sub", "user123"},
- {"roles", {"admin"}},
- {"perms", {"orders:read"}}};
-
- std::cout << "TOKEN_OK:\n"
- << make_jwt_hs256(ok, secret) << "\n\n";
- std::cout << "TOKEN_NO_PERM:\n"
- << make_jwt_hs256(no_perm, secret) << "\n";
- return 0;
+ const std::string secret = "dev_secret";
+
+ nlohmann::json ok = {
+ {"sub", "user123"},
+ {"roles", {"admin"}},
+ {"perms", {"products:write", "orders:read"}}};
+
+ nlohmann::json no_perm = {
+ {"sub", "user123"},
+ {"roles", {"admin"}},
+ {"perms", {"orders:read"}}};
+
+ std::cout << "TOKEN_OK:\n"
+ << make_jwt_hs256(ok, secret) << "\n\n";
+ std::cout << "TOKEN_NO_PERM:\n"
+ << make_jwt_hs256(no_perm, secret) << "\n";
+ return 0;
}
diff --git a/examples/auth/jwt/jwt_app_simple.cpp b/examples/auth/jwt/jwt_app_simple.cpp
index e6d58d0..428d671 100644
--- a/examples/auth/jwt/jwt_app_simple.cpp
+++ b/examples/auth/jwt/jwt_app_simple.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// jwt_app_simple.cpp β JWT middleware (App) super simple
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file jwt_app_simple.cpp β JWT middleware (App) super simple
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run jwt_app_simple.cpp
//
@@ -28,22 +38,22 @@ static const std::string kToken =
int main()
{
- App app;
+ App app;
- // π Protect ONLY /secure (dev preset: verify_exp = false)
- app.use("/secure", middleware::app::jwt_dev("dev_secret"));
+ // π Protect ONLY /secure (dev preset: verify_exp = false)
+ app.use("/secure", middleware::app::jwt_dev("dev_secret"));
- app.get("/", [](Request &, Response &res)
- { res.send(
- "JWT example:\n"
- " GET /secure requires Bearer token.\n"
- "\n"
- "Try:\n"
- " curl -i http://localhost:8080/secure\n"
- " curl -i -H \"Authorization: Bearer \" http://localhost:8080/secure\n"); });
+ app.get("/", [](Request &, Response &res)
+ { res.send(
+ "JWT example:\n"
+ " GET /secure requires Bearer token.\n"
+ "\n"
+ "Try:\n"
+ " curl -i http://localhost:8080/secure\n"
+ " curl -i -H \"Authorization: Bearer \" http://localhost:8080/secure\n"); });
- app.get("/secure", [](Request &req, Response &res)
- {
+ app.get("/secure", [](Request &req, Response &res)
+ {
auto &claims = req.state();
res.json({"ok", true,
"sub", claims.subject,
@@ -51,16 +61,16 @@ int main()
res.status(501).json({"ok", false,
"error", "JWT middleware not enabled (VIX_ENABLE_JWT)"}); });
- std::cout
- << "Vix JWT example running:\n"
- << " http://localhost:8080/\n"
- << " http://localhost:8080/secure\n\n"
- << "Use this token:\n"
- << " " << kToken << "\n\n"
- << "Test:\n"
- << " curl -i -H \"Authorization: Bearer " << kToken
- << "\" http://localhost:8080/secure\n";
+ std::cout
+ << "Vix JWT example running:\n"
+ << " http://localhost:8080/\n"
+ << " http://localhost:8080/secure\n\n"
+ << "Use this token:\n"
+ << " " << kToken << "\n\n"
+ << "Test:\n"
+ << " curl -i -H \"Authorization: Bearer " << kToken
+ << "\" http://localhost:8080/secure\n";
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/auth/rbac/rbac_app_simple.cpp b/examples/auth/rbac/rbac_app_simple.cpp
index d1e70ac..dffd39d 100644
--- a/examples/auth/rbac/rbac_app_simple.cpp
+++ b/examples/auth/rbac/rbac_app_simple.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// rbac_app_simple.cpp β RBAC (roles + perms) example (Vix.cpp)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file rbac_app_simple.cpp β RBAC (roles + perms) example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run rbac_app_simple.cpp
//
@@ -42,48 +52,48 @@ static const std::string TOKEN_NO_PERM =
int main()
{
- App app;
-
- // 1) JWT auth (puts JwtClaims into request state)
- vix::middleware::auth::JwtOptions jwt_opt{};
- jwt_opt.secret = "dev_secret";
- jwt_opt.verify_exp = false;
-
- // 2) RBAC: build Authz from JwtClaims, then enforce rules
- vix::middleware::auth::RbacOptions rbac_opt{};
- rbac_opt.require_auth = true;
- rbac_opt.use_resolver = false; // keep the example simple
-
- auto jwt_mw = vix::middleware::app::adapt_ctx(vix::middleware::auth::jwt(jwt_opt));
- auto ctx_mw = vix::middleware::app::adapt_ctx(vix::middleware::auth::rbac_context(rbac_opt));
- auto role_mw = vix::middleware::app::adapt_ctx(vix::middleware::auth::require_role("admin"));
- auto perm_mw = vix::middleware::app::adapt_ctx(vix::middleware::auth::require_perm("products:write"));
-
- // Protect only /admin
- app.use(vix::middleware::app::when(
- [](const Request &req)
- { return req.path() == "/admin"; },
- std::move(jwt_mw)));
- app.use(vix::middleware::app::when(
- [](const Request &req)
- { return req.path() == "/admin"; },
- std::move(ctx_mw)));
- app.use(vix::middleware::app::when(
- [](const Request &req)
- { return req.path() == "/admin"; },
- std::move(role_mw)));
- app.use(vix::middleware::app::when(
- [](const Request &req)
- { return req.path() == "/admin"; },
- std::move(perm_mw)));
-
- // Public
- app.get("/", [](Request &, Response &res)
- { res.send("RBAC example: /admin requires role=admin + perm=products:write"); });
-
- // Protected
- app.get("/admin", [](Request &req, Response &res)
- {
+ App app;
+
+ // 1) JWT auth (puts JwtClaims into request state)
+ vix::middleware::auth::JwtOptions jwt_opt{};
+ jwt_opt.secret = "dev_secret";
+ jwt_opt.verify_exp = false;
+
+ // 2) RBAC: build Authz from JwtClaims, then enforce rules
+ vix::middleware::auth::RbacOptions rbac_opt{};
+ rbac_opt.require_auth = true;
+ rbac_opt.use_resolver = false; // keep the example simple
+
+ auto jwt_mw = vix::middleware::app::adapt_ctx(vix::middleware::auth::jwt(jwt_opt));
+ auto ctx_mw = vix::middleware::app::adapt_ctx(vix::middleware::auth::rbac_context(rbac_opt));
+ auto role_mw = vix::middleware::app::adapt_ctx(vix::middleware::auth::require_role("admin"));
+ auto perm_mw = vix::middleware::app::adapt_ctx(vix::middleware::auth::require_perm("products:write"));
+
+ // Protect only /admin
+ app.use(vix::middleware::app::when(
+ [](const Request &req)
+ { return req.path() == "/admin"; },
+ std::move(jwt_mw)));
+ app.use(vix::middleware::app::when(
+ [](const Request &req)
+ { return req.path() == "/admin"; },
+ std::move(ctx_mw)));
+ app.use(vix::middleware::app::when(
+ [](const Request &req)
+ { return req.path() == "/admin"; },
+ std::move(role_mw)));
+ app.use(vix::middleware::app::when(
+ [](const Request &req)
+ { return req.path() == "/admin"; },
+ std::move(perm_mw)));
+
+ // Public
+ app.get("/", [](Request &, Response &res)
+ { res.send("RBAC example: /admin requires role=admin + perm=products:write"); });
+
+ // Protected
+ app.get("/admin", [](Request &req, Response &res)
+ {
auto& authz = req.state();
res.json({
@@ -93,17 +103,17 @@ int main()
"has_products_write", authz.has_perm("products:write")
}); });
- std::cout
- << "Vix RBAC example running:\n"
- << " http://localhost:8080/\n"
- << " http://localhost:8080/admin\n\n"
- << "TOKEN_OK:\n " << TOKEN_OK << "\n\n"
- << "TOKEN_NO_PERM:\n " << TOKEN_NO_PERM << "\n\n"
- << "Try:\n"
- << " curl -i http://localhost:8080/admin\n"
- << " curl -i -H \"Authorization: Bearer " << TOKEN_OK << "\" http://localhost:8080/admin\n"
- << " curl -i -H \"Authorization: Bearer " << TOKEN_NO_PERM << "\" http://localhost:8080/admin\n";
-
- app.run(8080);
- return 0;
+ std::cout
+ << "Vix RBAC example running:\n"
+ << " http://localhost:8080/\n"
+ << " http://localhost:8080/admin\n\n"
+ << "TOKEN_OK:\n " << TOKEN_OK << "\n\n"
+ << "TOKEN_NO_PERM:\n " << TOKEN_NO_PERM << "\n\n"
+ << "Try:\n"
+ << " curl -i http://localhost:8080/admin\n"
+ << " curl -i -H \"Authorization: Bearer " << TOKEN_OK << "\" http://localhost:8080/admin\n"
+ << " curl -i -H \"Authorization: Bearer " << TOKEN_NO_PERM << "\" http://localhost:8080/admin\n";
+
+ app.run(8080);
+ return 0;
}
diff --git a/examples/body_limit/body_limit_app.cpp b/examples/body_limit/body_limit_app.cpp
index a75237d..5e57357 100644
--- a/examples/body_limit/body_limit_app.cpp
+++ b/examples/body_limit/body_limit_app.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// body_limit_app.cpp β Body limit middleware example (Vix.cpp)
-//
+/**
+ *
+ * @file body_limit_app.cpp β Body limit middleware example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run vix/examples/body_limit_app.cpp
//
@@ -35,43 +45,43 @@ using namespace vix;
static void register_routes(App &app)
{
- app.get("/", [](Request &, Response &res)
- { res.send("body_limit example: /api/ping, /api/echo, /api/strict"); });
+ app.get("/", [](Request &, Response &res)
+ { res.send("body_limit example: /api/ping, /api/echo, /api/strict"); });
- app.get("/api/ping", [](Request &, Response &res)
- { res.json({"ok", true, "msg", "pong"}); });
+ app.get("/api/ping", [](Request &, Response &res)
+ { res.json({"ok", true, "msg", "pong"}); });
- app.post("/api/echo", [](Request &req, Response &res)
- { res.json({"ok", true,
- "bytes", static_cast(req.body().size()),
- "content_type", req.header("content-type")}); });
+ app.post("/api/echo", [](Request &req, Response &res)
+ { res.json({"ok", true,
+ "bytes", static_cast(req.body().size()),
+ "content_type", req.header("content-type")}); });
- app.post("/api/strict", [](Request &req, Response &res)
- { res.json({"ok", true,
- "msg", "strict accepted",
- "bytes", static_cast(req.body().size())}); });
+ app.post("/api/strict", [](Request &req, Response &res)
+ { res.json({"ok", true,
+ "msg", "strict accepted",
+ "bytes", static_cast(req.body().size())}); });
}
int main()
{
- App app;
+ App app;
- // /api: max 32 bytes (demo), chunked allowed
- app.use("/api", middleware::app::body_limit_dev(
- 32, // max_bytes
- false, // apply_to_get
- true // allow_chunked
- ));
+ // /api: max 32 bytes (demo), chunked allowed
+ app.use("/api", middleware::app::body_limit_dev(
+ 32, // max_bytes
+ false, // apply_to_get
+ true // allow_chunked
+ ));
- // /api/strict: max 32 bytes, chunked NOT allowed => 411 if missing Content-Length
- app.use("/api/strict", middleware::app::body_limit_dev(
- 32, // max_bytes
- false, // apply_to_get
- false // allow_chunked (strict)
- ));
+ // /api/strict: max 32 bytes, chunked NOT allowed => 411 if missing Content-Length
+ app.use("/api/strict", middleware::app::body_limit_dev(
+ 32, // max_bytes
+ false, // apply_to_get
+ false // allow_chunked (strict)
+ ));
- register_routes(app);
+ register_routes(app);
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/body_limit/body_limit_should_apply.cpp b/examples/body_limit/body_limit_should_apply.cpp
index ea057af..570b17c 100644
--- a/examples/body_limit/body_limit_should_apply.cpp
+++ b/examples/body_limit/body_limit_should_apply.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// body_limit_should_apply.cpp β CORS + conditional body limit via should_apply()
-//
+/**
+ *
+ * @file body_limit_should_apply.cpp β CORS + conditional body limit via should_apply()
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run vix/examples/body_limit_should_apply.cpp
//
@@ -31,19 +41,19 @@ using namespace vix;
// ------------------------------------------------------------
static void install_cors(App &app)
{
- app.use("/", middleware::app::cors_ip_demo({"http://localhost:5173",
- "http://127.0.0.1:5173",
- "http://0.0.0.0:5173"}));
+ app.use("/", middleware::app::cors_ip_demo({"http://localhost:5173",
+ "http://127.0.0.1:5173",
+ "http://0.0.0.0:5173"}));
- auto options_noop = [](Request &, Response &res)
- {
- res.status(204).send();
- };
+ auto options_noop = [](Request &, Response &res)
+ {
+ res.status(204).send();
+ };
- app.options("/api/ping", options_noop);
- app.options("/api/echo", options_noop);
- app.options("/api/strict", options_noop);
- app.options("/upload", options_noop);
+ app.options("/api/ping", options_noop);
+ app.options("/api/echo", options_noop);
+ app.options("/api/strict", options_noop);
+ app.options("/upload", options_noop);
}
// ------------------------------------------------------------
@@ -51,8 +61,8 @@ static void install_cors(App &app)
// ------------------------------------------------------------
static void install_body_limit(App &app)
{
- // Applies only to POST/PUT/PATCH (alias)
- app.use("/", middleware::app::body_limit_write_dev(16));
+ // Applies only to POST/PUT/PATCH (alias)
+ app.use("/", middleware::app::body_limit_write_dev(16));
}
// ------------------------------------------------------------
@@ -60,16 +70,16 @@ static void install_body_limit(App &app)
// ------------------------------------------------------------
static void install_routes(App &app)
{
- app.get("/health", [](Request &, Response &res)
- { res.json({"ok", true}); });
+ app.get("/health", [](Request &, Response &res)
+ { res.json({"ok", true}); });
- app.get("/api/ping", [](Request &, Response &res)
- {
+ app.get("/api/ping", [](Request &, Response &res)
+ {
res.header("X-Request-Id", "req_ping_1");
res.json({"ok", true, "msg", "pong"}); });
- app.post("/api/echo", [](Request &req, Response &res)
- {
+ app.post("/api/echo", [](Request &req, Response &res)
+ {
res.header("X-Request-Id", "req_echo_1");
res.json({
"ok", true,
@@ -78,26 +88,26 @@ static void install_routes(App &app)
"body", req.body()
}); });
- app.post("/api/strict", [](Request &req, Response &res)
- { res.json({"ok", true, "bytes", static_cast(req.body().size())}); });
+ app.post("/api/strict", [](Request &req, Response &res)
+ { res.json({"ok", true, "bytes", static_cast(req.body().size())}); });
- app.post("/upload", [](Request &req, Response &res)
- { res.json({"ok", true, "bytes", static_cast(req.body().size())}); });
+ app.post("/upload", [](Request &req, Response &res)
+ { res.json({"ok", true, "bytes", static_cast(req.body().size())}); });
}
static void run_app()
{
- App app;
+ App app;
- install_cors(app);
- install_body_limit(app);
- install_routes(app);
+ install_cors(app);
+ install_body_limit(app);
+ install_routes(app);
- app.run(8080);
+ app.run(8080);
}
int main()
{
- run_app();
- return 0;
+ run_app();
+ return 0;
}
diff --git a/examples/cache/http_cache_app_custom_cache.cpp b/examples/cache/http_cache_app_custom_cache.cpp
index 886bd61..6764796 100644
--- a/examples/cache/http_cache_app_custom_cache.cpp
+++ b/examples/cache/http_cache_app_custom_cache.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// http_cache_app_custom_cache.cpp β HTTP Cache (Custom Cache Injection)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file http_cache_app_custom_cache.cpp β HTTP Cache (Custom Cache Injection)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run examples/http_cache_app_custom_cache.cpp
//
@@ -23,43 +33,43 @@ using namespace vix;
static void register_routes(App &app)
{
- app.get("/api/slow", [](Request &, Response &res)
- {
+ app.get("/api/slow", [](Request &, Response &res)
+ {
std::this_thread::sleep_for(std::chrono::milliseconds(250));
res.text("slow response (origin)"); });
- app.get("/", [](Request &, Response &res)
- { res.text("home (not cached)"); });
+ app.get("/", [](Request &, Response &res)
+ { res.text("home (not cached)"); });
}
int main()
{
- App app;
+ App app;
- // Build a default cache instance (MemoryStore + policy) with ttl
- auto cache = middleware::app::make_default_cache({
- .ttl_ms = 30'000,
- });
+ // Build a default cache instance (MemoryStore + policy) with ttl
+ auto cache = middleware::app::make_default_cache({
+ .ttl_ms = 30'000,
+ });
- // Install middleware using injected cache
- app.use("/api/", middleware::app::http_cache_mw({
- .prefix = "/api/",
- .only_get = true,
- .ttl_ms = 30'000,
+ // Install middleware using injected cache
+ app.use("/api/", middleware::app::http_cache_mw({
+ .prefix = "/api/",
+ .only_get = true,
+ .ttl_ms = 30'000,
- .allow_bypass = true,
- .bypass_header = "x-vix-cache",
- .bypass_value = "bypass",
+ .allow_bypass = true,
+ .bypass_header = "x-vix-cache",
+ .bypass_value = "bypass",
- .vary_headers = {},
- .cache = cache,
+ .vary_headers = {},
+ .cache = cache,
- .add_debug_header = true,
- .debug_header = "x-vix-cache-status",
- }));
+ .add_debug_header = true,
+ .debug_header = "x-vix-cache-status",
+ }));
- register_routes(app);
+ register_routes(app);
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/cache/http_cache_app_debug.cpp b/examples/cache/http_cache_app_debug.cpp
index 9756b60..ae51698 100644
--- a/examples/cache/http_cache_app_debug.cpp
+++ b/examples/cache/http_cache_app_debug.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// http_cache_app_debug.cpp β HTTP Cache (Debug + Vary)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file http_cache_app_debug.cpp β HTTP Cache (Debug + Vary)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run examples/http_cache_app_debug.cpp
//
@@ -30,11 +40,11 @@ using namespace vix;
static void register_routes(App &app)
{
- app.get("/", [](Request &, Response &res)
- { res.text("home (not cached)"); });
+ app.get("/", [](Request &, Response &res)
+ { res.text("home (not cached)"); });
- app.get("/api/users", [](Request &req, Response &res)
- {
+ app.get("/api/users", [](Request &req, Response &res)
+ {
// β
Request API you actually have:
// - req.has_header(name)
// - req.header(name) -> std::string
@@ -51,24 +61,24 @@ static void register_routes(App &app)
int main()
{
- App app;
+ App app;
- app.use("/api/", middleware::app::http_cache({
- .ttl_ms = 30'000,
- .allow_bypass = true,
- .bypass_header = "x-vix-cache",
- .bypass_value = "bypass",
+ app.use("/api/", middleware::app::http_cache({
+ .ttl_ms = 30'000,
+ .allow_bypass = true,
+ .bypass_header = "x-vix-cache",
+ .bypass_value = "bypass",
- // Create different cache entries per language header
- .vary_headers = {"accept-language"},
+ // Create different cache entries per language header
+ .vary_headers = {"accept-language"},
- // Useful for demo/learning
- .add_debug_header = true,
- .debug_header = "x-vix-cache-status",
- }));
+ // Useful for demo/learning
+ .add_debug_header = true,
+ .debug_header = "x-vix-cache-status",
+ }));
- register_routes(app);
+ register_routes(app);
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/cache/http_cache_app_simple.cpp b/examples/cache/http_cache_app_simple.cpp
index 928759c..fdfac59 100644
--- a/examples/cache/http_cache_app_simple.cpp
+++ b/examples/cache/http_cache_app_simple.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// http_cache_app_simple.cpp β HTTP Cache (Simple)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file http_cache_app_simple.cpp β HTTP Cache (Simple)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run examples/http_cache_app_simple.cpp
//
@@ -21,27 +31,27 @@ using namespace vix;
static void register_routes(App &app)
{
- app.get("/", [](Request &, Response &res)
- { res.text("home (not cached)"); });
+ app.get("/", [](Request &, Response &res)
+ { res.text("home (not cached)"); });
- app.get("/api/users", [](Request &, Response &res)
- { res.text("users from origin"); });
+ app.get("/api/users", [](Request &, Response &res)
+ { res.text("users from origin"); });
}
int main()
{
- App app;
+ App app;
- // Cache GET requests under /api/*
- app.use("/api/", middleware::app::http_cache({
- .ttl_ms = 30'000,
- .allow_bypass = true,
- .bypass_header = "x-vix-cache",
- .bypass_value = "bypass",
- }));
+ // Cache GET requests under /api/*
+ app.use("/api/", middleware::app::http_cache({
+ .ttl_ms = 30'000,
+ .allow_bypass = true,
+ .bypass_header = "x-vix-cache",
+ .bypass_value = "bypass",
+ }));
- register_routes(app);
+ register_routes(app);
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/compression/compression_app_simple.cpp b/examples/compression/compression_app_simple.cpp
index cf0dc05..b2aa265 100644
--- a/examples/compression/compression_app_simple.cpp
+++ b/examples/compression/compression_app_simple.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// compression_app_simple.cpp β Compression middleware (App) example (Vix.cpp)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file compression_app_simple.cpp β Compression middleware (App) example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run compression_app_simple.cpp
//
@@ -29,45 +39,45 @@ using namespace vix;
static void print_help()
{
- std::cout
- << "Vix Compression example running:\n"
- << " http://localhost:8080/\n"
- << " http://localhost:8080/x\n"
- << " http://localhost:8080/small\n\n"
- << "Try:\n"
- << " curl -i http://localhost:8080/x\n"
- << " curl -i -H \"Accept-Encoding: gzip, br\" http://localhost:8080/x\n"
- << " curl -i -H \"Accept-Encoding: gzip\" http://localhost:8080/small\n";
+ std::cout
+ << "Vix Compression example running:\n"
+ << " http://localhost:8080/\n"
+ << " http://localhost:8080/x\n"
+ << " http://localhost:8080/small\n\n"
+ << "Try:\n"
+ << " curl -i http://localhost:8080/x\n"
+ << " curl -i -H \"Accept-Encoding: gzip, br\" http://localhost:8080/x\n"
+ << " curl -i -H \"Accept-Encoding: gzip\" http://localhost:8080/small\n";
}
int main()
{
- App app;
+ App app;
- // Install compression middleware globally
- auto mw = vix::middleware::app::adapt_ctx(
- vix::middleware::performance::compression({
- .min_size = 8, // same as smoke test
- .add_vary = true,
- .enabled = true,
- }));
+ // Install compression middleware globally
+ auto mw = vix::middleware::app::adapt_ctx(
+ vix::middleware::performance::compression({
+ .min_size = 8, // same as smoke test
+ .add_vary = true,
+ .enabled = true,
+ }));
- app.use(std::move(mw));
+ app.use(std::move(mw));
- app.get("/", [](Request &, Response &res)
- { res.send("Compression middleware installed. Try /x with Accept-Encoding."); });
+ app.get("/", [](Request &, Response &res)
+ { res.send("Compression middleware installed. Try /x with Accept-Encoding."); });
- // Big body => should trigger "planned" (debug) if Accept-Encoding asks gzip/br
- app.get("/x", [](Request &, Response &res)
- { res.status(200).send(std::string(20, 'a')); });
+ // Big body => should trigger "planned" (debug) if Accept-Encoding asks gzip/br
+ app.get("/x", [](Request &, Response &res)
+ { res.status(200).send(std::string(20, 'a')); });
- // Small body => should NOT trigger "planned"
- app.get("/small", [](Request &, Response &res)
- {
- res.status(200).send("aaaa"); // 4 bytes
- });
+ // Small body => should NOT trigger "planned"
+ app.get("/small", [](Request &, Response &res)
+ {
+ res.status(200).send("aaaa"); // 4 bytes
+ });
- print_help();
- app.run(8080);
- return 0;
+ print_help();
+ app.run(8080);
+ return 0;
}
diff --git a/examples/cors/cors_app_basic.cpp b/examples/cors/cors_app_basic.cpp
index b5e455d..e839a82 100644
--- a/examples/cors/cors_app_basic.cpp
+++ b/examples/cors/cors_app_basic.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// cors_app_basic.cpp β Basic CORS example (Vix.cpp)
+/**
+ *
+ * @file cors_app_basic.cpp β Basic CORS example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// curl -i http://localhost:8080/api -H "Origin: https://example.com"
// ============================================================================
@@ -10,14 +21,14 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- app.use("/api", middleware::app::cors_dev({"https://example.com"}));
+ app.use("/api", middleware::app::cors_dev({"https://example.com"}));
- app.get("/api", [](Request &, Response &res)
- {
+ app.get("/api", [](Request &, Response &res)
+ {
res.header("X-Request-Id", "req_123");
res.json({ "ok", true }); });
- app.run(8080);
+ app.run(8080);
}
diff --git a/examples/cors/cors_app_strict.cpp b/examples/cors/cors_app_strict.cpp
index b2f743f..bf1e72a 100644
--- a/examples/cors/cors_app_strict.cpp
+++ b/examples/cors/cors_app_strict.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// cors_app_strict.cpp β Strict CORS + controlled preflight (Vix.cpp)
+/**
+ *
+ * @file cors_app_strict.cpp β Strict CORS + controlled preflight (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// # allowed
// curl -i -X OPTIONS http://localhost:8080/api \
// -H "Origin: https://example.com" \
@@ -18,22 +29,22 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- // π Apply CORS only on /api prefix
- app.use("/api", middleware::app::cors_dev({"https://example.com"}));
+ // π Apply CORS only on /api prefix
+ app.use("/api", middleware::app::cors_dev({"https://example.com"}));
- // β
Explicit OPTIONS route (lets middleware answer preflight)
- app.options("/api", [](Request &, Response &res)
- {
+ // β
Explicit OPTIONS route (lets middleware answer preflight)
+ app.options("/api", [](Request &, Response &res)
+ {
// Optional debug marker (only if this handler executes)
res.header("X-OPTIONS-HIT", "1");
res.status(204).send(); });
- app.get("/api", [](Request &, Response &res)
- {
+ app.get("/api", [](Request &, Response &res)
+ {
res.header("X-Request-Id", "req_123");
res.json({ "ok", true }); });
- app.run(8080);
+ app.run(8080);
}
diff --git a/examples/csrf/csrf_pipeline_demo.cpp b/examples/csrf/csrf_pipeline_demo.cpp
index 206110b..15c45c3 100644
--- a/examples/csrf/csrf_pipeline_demo.cpp
+++ b/examples/csrf/csrf_pipeline_demo.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// csrf_pipeline_demo.cpp β CSRF pipeline demo (Vix.cpp)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file csrf_pipeline_demo.cpp β CSRF pipeline demo (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run csrf_pipeline_demo.cpp
// ============================================================================
@@ -17,66 +27,66 @@ using namespace vix::middleware;
static vix::vhttp::RawRequest make_post(bool ok)
{
- namespace http = boost::beast::http;
+ namespace http = boost::beast::http;
- vix::vhttp::RawRequest req{http::verb::post, "/api/update", 11};
- req.set(http::field::host, "localhost");
+ vix::vhttp::RawRequest req{http::verb::post, "/api/update", 11};
+ req.set(http::field::host, "localhost");
- // Cookie + header must match
- req.set("Cookie", "csrf_token=abc");
- req.set("x-csrf-token", ok ? "abc" : "wrong");
+ // Cookie + header must match
+ req.set("Cookie", "csrf_token=abc");
+ req.set("x-csrf-token", ok ? "abc" : "wrong");
- req.body() = "x=1";
- req.prepare_payload();
- return req;
+ req.body() = "x=1";
+ req.prepare_payload();
+ return req;
}
int main()
{
- namespace http = boost::beast::http;
+ namespace http = boost::beast::http;
- // FAIL
- {
- auto raw = make_post(false);
- http::response res;
+ // FAIL
+ {
+ auto raw = make_post(false);
+ http::response res;
- vix::vhttp::Request req(raw, {});
- vix::vhttp::ResponseWrapper w(res);
+ vix::vhttp::Request req(raw, {});
+ vix::vhttp::ResponseWrapper w(res);
- HttpPipeline p;
- p.use(vix::middleware::security::csrf()); // MiddlewareFn(Context&, Next)
+ HttpPipeline p;
+ p.use(vix::middleware::security::csrf()); // MiddlewareFn(Context&, Next)
- int final_calls = 0;
- p.run(req, w, [&](Request &, Response &)
- {
+ int final_calls = 0;
+ p.run(req, w, [&](Request &, Response &)
+ {
final_calls++;
w.ok().text("OK"); });
- assert(final_calls == 0);
- assert(res.result_int() == 403);
- }
+ assert(final_calls == 0);
+ assert(res.result_int() == 403);
+ }
- // OK
- {
- auto raw = make_post(true);
- http::response res;
+ // OK
+ {
+ auto raw = make_post(true);
+ http::response res;
- vix::vhttp::Request req(raw, {});
- vix::vhttp::ResponseWrapper w(res);
+ vix::vhttp::Request req(raw, {});
+ vix::vhttp::ResponseWrapper w(res);
- HttpPipeline p;
- p.use(vix::middleware::security::csrf());
+ HttpPipeline p;
+ p.use(vix::middleware::security::csrf());
- int final_calls = 0;
- p.run(req, w, [&](Request &, Response &)
- {
+ int final_calls = 0;
+ p.run(req, w, [&](Request &, Response &)
+ {
final_calls++;
w.ok().text("OK"); });
- assert(final_calls == 1);
- assert(res.result_int() == 200);
- }
+ assert(final_calls == 1);
+ assert(res.result_int() == 200);
+ }
- std::cout << "[OK] csrf pipeline demo\n";
- return 0;
+ std::cout << "[OK] csrf pipeline demo\n";
+ return 0;
}
diff --git a/examples/csrf/csrf_strict_server.cpp b/examples/csrf/csrf_strict_server.cpp
index 21f78d3..917cd4d 100644
--- a/examples/csrf/csrf_strict_server.cpp
+++ b/examples/csrf/csrf_strict_server.cpp
@@ -1,6 +1,16 @@
-// ============================================================================
-// csrf_strict_server.cpp β CSRF middleware example (Vix.cpp)
-// ----------------------------------------------------------------------------
+/**
+ *
+ * @file csrf_strict_server.cpp β CSRF middleware example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// Run:
// vix run csrf_strict_server.cpp
//
@@ -27,17 +37,17 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- app.use("/api", middleware::app::csrf_dev());
+ app.use("/api", middleware::app::csrf_dev());
- app.get("/api/csrf", [](Request &, Response &res)
- {
+ app.get("/api/csrf", [](Request &, Response &res)
+ {
res.header("Set-Cookie", "csrf_token=abc; Path=/; SameSite=Lax");
res.json({ "csrf_token", "abc" }); });
- app.post("/api/update", [](Request &, Response &res)
- { res.json({"ok", true, "message", "CSRF passed β
"}); });
+ app.post("/api/update", [](Request &, Response &res)
+ { res.json({"ok", true, "message", "CSRF passed β
"}); });
- app.run(8080);
+ app.run(8080);
}
diff --git a/examples/csrf/security_cors_csrf_server.cpp b/examples/csrf/security_cors_csrf_server.cpp
index 8b04f59..565b398 100644
--- a/examples/csrf/security_cors_csrf_server.cpp
+++ b/examples/csrf/security_cors_csrf_server.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// security_cors_csrf_server.cpp β CORS + CSRF (Vix.cpp)
+/**
+ *
+ * @file security_cors_csrf_server.cpp β CORS + CSRF (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Goal:
// - OPTIONS handled by CORS middleware (preflight)
@@ -51,33 +62,33 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- // Apply on /api (order matters)
- middleware::app::protect_prefix(app, "/api",
- middleware::app::cors_dev({"https://example.com"}));
+ // Apply on /api (order matters)
+ middleware::app::protect_prefix(app, "/api",
+ middleware::app::cors_dev({"https://example.com"}));
- // CSRF expects: cookie "csrf_token" and header "x-csrf-token" by default
- middleware::app::protect_prefix(app, "/api",
- middleware::app::csrf_dev("csrf_token", "x-csrf-token", false));
- // ou strict:
- // middleware::app::protect_prefix(app, "/api",
- // middleware::app::csrf_strict_dev("csrf_token", "x-csrf-token"));
+ // CSRF expects: cookie "csrf_token" and header "x-csrf-token" by default
+ middleware::app::protect_prefix(app, "/api",
+ middleware::app::csrf_dev("csrf_token", "x-csrf-token", false));
+ // ou strict:
+ // middleware::app::protect_prefix(app, "/api",
+ // middleware::app::csrf_strict_dev("csrf_token", "x-csrf-token"));
- // Routes
- app.get("/api/csrf", [](Request &, Response &res)
- {
+ // Routes
+ app.get("/api/csrf", [](Request &, Response &res)
+ {
res.header("Set-Cookie", "csrf_token=abc; Path=/; SameSite=Lax");
res.header("X-Request-Id", "req_123");
res.json({ "csrf_token", "abc" }); });
- app.post("/api/update", [](Request &, Response &res)
- {
+ app.post("/api/update", [](Request &, Response &res)
+ {
res.header("X-Request-Id", "req_456");
res.json({ "ok", true, "message", "CORS β
+ CSRF β
" }); });
- app.get("/", [](Request &, Response &res)
- { res.send("Welcome"); });
+ app.get("/", [](Request &, Response &res)
+ { res.send("Welcome"); });
- app.run(8080);
+ app.run(8080);
}
diff --git a/examples/etag/etag_app_simple.cpp b/examples/etag/etag_app_simple.cpp
index f811109..a33d1c9 100644
--- a/examples/etag/etag_app_simple.cpp
+++ b/examples/etag/etag_app_simple.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// etag_app_simple.cpp β ETag middleware example (Vix.cpp)
+/**
+ *
+ * @file etag_app_simple.cpp β ETag middleware example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Run:
// vix run etag_app_simple.cpp
@@ -21,30 +32,30 @@ using namespace vix;
static void print_help()
{
- std::cout
- << "Vix ETag example running:\n"
- << " http://localhost:8080/x\n\n"
- << "Try:\n"
- << " curl -i http://localhost:8080/x\n"
- << " curl -i -H 'If-None-Match: ' http://localhost:8080/x\n"
- << " curl -I http://localhost:8080/x\n";
+ std::cout
+ << "Vix ETag example running:\n"
+ << " http://localhost:8080/x\n\n"
+ << "Try:\n"
+ << " curl -i http://localhost:8080/x\n"
+ << " curl -i -H 'If-None-Match: ' http://localhost:8080/x\n"
+ << " curl -I http://localhost:8080/x\n";
}
int main()
{
- App app;
+ App app;
- // Install ETag middleware globally
- auto mw = vix::middleware::app::adapt_ctx(
- vix::middleware::performance::etag({.weak = true,
- .add_cache_control_if_missing = false,
- .min_body_size = 1}));
- app.use(std::move(mw));
+ // Install ETag middleware globally
+ auto mw = vix::middleware::app::adapt_ctx(
+ vix::middleware::performance::etag({.weak = true,
+ .add_cache_control_if_missing = false,
+ .min_body_size = 1}));
+ app.use(std::move(mw));
- app.head("/x", [](Request &, Response &res)
- { res.status(200); });
+ app.head("/x", [](Request &, Response &res)
+ { res.status(200); });
- print_help();
- app.run(8080);
- return 0;
+ print_help();
+ app.run(8080);
+ return 0;
}
diff --git a/examples/form/form_app_simple.cpp b/examples/form/form_app_simple.cpp
index df086da..ddd9fee 100644
--- a/examples/form/form_app_simple.cpp
+++ b/examples/form/form_app_simple.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// form_app_simple.cpp β Form parser (App) simple example (Vix.cpp)
+/**
+ *
+ * @file form_app_simple.cpp β Form parser (App) simple example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Run:
// vix run form_app_simple.cpp
@@ -28,20 +39,20 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- app.use("/form", middleware::app::form_dev(128));
+ app.use("/form", middleware::app::form_dev(128));
- app.get("/", [](Request &, Response &res)
- { res.send("POST /form (application/x-www-form-urlencoded)"); });
+ app.get("/", [](Request &, Response &res)
+ { res.send("POST /form (application/x-www-form-urlencoded)"); });
- app.post("/form", [](Request &req, Response &res)
- {
+ app.post("/form", [](Request &req, Response &res)
+ {
auto& fb = req.state();
auto it = fb.fields.find("b");
res.send(it == fb.fields.end() ? "" : it->second); });
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/form/json_app_simple.cpp b/examples/form/json_app_simple.cpp
index 7b2d7ce..0c7b6ee 100644
--- a/examples/form/json_app_simple.cpp
+++ b/examples/form/json_app_simple.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// json_app_simple.cpp β JSON parser (App) simple example (Vix.cpp)
+/**
+ *
+ * @file json_app_simple.cpp β JSON parser (App) simple example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Run:
// vix run json_app_simple.cpp
@@ -39,19 +50,19 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- // 1-liner like Node/FastAPI
- app.use("/json", middleware::app::json_dev(
- /*max_bytes=*/256,
- /*allow_empty=*/true,
- /*require_content_type=*/true));
+ // 1-liner like Node/FastAPI
+ app.use("/json", middleware::app::json_dev(
+ /*max_bytes=*/256,
+ /*allow_empty=*/true,
+ /*require_content_type=*/true));
- app.get("/", [](Request &, Response &res)
- { res.send("POST /json with application/json"); });
+ app.get("/", [](Request &, Response &res)
+ { res.send("POST /json with application/json"); });
- app.post("/json", [](Request &req, Response &res)
- {
+ app.post("/json", [](Request &req, Response &res)
+ {
auto &jb = req.state();
// keep it simple: just echo the parsed JSON
@@ -60,6 +71,6 @@ int main()
"raw", jb.value.dump()
}); });
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/form/json_app_strict.cpp b/examples/form/json_app_strict.cpp
index b04384d..1777343 100644
--- a/examples/form/json_app_strict.cpp
+++ b/examples/form/json_app_strict.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// json_app_strict.cpp β JSON parser (App) strict example (Vix.cpp)
+/**
+ *
+ * @file json_app_strict.cpp β JSON parser (App) strict example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Run:
// vix run json_app_strict.cpp
@@ -38,19 +49,19 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- // STRICT JSON: Content-Type required + body required (allow_empty=false)
- app.use("/json", middleware::app::json_dev(
- /*max_bytes=*/256,
- /*allow_empty=*/false,
- /*require_content_type=*/true));
+ // STRICT JSON: Content-Type required + body required (allow_empty=false)
+ app.use("/json", middleware::app::json_dev(
+ /*max_bytes=*/256,
+ /*allow_empty=*/false,
+ /*require_content_type=*/true));
- app.get("/", [](Request &, Response &res)
- { res.send("POST /json requires a non-empty JSON body."); });
+ app.get("/", [](Request &, Response &res)
+ { res.send("POST /json requires a non-empty JSON body."); });
- app.post("/json", [](Request &req, Response &res)
- {
+ app.post("/json", [](Request &req, Response &res)
+ {
auto &jb = req.state();
if (jb.value.contains("x"))
@@ -58,6 +69,6 @@ int main()
else
res.status(200).send(jb.value.dump()); });
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/form/multipart_app_simple.cpp b/examples/form/multipart_app_simple.cpp
index 60883c6..e7e832e 100644
--- a/examples/form/multipart_app_simple.cpp
+++ b/examples/form/multipart_app_simple.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// multipart_app_simple.cpp β Multipart parser (App) simple example (Vix.cpp)
+/**
+ *
+ * @file multipart_app_simple.cpp β Multipart parser (App) simple example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Run:
// vix run multipart_app_simple.cpp
@@ -33,22 +44,22 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- app.use("/mp", middleware::app::cors_dev());
- app.use("/mp", middleware::app::multipart_save_dev("uploads"));
+ app.use("/mp", middleware::app::cors_dev());
+ app.use("/mp", middleware::app::multipart_save_dev("uploads"));
- app.options("/mp", [](Request &, Response &res)
- { res.status(204).send(""); });
+ app.options("/mp", [](Request &, Response &res)
+ { res.status(204).send(""); });
- app.get("/", [](Request &, Response &res)
- { res.send("POST /mp multipart/form-data (saves files to ./uploads/)"); });
+ app.get("/", [](Request &, Response &res)
+ { res.send("POST /mp multipart/form-data (saves files to ./uploads/)"); });
- app.post("/mp", [](Request &req, Response &res)
- {
+ app.post("/mp", [](Request &req, Response &res)
+ {
auto &form = req.state();
res.json(middleware::app::multipart_json(form)); });
- app.run(8080);
- return 0;
-}
\ No newline at end of file
+ app.run(8080);
+ return 0;
+}
diff --git a/examples/group_builder/group_app_example.cpp b/examples/group_builder/group_app_example.cpp
index fbc65e6..e9ca15b 100644
--- a/examples/group_builder/group_app_example.cpp
+++ b/examples/group_builder/group_app_example.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// group_app_example.cpp β Groups + protect() demo (Vix.cpp)
+/**
+ *
+ * @file group_app_example.cpp β Groups + protect() demo (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Run:
// vix run group_app_example.cpp
@@ -22,15 +33,15 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- // Root
- app.get("/", [](Request &, Response &res)
- { res.send("Welcome. Try /api/public, /api/secure, /api/admin/dashboard"); });
+ // Root
+ app.get("/", [](Request &, Response &res)
+ { res.send("Welcome. Try /api/public, /api/secure, /api/admin/dashboard"); });
- // GROUP: /api
- app.group("/api", [&](App::Group &api)
- {
+ // GROUP: /api
+ app.group("/api", [&](App::Group &api)
+ {
// Public API
api.get("/public", [](Request &, Response &res)
{
@@ -67,21 +78,21 @@ int main()
});
}); });
- // Help
- std::cout
- << "Vix Groups example running:\n"
- << " http://localhost:8080/\n"
- << " http://localhost:8080/api/public\n"
- << " http://localhost:8080/api/secure\n"
- << " http://localhost:8080/api/admin/dashboard\n\n"
- << "API KEY:\n"
- << " secret\n\n"
- << "Try:\n"
- << " curl -i http://localhost:8080/api/public\n"
- << " curl -i http://localhost:8080/api/secure\n"
- << " curl -i -H \"x-api-key: secret\" http://localhost:8080/api/secure\n"
- << " curl -i \"http://localhost:8080/api/secure?api_key=secret\"\n";
+ // Help
+ std::cout
+ << "Vix Groups example running:\n"
+ << " http://localhost:8080/\n"
+ << " http://localhost:8080/api/public\n"
+ << " http://localhost:8080/api/secure\n"
+ << " http://localhost:8080/api/admin/dashboard\n\n"
+ << "API KEY:\n"
+ << " secret\n\n"
+ << "Try:\n"
+ << " curl -i http://localhost:8080/api/public\n"
+ << " curl -i http://localhost:8080/api/secure\n"
+ << " curl -i -H \"x-api-key: secret\" http://localhost:8080/api/secure\n"
+ << " curl -i \"http://localhost:8080/api/secure?api_key=secret\"\n";
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/group_builder/group_builder_example.cpp b/examples/group_builder/group_builder_example.cpp
index 0956478..918e217 100644
--- a/examples/group_builder/group_builder_example.cpp
+++ b/examples/group_builder/group_builder_example.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// group_builder_example.cpp β group() builder style (Vix.cpp)
+/**
+ *
+ * @file group_builder_example.cpp β group() builder style (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Run:
// vix run group_builder_example.cpp
@@ -18,32 +29,32 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- // Create /api group
- auto api = app.group("/api");
+ // Create /api group
+ auto api = app.group("/api");
- // Public endpoint
- api.get("/public", [](Request &, Response &res)
- { res.send("Public endpoint"); });
+ // Public endpoint
+ api.get("/public", [](Request &, Response &res)
+ { res.send("Public endpoint"); });
- // π Protect all following /api routes with API key (DEV preset)
- api.use(middleware::app::api_key_dev("secret"));
+ // π Protect all following /api routes with API key (DEV preset)
+ api.use(middleware::app::api_key_dev("secret"));
- // Secure endpoint
- api.get("/secure", [](Request &req, Response &res)
- {
+ // Secure endpoint
+ api.get("/secure", [](Request &req, Response &res)
+ {
auto &k = req.state();
res.json({
"ok", true,
"api_key", k.value
}); });
- std::cout
- << "Running:\n"
- << " http://localhost:8080/api/public\n"
- << " http://localhost:8080/api/secure\n";
+ std::cout
+ << "Running:\n"
+ << " http://localhost:8080/api/public\n"
+ << " http://localhost:8080/api/secure\n";
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/headers/headers_pipeline_demo.cpp b/examples/headers/headers_pipeline_demo.cpp
index acb6511..3e0f0eb 100644
--- a/examples/headers/headers_pipeline_demo.cpp
+++ b/examples/headers/headers_pipeline_demo.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// headers_pipeline_demo.cpp β Security headers pipeline demo (Vix.cpp)
+/**
+ *
+ * @file headers_pipeline_demo.cpp β Security headers pipeline demo (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Run:
// vix run headers_pipeline_demo.cpp
@@ -16,47 +27,47 @@ using namespace vix::middleware;
static vix::vhttp::RawRequest make_req()
{
- namespace http = boost::beast::http;
- vix::vhttp::RawRequest req{http::verb::get, "/x", 11};
- req.set(http::field::host, "localhost");
- req.prepare_payload();
- return req;
+ namespace http = boost::beast::http;
+ vix::vhttp::RawRequest req{http::verb::get, "/x", 11};
+ req.set(http::field::host, "localhost");
+ req.prepare_payload();
+ return req;
}
int main()
{
- namespace http = boost::beast::http;
+ namespace http = boost::beast::http;
- auto raw = make_req();
- http::response res;
+ auto raw = make_req();
+ http::response res;
- vix::vhttp::Request req(raw, {});
- vix::vhttp::ResponseWrapper w(res);
+ vix::vhttp::Request req(raw, {});
+ vix::vhttp::ResponseWrapper w(res);
- HttpPipeline p;
+ HttpPipeline p;
- // Default headers() adds:
- // - X-Content-Type-Options: nosniff
- // - X-Frame-Options: DENY
- // - Referrer-Policy: no-referrer
- // - Permissions-Policy: ...
- p.use(vix::middleware::security::headers());
+ // Default headers() adds:
+ // - X-Content-Type-Options: nosniff
+ // - X-Frame-Options: DENY
+ // - Referrer-Policy: no-referrer
+ // - Permissions-Policy: ...
+ p.use(vix::middleware::security::headers());
- int final_calls = 0;
- p.run(req, w, [&](Request &, Response &)
- {
+ int final_calls = 0;
+ p.run(req, w, [&](Request &, Response &)
+ {
final_calls++;
w.ok().text("OK"); });
- assert(final_calls == 1);
- assert(res.result_int() == 200);
+ assert(final_calls == 1);
+ assert(res.result_int() == 200);
- // Must exist
- assert(res.find("X-Content-Type-Options") != res.end());
- assert(res.find("X-Frame-Options") != res.end());
- assert(res.find("Referrer-Policy") != res.end());
- assert(res.find("Permissions-Policy") != res.end());
+ // Must exist
+ assert(res.find("X-Content-Type-Options") != res.end());
+ assert(res.find("X-Frame-Options") != res.end());
+ assert(res.find("Referrer-Policy") != res.end());
+ assert(res.find("Permissions-Policy") != res.end());
- std::cout << "[OK] security headers pipeline demo\n";
- return 0;
+ std::cout << "[OK] security headers pipeline demo\n";
+ return 0;
}
diff --git a/examples/headers/security_cors_csrf_headers_server.cpp b/examples/headers/security_cors_csrf_headers_server.cpp
index 488a6e8..bd89c7b 100644
--- a/examples/headers/security_cors_csrf_headers_server.cpp
+++ b/examples/headers/security_cors_csrf_headers_server.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// security_cors_csrf_headers_server.cpp β CORS + CSRF + Security Headers (Vix.cpp)
+/**
+ *
+ * @file security_cors_csrf_headers_server.cpp β CORS + CSRF + Security Headers (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Goal (realistic app):
// - OPTIONS handled by CORS middleware (preflight)
@@ -54,41 +65,41 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- // Apply on ALL /api/*
- // Order matters: headers first, then CORS, then CSRF.
- app.use("/api", middleware::app::security_headers_dev()); // HSTS off by default
- app.use("/api", middleware::app::cors_dev({
- "http://localhost:5173",
- "http://0.0.0.0:5173",
- "https://example.com" // for your curl tests
- }));
- app.use("/api", middleware::app::csrf_dev("csrf_token", "x-csrf-token", false));
+ // Apply on ALL /api/*
+ // Order matters: headers first, then CORS, then CSRF.
+ app.use("/api", middleware::app::security_headers_dev()); // HSTS off by default
+ app.use("/api", middleware::app::cors_dev({
+ "http://localhost:5173",
+ "http://0.0.0.0:5173",
+ "https://example.com" // for your curl tests
+ }));
+ app.use("/api", middleware::app::csrf_dev("csrf_token", "x-csrf-token", false));
- // Explicit OPTIONS routes (lets CORS middleware answer preflight)
- app.options("/api/update", [](Request &, Response &res)
- { res.status(204).send(); });
+ // Explicit OPTIONS routes (lets CORS middleware answer preflight)
+ app.options("/api/update", [](Request &, Response &res)
+ { res.status(204).send(); });
- app.options("/api/csrf", [](Request &, Response &res)
- { res.status(204).send(); });
+ app.options("/api/csrf", [](Request &, Response &res)
+ { res.status(204).send(); });
- // Routes
- app.get("/api/csrf", [](Request &, Response &res)
- {
+ // Routes
+ app.get("/api/csrf", [](Request &, Response &res)
+ {
// For cross-origin cookie in browsers: HTTPS + SameSite=None; Secure
// For local dev HTTP: SameSite=Lax is fine but cookie might not be sent cross-site.
res.header("Set-Cookie", "csrf_token=abc; Path=/; SameSite=Lax");
res.header("X-Request-Id", "req_csrf_1");
res.json({"csrf_token", "abc"}); });
- app.post("/api/update", [](Request &, Response &res)
- {
+ app.post("/api/update", [](Request &, Response &res)
+ {
res.header("X-Request-Id", "req_update_1");
res.json({"ok", true, "message", "CORS β
+ CSRF β
+ HEADERS β
"}); });
- app.get("/", [](Request &, Response &res)
- { res.send("public route"); });
+ app.get("/", [](Request &, Response &res)
+ { res.send("public route"); });
- app.run(8080);
+ app.run(8080);
}
diff --git a/examples/headers/security_headers_server.cpp b/examples/headers/security_headers_server.cpp
index 2ee773b..0d1d658 100644
--- a/examples/headers/security_headers_server.cpp
+++ b/examples/headers/security_headers_server.cpp
@@ -1,5 +1,16 @@
-// ============================================================================
-// security_headers_server.cpp β Security headers middleware example (Vix.cpp)
+/**
+ *
+ * @file security_headers_server.cpp β Security headers middleware example (Vix.cpp)
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ----------------------------------------------------------------------------
// Goal:
// - Apply security headers only on /api prefix
@@ -20,17 +31,17 @@ using namespace vix;
int main()
{
- App app;
+ App app;
- // π Apply security headers only on /api
- app.use("/api", middleware::app::security_headers_dev());
+ // π Apply security headers only on /api
+ app.use("/api", middleware::app::security_headers_dev());
- app.get("/api/ping", [](Request &, Response &res)
- { res.json({"ok", true, "message", "headers applied β
"}); });
+ app.get("/api/ping", [](Request &, Response &res)
+ { res.json({"ok", true, "message", "headers applied β
"}); });
- // Public route (no forced headers)
- app.get("/", [](Request &, Response &res)
- { res.send("public route"); });
+ // Public route (no forced headers)
+ app.get("/", [](Request &, Response &res)
+ { res.send("public route"); });
- app.run(8080);
+ app.run(8080);
}
diff --git a/examples/hello_routes.cpp b/examples/hello_routes.cpp
index 4683cf3..35a20f2 100644
--- a/examples/hello_routes.cpp
+++ b/examples/hello_routes.cpp
@@ -1,5 +1,17 @@
+/**
+ *
+ * @file hello_routes.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ============================================================================
-// hello_routes.cpp β Minimal example (new Vix.cpp API)
// GET /hello β {"message":"Hello, Vix!"}
// GET /user β {"name":"Ada","tags":["c++","net","http"],"profile":{"id":42,"vip":true}}
// GET /users/{id} β 404 {"error":"User not found"}
@@ -11,39 +23,36 @@ namespace J = vix::json;
int main()
{
- App app;
-
- // Simple hello route
- app.get("/hello", [](auto &, auto &res)
- { res.json({"message", "Hello, Vix!"}); });
-
- // Nested JSON using builders
- app.get("/user", [](auto &, auto &res)
- {
- using namespace J;
- res.json({
- "name", "Ada",
- "tags", array({ "c++", "net", "http" }),
- "profile", obj({ "id", 42, "vip", true })
- }); });
-
- // Example with path param
- app.get("/users/{id}", [](auto &, auto &res)
- { res.status(4040).json({"error", "User not found"}); });
-
- app.get("/hello", [](const Request &, Response &)
- { return vix::json::o("message", "Hello", "id", 20); });
-
- app.get("/txt", [](const Request &, Response &)
- {
- return "Hello world"; // const char*
- });
-
- app.get("/mix", [](Request &, Response &res)
- {
+ App app;
+
+ // Simple hello route
+ app.get("/", [](Request &, Response &res)
+ { res.json({"message", "Hello, Vix!"}); });
+
+ // Nested JSON using builders
+ app.get("/user", [](Request &, Response &res)
+ { res.json({"name", "Ada",
+ "tags", J::array({"c++", "net", "http"}),
+ "profile", J::obj({"id", 42, "vip", true})}); });
+
+ // Example with path param
+ app.get("/users/{id}", [](Request &, Response &res)
+ { res.status(4040).json({"error", "User not found"}); });
+
+ app.get("/hello", [](const Request &, Response &res)
+ {
+ res.set_status(200);
+ return vix::json::o("message", "Hello", "id", 20); });
+
+ app.get("/txt", [](const Request &, Response &)
+ {
+ return "Hello world"; // const char*
+ });
+
+ app.get("/mix", [](Request &, Response &res)
+ {
res.status(201).send("Created");
return vix::json::o("ignored", true); });
- app.run(8080);
- return 0;
+ app.run(8080);
}
diff --git a/examples/http/basic_get.cpp b/examples/http/basic_get.cpp
index abce14f..13dcba0 100644
--- a/examples/http/basic_get.cpp
+++ b/examples/http/basic_get.cpp
@@ -1,28 +1,30 @@
-//
-// examples/http/basic_get.cpp
-//
-// Minimal HTTP server using Vix.cpp.
-//
-// Demonstrates:
-// - Creating a vix::App
-// - Registering a simple GET route
-// - Returning a JSON response
-//
-
+/**
+ *
+ * @file examples/http/basic_get.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
using namespace vix;
int main()
{
- App app;
+ App app;
- // GET /
- app.get("/", [](auto &, auto &res)
- { res.json({"framework", "Vix.cpp",
- "message", "Hello from basic_get.cpp π"}); });
+ // GET /
+ app.get("/", [](Request &, Response &res)
+ { res.json({"framework", "Vix.cpp",
+ "message", "Hello from basic_get.cpp π"}); });
- // Start the HTTP server on port 8080
- app.run(8080);
- return 0;
+ // Start the HTTP server on port 8080
+ app.run(8080);
+ return 0;
}
diff --git a/examples/http/json_api.cpp b/examples/http/json_api.cpp
index f1aab59..3e810e3 100644
--- a/examples/http/json_api.cpp
+++ b/examples/http/json_api.cpp
@@ -1,100 +1,92 @@
-//
-// examples/http/json_api.cpp
-//
-// Simple JSON API example using Vix.cpp.
-//
-// Demonstrates:
-// - A small "users" API under /api/users
-// - GET /api/users β returns a JSON array
-// - POST /api/users β accepts a JSON body and echoes basic info
-//
-// Note:
-// This example uses nlohmann::json for parsing the request body.
-// Make sure nlohmann/json.hpp is available in your include path.
-//
+/**
+ *
+ * @file examples/http/json_api.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
-#include
using namespace vix;
int main()
{
- App app;
+ App app;
- // In-memory fake "database"
- std::vector users = {
- {{"id", 1}, {"name", "Alice"}, {"role", "admin"}},
- {{"id", 2}, {"name", "Bob"}, {"role", "user"}}};
+ // In-memory fake "database"
+ std::vector users = {
+ {{"id", 1}, {"name", "Alice"}, {"role", "admin"}},
+ {{"id", 2}, {"name", "Bob"}, {"role", "user"}}};
- // --------------------------------------------------------
- // GET /api/users
- //
- // Returns the full list of users as JSON.
- // --------------------------------------------------------
- app.get("/api/users", [&users](auto &, auto &res)
- {
- json payload = {
+ // GET /api/users
+ //
+ // Returns the full list of users as JSON.
+ app.get("/api/users", [&users](Request &, Response &res)
+ {
+ json::Json payload = {
{"count", users.size()},
{"items", users}
};
res.json(payload); });
- // --------------------------------------------------------
- // POST /api/users
- //
- // Expects a JSON body like:
- // { "name": "Charlie", "role": "user" }
- //
- // For simplicity, we:
- // - parse the body
- // - assign a new incremental id
- // - push it into the in-memory vector
- // - return the created user
- // --------------------------------------------------------
- app.post("/api/users", [&users](auto &req, auto &res)
- {
+ // POST /api/users
+ //
+ // Expects a JSON body like:
+ // { "name": "Charlie", "role": "user" }
+ //
+ // For simplicity, we:
+ // - parse the body
+ // - assign a new incremental id
+ // - push it into the in-memory vector
+ // - return the created user
+ app.post("/api/users", [&users](Request &req, Response &res)
+ {
try
{
// req is typically a boost::beast::http::request
const auto& body = req.body();
- auto data = json::parse(body);
+ json::Json data = json::Json::parse(body);
// Generate a very simple new id
int newId = users.empty()
? 1
: (users.back().value("id", 0) + 1);
- json user = {
+ json::Json user = json::Json({
{"id", newId},
{"name", data.value("name", "unknown")},
{"role", data.value("role", "user")}
- };
+ });
users.push_back(user);
- res.status(201).json({
+ res.status(201).send(vix::json::kv({
{"message", "User created"},
{"user", user}
- });
+ }));
}
catch (const std::exception& e)
{
- res.status(400).json({
+ res.status(400).send(vix::json::kv({
{"error", "Invalid JSON payload"},
{"details", e.what()}
- });
+ }));
} });
- // --------------------------------------------------------
- // Root route: hint for trying the API
- // --------------------------------------------------------
- app.get("/", [](auto &, auto &res)
- { res.json({"api", "/api/users",
- "hint1", "GET /api/users",
- "hint2", "POST /api/users with JSON body {\"name\":\"Charlie\",\"role\":\"user\"}"}); });
+ // Root route: hint for trying the API
+ app.get("/", [](Request &, Response &res)
+ { res.json({"api", "/api/users",
+ "hint1", "GET /api/users",
+ "hint2", "POST /api/users with JSON body {\"name\":\"Charlie\",\"role\":\"user\"}"}); });
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/http/json_builders_routes.cpp b/examples/http/json_builders_routes.cpp
index 891d7b6..e2e3961 100644
--- a/examples/http/json_builders_routes.cpp
+++ b/examples/http/json_builders_routes.cpp
@@ -1,5 +1,17 @@
+/**
+ *
+ * @file examples/http/json_builders_routes.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ============================================================================
-// json_builders_routes.cpp β Minimal routes using Vix::json builders (new API)
// GET /hello -> {"message":"Hello, World!"}
// GET /users/{id} -> {"user":{"id":"","active":true}}
// GET /roles -> {"roles":["admin","editor","viewer"]}
@@ -13,16 +25,16 @@ namespace J = vix::json;
int main()
{
- App app;
+ App app;
- // GET /hello -> {"message": "Hello, World!"}
- app.get("/hello", [](auto &, auto &res)
- { res.json({"message", "Hello, World!"}); });
+ // GET /hello -> {"message": "Hello, World!"}
+ app.get("/hello", [](Request &, Response &res)
+ { res.json({"message", "Hello, World!"}); });
- // GET /users/{id} -> {"user": {"id": "...", "active": true}}
- app.get("/users/{id}", [](auto &, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
+ // GET /users/{id} -> {"user": {"id": "...", "active": true}}
+ app.get("/users/{id}", [](Request &req, Response &res)
+ {
+ const std::string id = req.param("id");
res.json({
"user", J::obj({
"id", id,
@@ -30,10 +42,10 @@ int main()
})
}); });
- // GET /roles -> {"roles": ["admin", "editor", "viewer"]}
- app.get("/roles", [](auto &, auto &res)
- { res.json({"roles", J::array({"admin", "editor", "viewer"})}); });
+ // GET /roles -> {"roles": ["admin", "editor", "viewer"]}
+ app.get("/roles", [](Request &, Response &res)
+ { res.json({"roles", J::array({"admin", "editor", "viewer"})}); });
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/http/now_server.cpp b/examples/http/now_server.cpp
index 2cbe44c..5ef1278 100644
--- a/examples/http/now_server.cpp
+++ b/examples/http/now_server.cpp
@@ -1,5 +1,17 @@
+/**
+ *
+ * @file now_server.cpp β Demo route: current time in ISO 8601 and milliseconds
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
// ============================================================================
-// now_server.cpp β Demo route: current time in ISO 8601 and milliseconds
// GET /now -> {"iso8601":"2025-10-09T10:34:12.123Z","ms":1696848852123}
// ============================================================================
@@ -13,21 +25,21 @@ using namespace vix::utils;
int main()
{
- auto &log = Logger::getInstance();
- log.setPattern("[%H:%M:%S.%e] [%^%l%$] %v");
- log.setLevel(Logger::Level::INFO);
+ auto &log = Logger::getInstance();
+ log.setPattern("[%H:%M:%S.%e] [%^%l%$] %v");
+ log.setLevel(Logger::Level::INFO);
- const int port = utils::env_int("PORT", 8080);
+ const int port = utils::env_int("PORT", 8081);
- App app;
+ App app;
- // GET /now β returns current ISO 8601 timestamp and epoch ms
- app.get("/now", [](auto &, auto &res)
- { res.json({"iso8601", utils::iso8601_now(),
- "ms", static_cast(utils::now_ms())}); });
+ // GET /now β returns current ISO 8601 timestamp and epoch ms
+ app.get("/now", [](Request &, Response &res)
+ { res.json({"iso8601", utils::iso8601_now(),
+ "ms", static_cast(utils::now_ms())}); });
- log.log(Logger::Level::INFO, "Starting server on port {}", port);
+ log.log(Logger::Level::INFO, "Starting server on port {}", port);
- app.run(port);
- return 0;
+ app.run(port);
+ return 0;
}
diff --git a/examples/http/router_params.cpp b/examples/http/router_params.cpp
index 91065d0..0633c32 100644
--- a/examples/http/router_params.cpp
+++ b/examples/http/router_params.cpp
@@ -1,13 +1,16 @@
-//
-// examples/http/router_params.cpp
-//
-// Example demonstrating route parameters with Vix.cpp.
-//
-// Demonstrates:
-// - Path parameters: /hello/{name}
-// - Multiple parameters: /posts/{year}/{slug}
-// - Returning JSON with dynamic values
-//
+/**
+ *
+ * @file examples/http/router_params.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
@@ -15,44 +18,46 @@ using namespace vix;
int main()
{
- App app;
-
- // GET /hello/{name}
- //
- // Example:
- // GET /hello/Alice -> { "greeting": "Hello Alice π" }
- //
- app.get("/hello/{name}", [](auto &, auto &res, auto ¶ms)
- {
- const auto name = params["name"];
+ App app;
+
+ // GET /hello/{name}
+ //
+ // Example:
+ // GET /hello/Alice -> { "greeting": "Hello Alice π" }
+ //
+ app.get("/hello/{name}", [](Request &req, Response &res)
+ {
+ const auto name = req.param("name");
res.json({
"greeting", "Hello " + name + " π",
"powered_by", "Vix.cpp"
}); });
- // GET /posts/{year}/{slug}
- //
- // Example:
- // GET /posts/2025/hello-world
- //
- app.get("/posts/{year}/{slug}", [](auto &, auto &res, auto ¶ms)
- {
- const auto year = params["year"];
- const auto slug = params["slug"];
-
- res.json({
- "year", year,
- "slug", slug,
- "title", "Post: " + slug,
- "message", "This is an example route with multiple params.",
- "powered_by", "Vix.cpp"
- }); });
-
- // Optional: a root route for discoverability
- app.get("/", [](auto &, auto &res)
- { res.json({"routes", "/hello/{name}, /posts/{year}/{slug}",
- "hint", "Try GET /hello/Alice or /posts/2025/hello-world"}); });
-
- app.run(8080);
- return 0;
+ // GET /posts/{year}/{slug}
+ //
+ // Example:
+ // GET /posts/2025/hello-world
+ //
+ app.get("/posts", [](Request &req, Response &res)
+ {
+ const auto year = req.query_value("year");
+ const auto slug = req.query_value("slug");
+
+ res.json(json::kv({
+ {"year", year},
+ {"slug", slug},
+ {"title", "Post: " + slug},
+ {"message", "This is an example route with multiple params."},
+ {"powered_by", "Vix.cpp"},
+ {"params", req.params()},
+ {"query", req.query()}
+ })); });
+
+ // Optional: a root route for discoverability
+ app.get("/", [](Request &, Response &res)
+ { res.json({"routes", "/hello/{name}, /posts/{year}/{slug}",
+ "hint", "Try GET /hello/Alice or /posts/2025/hello-world"}); });
+
+ app.run(8080);
+ return 0;
}
diff --git a/examples/http/trace_route.cpp b/examples/http/trace_route.cpp
index 0dc5634..843898e 100644
--- a/examples/http/trace_route.cpp
+++ b/examples/http/trace_route.cpp
@@ -1,5 +1,18 @@
+/**
+ *
+ * @file examples/http/trace_route.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
+
// ============================================================================
-// trace_route.cpp β Demo: contextual logging + request tracing (new Vix.cpp API)
// GET /trace -> {"rid": "", "ok": true}
// ============================================================================
@@ -13,23 +26,23 @@ using namespace vix::utils;
int main()
{
- auto &log = Logger::getInstance();
- log.setPattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
- log.setLevel(Logger::Level::INFO);
- log.setAsync(true);
+ auto &log = Logger::getInstance();
+ log.setPattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
+ log.setLevel(Logger::Level::INFO);
+ log.setAsync(true);
- App app;
+ App app;
- // GET /trace
- app.get("/trace", [](auto &req, auto &res)
- {
+ // GET /trace
+ app.get("/trace", [](Request &req, Response &res)
+ {
Logger::Context ctx;
ctx.request_id = utils::uuid4();
ctx.module = "trace_handler";
Logger::getInstance().setContext(ctx);
std::string path(req.target().data(), req.target().size());
- std::string method(req.method_string().data(), req.method_string().size());
+ std::string method(req.method().data(), req.method().size());
Logger::getInstance().logf(
Logger::Level::INFO,
@@ -43,6 +56,5 @@ int main()
"ok", true
}); });
- app.run(8080);
- return 0;
+ app.run(8080);
}
diff --git a/examples/http_crud/CMakeLists.txt b/examples/http_crud/CMakeLists.txt
index a87e249..33e4a7e 100644
--- a/examples/http_crud/CMakeLists.txt
+++ b/examples/http_crud/CMakeLists.txt
@@ -10,7 +10,6 @@ set(_HTTP_CRUD_EXAMPLES
users_crud_internal.cpp
users_crud.cpp
repository_crud_full.cpp
- validation_user_create.cpp
)
foreach(EXAMPLE_SRC IN LISTS _HTTP_CRUD_EXAMPLES)
diff --git a/examples/http_crud/batch_insert_tx.cpp b/examples/http_crud/batch_insert_tx.cpp
new file mode 100644
index 0000000..7cdaeae
--- /dev/null
+++ b/examples/http_crud/batch_insert_tx.cpp
@@ -0,0 +1,79 @@
+/**
+ *
+ * @file examples/http_crud/batch_insert_tx.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+using namespace vix::orm;
+
+int main(int argc, char **argv)
+{
+ std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
+ std::string user = (argc > 2 ? argv[2] : "root");
+ std::string pass = (argc > 3 ? argv[3] : "");
+ std::string db = (argc > 4 ? argv[4] : "vixdb");
+
+ try
+ {
+ auto factory = make_mysql_factory(host, user, pass, db);
+
+ PoolConfig cfg;
+ cfg.min = 1;
+ cfg.max = 8;
+
+ ConnectionPool pool{factory, cfg};
+ pool.warmup();
+
+ Transaction tx(pool);
+ auto &c = tx.conn();
+
+ auto st = c.prepare("INSERT INTO users(name,email,age) VALUES(?,?,?)");
+
+ struct Row
+ {
+ const char *name;
+ const char *email;
+ int age;
+ };
+
+ std::vector rows = {
+ {"Zoe", "zoe@example.com", 23},
+ {"Mina", "mina@example.com", 31},
+ {"Omar", "omar@example.com", 35},
+ };
+
+ std::uint64_t total = 0;
+ for (const auto &r : rows)
+ {
+ st->bind(1, r.name);
+ st->bind(2, r.email);
+ st->bind(3, r.age);
+ total += st->exec();
+ }
+
+ tx.commit();
+ std::cout << "[OK] inserted rows = " << total << "\n";
+ return 0;
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "[ERR] " << e.what() << "\n";
+ return 1;
+ }
+}
diff --git a/examples/http_crud/delete_user.cpp b/examples/http_crud/delete_user.cpp
index 1d33cd4..b883966 100644
--- a/examples/http_crud/delete_user.cpp
+++ b/examples/http_crud/delete_user.cpp
@@ -1,7 +1,16 @@
-// ============================================================================
-// delete_user.cpp β DELETE example (new Vix.cpp API)
-// DELETE /users/{id} -> {"action":"delete","status":"deleted","user_id":""}
-// ============================================================================
+/**
+ *
+ * @file examples/http_crud/delete_user.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
#include
@@ -12,12 +21,12 @@ namespace J = vix::json;
int main()
{
- App app;
+ App app;
- // DELETE /users/{id}
- app.del("/users/{id}", [](auto &, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
+ // DELETE /users/{id}
+ app.del("/users/{id}", [](Request &req, Response &res)
+ {
+ const std::string id = req.param("id");
// In a real app you'd remove the resource from DB or memory here
res.json({
@@ -26,6 +35,6 @@ int main()
"user_id", id
}); });
- app.run(8080);
- return 0;
+ app.run(8080);
+ return 0;
}
diff --git a/examples/http_crud/error_handling.cpp b/examples/http_crud/error_handling.cpp
new file mode 100644
index 0000000..0b320d1
--- /dev/null
+++ b/examples/http_crud/error_handling.cpp
@@ -0,0 +1,39 @@
+/**
+ *
+ * @file examples/http_crud/error_handling.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
+#include
+#include
+
+using namespace vix::orm;
+
+int main(int argc, char **argv)
+{
+ (void)argc;
+ (void)argv;
+ try
+ {
+ // Intentionally wrong DB name to show error
+ auto raw = make_mysql_factory("tcp://127.0.0.1:3306", "root", "", "db_does_not_exist");
+ //.....
+ std::cout << "[INFO] This message may not be reached if connection fails.\n";
+ }
+ catch (const DBError &e)
+ {
+ std::cerr << "[DBError] " << e.what() << "\n";
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "[std::exception] " << e.what() << "\n";
+ }
+ return 0;
+}
diff --git a/examples/http_crud/migrations/2025_10_10_000001_create_users.down.sql b/examples/http_crud/migrations/2025_10_10_000001_create_users.down.sql
new file mode 100644
index 0000000..662db4d
--- /dev/null
+++ b/examples/http_crud/migrations/2025_10_10_000001_create_users.down.sql
@@ -0,0 +1,2 @@
+-- Drop users table
+DROP TABLE IF EXISTS users;
diff --git a/examples/http_crud/migrations/2025_10_10_000001_create_users.up.sql b/examples/http_crud/migrations/2025_10_10_000001_create_users.up.sql
new file mode 100644
index 0000000..4659050
--- /dev/null
+++ b/examples/http_crud/migrations/2025_10_10_000001_create_users.up.sql
@@ -0,0 +1,10 @@
+-- Create users table
+CREATE TABLE IF NOT EXISTS users (
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ name VARCHAR(120) NOT NULL,
+ email VARCHAR(190) NOT NULL,
+ age INT NOT NULL,
+
+ PRIMARY KEY (id),
+ UNIQUE KEY uq_users_email (email)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
diff --git a/examples/http_crud/migrations/2025_10_10_000002_create_orders.down.sql b/examples/http_crud/migrations/2025_10_10_000002_create_orders.down.sql
new file mode 100644
index 0000000..1e94744
--- /dev/null
+++ b/examples/http_crud/migrations/2025_10_10_000002_create_orders.down.sql
@@ -0,0 +1,2 @@
+-- Drop orders table
+DROP TABLE IF EXISTS orders;
diff --git a/examples/http_crud/migrations/2025_10_10_000002_create_orders.up.sql b/examples/http_crud/migrations/2025_10_10_000002_create_orders.up.sql
new file mode 100644
index 0000000..0d465bb
--- /dev/null
+++ b/examples/http_crud/migrations/2025_10_10_000002_create_orders.up.sql
@@ -0,0 +1,14 @@
+-- Create orders table
+CREATE TABLE IF NOT EXISTS orders (
+ id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
+ user_id BIGINT UNSIGNED NOT NULL,
+ total DECIMAL(12,2) NOT NULL,
+
+ PRIMARY KEY (id),
+ INDEX ix_orders_user_id (user_id),
+
+ CONSTRAINT fk_orders_user
+ FOREIGN KEY (user_id)
+ REFERENCES users(id)
+ ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
diff --git a/examples/http_crud/post_create_user.cpp b/examples/http_crud/post_create_user.cpp
index 4f3044f..61d1451 100644
--- a/examples/http_crud/post_create_user.cpp
+++ b/examples/http_crud/post_create_user.cpp
@@ -1,7 +1,16 @@
-// ============================================================================
-// post_create_user.cpp β POST example (new Vix.cpp API)
-// POST /users -> {"action":"create","status":"created","user":{...}}
-// ============================================================================
+/**
+ *
+ * @file examples/http_crud/post_create_user.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
#include
@@ -12,14 +21,13 @@ namespace J = vix::json;
int main()
{
- App app;
+ App app;
- // POST /users
- app.post("/users", [](auto &req, auto &res)
- {
+ // POST /users
+ app.post("/users", [](Request &req, Response &res)
+ {
try {
- // Parse body as nlohmann::json for simplicity (still supported)
- auto body = nlohmann::json::parse(req.body());
+ auto body = json::Json::parse(req.body());
const std::string name = body.value("name", "");
const std::string email = body.value("email", "");
@@ -41,6 +49,5 @@ int main()
});
} });
- app.run(8080);
- return 0;
+ app.run(8080);
}
diff --git a/examples/http_crud/put_update_user.cpp b/examples/http_crud/put_update_user.cpp
index 02c1502..bb8255e 100644
--- a/examples/http_crud/put_update_user.cpp
+++ b/examples/http_crud/put_update_user.cpp
@@ -1,7 +1,16 @@
-// ============================================================================
-// put_update_user.cpp β PUT example (new Vix.cpp API)
-// PUT /users/{id} -> {"action":"update","status":"updated","user":{...}}
-// ============================================================================
+/**
+ *
+ * @file examples/http_crud/put_update_user.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
#include
@@ -12,16 +21,16 @@ namespace J = vix::json;
int main()
{
- App app;
+ App app;
- // PUT /users/{id}
- app.put("/users/{id}", [](auto &req, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
+ // PUT /users/{id}
+ app.put("/users/{id}", [](Request &req, Response &res)
+ {
+ const std::string id = req.param("id");
try {
// Parsing with nlohmann::json for input is fine (Vix supports it internally)
- auto body = nlohmann::json::parse(req.body());
+ auto body = json::Json::parse(req.body());
const std::string name = body.value("name", "");
const std::string email = body.value("email", "");
@@ -44,6 +53,5 @@ int main()
});
} });
- app.run(8080);
- return 0;
+ app.run(8080);
}
diff --git a/examples/http_crud/querybuilder_update.cpp b/examples/http_crud/querybuilder_update.cpp
new file mode 100644
index 0000000..604ee61
--- /dev/null
+++ b/examples/http_crud/querybuilder_update.cpp
@@ -0,0 +1,62 @@
+/**
+ *
+ * @file examples/http_crud/querybuilder_update.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
+#include
+#include
+#include
+
+#include
+#include
+
+using namespace vix::orm;
+
+int main(int argc, char **argv)
+{
+ std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
+ std::string user = (argc > 2 ? argv[2] : "root");
+ std::string pass = (argc > 3 ? argv[3] : "");
+ std::string db = (argc > 4 ? argv[4] : "vixdb");
+
+ try
+ {
+ auto factory = make_mysql_factory(host, user, pass, db);
+
+ PoolConfig cfg;
+ cfg.min = 1;
+ cfg.max = 8;
+
+ ConnectionPool pool{factory, cfg};
+ pool.warmup();
+
+ QueryBuilder qb;
+ qb.raw("UPDATE users SET age=? WHERE email=?")
+ .param(29)
+ .param(std::string("gaspardkirira@example.com"));
+
+ PooledConn pc(pool);
+ auto st = pc.get().prepare(qb.sql());
+
+ const auto &ps = qb.params();
+ for (std::size_t i = 0; i < ps.size(); ++i)
+ st->bind(i + 1, ps[i]);
+
+ auto affected = st->exec();
+ std::cout << "[OK] affected rows = " << affected << "\n";
+ return 0;
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "[ERR] " << e.what() << "\n";
+ return 1;
+ }
+}
diff --git a/examples/http_crud/repository_crud_full.cpp b/examples/http_crud/repository_crud_full.cpp
index b7a75a7..8db701c 100644
--- a/examples/http_crud/repository_crud_full.cpp
+++ b/examples/http_crud/repository_crud_full.cpp
@@ -1,68 +1,101 @@
/**
- * @file repository_crud_full.cpp
- * @brief Example β Full CRUD except SELECT (pending ResultSet).
+ *
+ * @file examples/http_crud/repository_crud_full.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
*/
-
#include
+#include
+#include
+
#include
#include
+#include
struct User
{
- std::int64_t id{};
- std::string name;
- std::string email;
- int age{};
+ std::int64_t id{};
+ std::string name;
+ std::string email;
+ int age{};
};
namespace vix::orm
{
- template <>
- struct Mapper
+ template <>
+ struct Mapper
+ {
+ static User fromRow(const ResultRow &) { return {}; } // pending
+
+ static std::vector>
+ toInsertParams(const User &u)
{
- static User fromRow(const ResultRow &) { return {}; } // pending
- static std::vector> toInsertParams(const User &u)
- {
- return {{"name", u.name}, {"email", u.email}, {"age", u.age}};
- }
- static std::vector> toUpdateParams(const User &u)
- {
- return {{"name", u.name}, {"email", u.email}, {"age", u.age}};
- }
- };
-} // namespace Vix::orm
+ return {
+ {"name", u.name},
+ {"email", u.email},
+ {"age", u.age},
+ };
+ }
+
+ static std::vector>
+ toUpdateParams(const User &u)
+ {
+ return {
+ {"name", u.name},
+ {"email", u.email},
+ {"age", u.age},
+ };
+ }
+ };
+} // namespace vix::orm
int main(int argc, char **argv)
{
- using namespace Vix::orm;
+ using namespace vix::orm;
- std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
- std::string user = (argc > 2 ? argv[2] : "root");
- std::string pass = (argc > 3 ? argv[3] : "");
- std::string db = (argc > 4 ? argv[4] : "vixdb");
+ std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
+ std::string user = (argc > 2 ? argv[2] : "root");
+ std::string pass = (argc > 3 ? argv[3] : "");
+ std::string db = (argc > 4 ? argv[4] : "vixdb");
- try
- {
- ConnectionPool pool{host, user, pass, db};
- BaseRepository repo{pool, "users"};
+ try
+ {
+ auto factory = make_mysql_factory(host, user, pass, db);
- // Create
- std::int64_t id = static_cast(repo.create(User{0, "Bob", "gaspardkirira@example.com", 30}));
- std::cout << "[OK] create β id=" << id << "\n";
+ PoolConfig cfg;
+ cfg.min = 1;
+ cfg.max = 8;
- // Update
- repo.updateById(id, User{id, "Adastra", "adastra@example.com", 31});
- std::cout << "[OK] update β id=" << id << "\n";
+ ConnectionPool pool{factory, cfg};
+ pool.warmup();
- // Delete
- repo.removeById(id);
- std::cout << "[OK] delete β id=" << id << "\n";
+ BaseRepository repo{pool, "users"};
- return 0;
- }
- catch (const std::exception &e)
- {
- std::cerr << "[ERR] " << e.what() << "\n";
- return 1;
- }
+ // Create
+ std::int64_t id = static_cast(
+ repo.create(User{0, "Bob", "gaspardkirira@example.com", 30}));
+ std::cout << "[OK] create β id=" << id << "\n";
+
+ // Update
+ repo.updateById(id, User{id, "Adastra", "adastra@example.com", 31});
+ std::cout << "[OK] update β id=" << id << "\n";
+
+ // Delete
+ repo.removeById(id);
+ std::cout << "[OK] delete β id=" << id << "\n";
+
+ return 0;
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "[ERR] " << e.what() << "\n";
+ return 1;
+ }
}
diff --git a/examples/http_crud/tx_unit_of_work.cpp b/examples/http_crud/tx_unit_of_work.cpp
new file mode 100644
index 0000000..9196bcb
--- /dev/null
+++ b/examples/http_crud/tx_unit_of_work.cpp
@@ -0,0 +1,71 @@
+/**
+ *
+ * @file examples/http_crud/tx_unit_of_work.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+
+using namespace vix::orm;
+
+int main(int argc, char **argv)
+{
+ std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
+ std::string user = (argc > 2 ? argv[2] : "root");
+ std::string pass = (argc > 3 ? argv[3] : "");
+ std::string db = (argc > 4 ? argv[4] : "vixdb");
+
+ try
+ {
+ auto factory = make_mysql_factory(host, user, pass, db);
+
+ PoolConfig cfg;
+ cfg.min = 1;
+ cfg.max = 8;
+
+ ConnectionPool pool{factory, cfg};
+ pool.warmup();
+
+ UnitOfWork uow{pool};
+ auto &c = uow.conn();
+
+ {
+ auto st = c.prepare("INSERT INTO users(name,email,age) VALUES(?,?,?)");
+ st->bind(1, std::string("Alice"));
+ st->bind(2, std::string("alice@example.com"));
+ st->bind(3, 27);
+ st->exec();
+ }
+
+ const auto userId = c.lastInsertId();
+
+ {
+ auto st = c.prepare("INSERT INTO orders(user_id,total) VALUES(?,?)");
+ st->bind(1, static_cast(userId));
+ st->bind(2, 199.99);
+ st->exec();
+ }
+
+ uow.commit();
+ std::cout << "[OK] user+order committed. user_id=" << userId << "\n";
+ return 0;
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "[ERR] " << e.what() << "\n";
+ return 1;
+ }
+}
diff --git a/examples/http_crud/user_crud_with_validation.cpp b/examples/http_crud/user_crud_with_validation.cpp
index dc721af..359b388 100644
--- a/examples/http_crud/user_crud_with_validation.cpp
+++ b/examples/http_crud/user_crud_with_validation.cpp
@@ -1,12 +1,16 @@
-// ============================================================================
-// user_crud_with_validation.cpp β Full CRUD + Validation (Vix.cpp, nouvelle API)
-// ----------------------------------------------------------------------------
-// Routes:
-// POST /users β Create user (with validation)
-// GET /users/{id} β Read user
-// PUT /users/{id} β Update user
-// DELETE /users/{id} β Delete user
-// ============================================================================
+/**
+ *
+ * @file examples/http_crud/user_crud_with_validation.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include // App, http, ResponseWrapper, etc.
#include // Vix::json::token, obj(), array()
@@ -28,10 +32,10 @@ using namespace vix::utils;
// --------------------------- Data Model -------------------------------------
struct User
{
- std::string id;
- std::string name;
- std::string email;
- int age{};
+ std::string id;
+ std::string name;
+ std::string email;
+ int age{};
};
static std::mutex g_mtx;
@@ -40,75 +44,75 @@ static std::unordered_map g_users;
// --------------------------- Helpers ----------------------------------------
static J::kvs user_to_kvs(const User &u)
{
- return J::obj({"id", u.id,
- "name", u.name,
- "email", u.email,
- "age", static_cast(u.age)});
+ return J::obj({"id", u.id,
+ "name", u.name,
+ "email", u.email,
+ "age", static_cast(u.age)});
}
static std::string to_string_safe(const njson &j)
{
- if (j.is_string())
- return j.get();
- if (j.is_number_integer())
- return std::to_string(j.get());
- if (j.is_number_unsigned())
- return std::to_string(j.get());
- if (j.is_number_float())
- return std::to_string(j.get());
- if (j.is_boolean())
- return j.get() ? "true" : "false";
- return {};
+ if (j.is_string())
+ return j.get();
+ if (j.is_number_integer())
+ return std::to_string(j.get());
+ if (j.is_number_unsigned())
+ return std::to_string(j.get());
+ if (j.is_number_float())
+ return std::to_string(j.get());
+ if (j.is_boolean())
+ return j.get() ? "true" : "false";
+ return {};
}
static bool parse_user(const njson &j, User &out)
{
- try
- {
- out.name = j.value("name", std::string{});
- out.email = j.value("email", std::string{});
+ try
+ {
+ out.name = j.value("name", std::string{});
+ out.email = j.value("email", std::string{});
- if (j.contains("age"))
- {
- if (j["age"].is_string())
- out.age = std::stoi(j["age"].get());
- else if (j["age"].is_number_integer())
- out.age = static_cast(j["age"].get());
- else if (j["age"].is_number_unsigned())
- out.age = static_cast(j["age"].get());
- else if (j["age"].is_number_float())
- out.age = static_cast(j["age"].get());
- else
- out.age = 0;
- }
- else
- {
- out.age = 0;
- }
- return true;
+ if (j.contains("age"))
+ {
+ if (j["age"].is_string())
+ out.age = std::stoi(j["age"].get());
+ else if (j["age"].is_number_integer())
+ out.age = static_cast(j["age"].get());
+ else if (j["age"].is_number_unsigned())
+ out.age = static_cast(j["age"].get());
+ else if (j["age"].is_number_float())
+ out.age = static_cast(j["age"].get());
+ else
+ out.age = 0;
}
- catch (...)
+ else
{
- return false;
+ out.age = 0;
}
+ return true;
+ }
+ catch (...)
+ {
+ return false;
+ }
}
static std::string gen_id_from_email(const std::string &email)
{
- const auto h = std::hash{}(email) & 0xFFFFFFull;
- std::ostringstream oss;
- oss << h;
- return oss.str();
+ const auto h = std::hash{}(email) & 0xFFFFFFull;
+ std::ostringstream oss;
+ oss << h;
+ return oss.str();
}
// --------------------------- Main -------------------------------------------
int main()
{
- App app;
+ App app;
- // CREATE (POST /users)
- app.post("/users", [](auto &req, auto &res)
- {
+ // CREATE (POST /users)
+ app.post("/users", [](Request &req, Response &res)
+ {
njson body;
try {
body = njson::parse(req.body());
@@ -168,10 +172,10 @@ int main()
"user", user_to_kvs(u)
}); });
- // READ (GET /users/{id})
- app.get("/users/{id}", [](auto & /*req*/, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
+ // READ (GET /users/{id})
+ app.get("/users/{id}", [](Request &req, Response &res)
+ {
+ const std::string id = req.param("id");
std::lock_guard lock(g_mtx);
auto it = g_users.find(id);
if (it == g_users.end()) {
@@ -184,10 +188,10 @@ int main()
"user", user_to_kvs(it->second)
}); });
- // UPDATE (PUT /users/{id})
- app.put("/users/{id}", [](auto &req, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
+ // UPDATE (PUT /users/{id})
+ app.put("/users/{id}", [](Request &req, Response &res)
+ {
+ const std::string id = req.param("id");
njson body;
try {
@@ -222,10 +226,10 @@ int main()
"user", user_to_kvs(it->second)
}); });
- // DELETE (DELETE /users/{id})
- app.del("/users/{id}", [](auto & /*req*/, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
+ // DELETE (DELETE /users/{id})
+ app.del("/users/{id}", [](Request &req, Response &res)
+ {
+ const std::string id = req.param("id");
std::lock_guard lock(g_mtx);
const auto n = g_users.erase(id);
if (!n) {
@@ -239,7 +243,6 @@ int main()
"user_id", id
}); });
- // Lancement
- app.run(8080);
- return 0;
+ // Lancement
+ app.run(8080);
}
diff --git a/examples/http_crud/users_crud.cpp b/examples/http_crud/users_crud.cpp
index bfeb194..964b560 100644
--- a/examples/http_crud/users_crud.cpp
+++ b/examples/http_crud/users_crud.cpp
@@ -1,152 +1,75 @@
/**
- * @file users_crud.cpp
- * @brief Example β Basic CRUD operations with Vix ORM.
*
- * This example demonstrates how to use the Vix ORM core classes
- * (`ConnectionPool`, `BaseRepository`, and `Mapper`) to perform
- * a simple `INSERT` on a `users` table.
+ * @file examples/http_crud/users_crud.cpp
+ * @author Gaspard Kirira
*
- * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- * Requirements
- * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- * - MySQL server accessible on localhost or custom TCP host.
- * - A table `users` with columns:
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
*
- * ```sql
- * CREATE TABLE users (
- * id BIGINT AUTO_INCREMENT PRIMARY KEY,
- * name VARCHAR(255) NOT NULL,
- * email VARCHAR(255) NOT NULL,
- * age INT NOT NULL
- * );
- * ```
+ * Vix.cpp
*
- * - Compiled with:
- * ```bash
- * cmake -S .. -B build -DVIX_ORM_BUILD_EXAMPLES=ON -DVIX_ORM_USE_MYSQL=ON
- * cmake --build build -j
- * ./build/vix_orm_users tcp://127.0.0.1:3306 root password vixdb
- * ```
- *
- * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- * Example flow
- * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- * 1. Define a C++ struct `User` representing the table.
- * 2. Provide a `Mapper` specialization describing how to
- * convert a `User` to SQL insert/update parameters.
- * 3. Use a `ConnectionPool` to manage MySQL connections.
- * 4. Create a `BaseRepository` and call `create()`.
- *
- * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- * Output example
- * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- * ```
- * [OK] Insert user β id=42
- * ```
*/
-
#include
+#include
+#include
#include
-#include
+#include
-// ============================================================================
-// Entity definition
-// ----------------------------------------------------------------------------
-// Represents a single row in the `users` table.
-// ============================================================================
-struct User
-{
- std::int64_t id{};
- std::string name;
- std::string email;
- int age{};
-};
+using namespace vix::orm;
-// ============================================================================
-// Mapper specialization for User
-// ----------------------------------------------------------------------------
-// Defines how to convert between `User` objects and SQL parameters.
-// Note: reading (fromRow) is omitted here since ResultSet adapter is pending.
-// ============================================================================
-namespace vix::orm
+int main(int argc, char **argv)
{
- template <>
- struct Mapper
- {
- static User fromRow(const ResultRow &)
- {
- // Not implemented yet (ResultSet adapter pending)
- return {};
- }
+ std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
+ std::string user = (argc > 2 ? argv[2] : "root");
+ std::string pass = (argc > 3 ? argv[3] : "");
+ std::string db = (argc > 4 ? argv[4] : "vixdb");
- static std::vector> toInsertParams(const User &u)
- {
- return {
- {"name", u.name},
- {"email", u.email},
- {"age", u.age}};
- }
-
- static std::vector> toUpdateParams(const User &u)
- {
- return {
- {"name", u.name},
- {"email", u.email},
- {"age", u.age}};
- }
- };
-} // namespace Vix::orm
+ try
+ {
+ auto factory = make_mysql_factory(host, user, pass, db);
-// ============================================================================
-// Entry point
-// ----------------------------------------------------------------------------
-// Demonstrates connecting, creating a repository, and inserting a record.
-// ============================================================================
-int main(int argc, char **argv)
-{
- using namespace Vix::orm;
+ PoolConfig cfg;
+ cfg.min = 1;
+ cfg.max = 8;
- // ------------------------------------------------------------------------
- // 1. Retrieve DB credentials (defaults or CLI arguments)
- // ------------------------------------------------------------------------
- std::string host = (argc > 1 ? argv[1] : "tcp://127.0.0.1:3306");
- std::string user = (argc > 2 ? argv[2] : "root");
- std::string pass = (argc > 3 ? argv[3] : "");
- std::string db = (argc > 4 ? argv[4] : "vixdb");
+ ConnectionPool pool{factory, cfg};
+ pool.warmup();
- try
- {
- // --------------------------------------------------------------------
- // 2. Initialize a connection pool
- // --------------------------------------------------------------------
- ConnectionPool pool{host, user, pass, db};
+ Transaction tx(pool);
+ auto &c = tx.conn();
- // --------------------------------------------------------------------
- // 3. Create repository for `users`
- // --------------------------------------------------------------------
- BaseRepository users{pool, "users"};
+ auto st = c.prepare("INSERT INTO users(name,email,age) VALUES(?,?,?)");
- // --------------------------------------------------------------------
- // 4. Insert a user (CREATE)
- // --------------------------------------------------------------------
- std::uint64_t id = users.create(User{
- 0,
- "Gaspard",
- "gaspardkirira@outlook.com",
- 28});
+ struct Row
+ {
+ const char *name;
+ const char *email;
+ int age;
+ };
+ std::vector rows = {
+ {"Zoe", "zoe@example.com", 23},
+ {"Mina", "mina@example.com", 31},
+ {"Omar", "omar@example.com", 35},
+ };
- // --------------------------------------------------------------------
- // 5. Display success result
- // --------------------------------------------------------------------
- std::cout << "[OK] Insert user β id=" << id << "\n";
- return 0;
- }
- catch (const std::exception &e)
+ std::uint64_t total = 0;
+ for (const auto &r : rows)
{
- // --------------------------------------------------------------------
- // 6. Error handling (DB connection or execution failure)
- // --------------------------------------------------------------------
- std::cerr << "[ERR] " << e.what() << "\n";
- return 1;
+ st->bind(1, r.name);
+ st->bind(2, r.email);
+ st->bind(3, r.age);
+ total += st->exec();
}
+
+ tx.commit();
+ std::cout << "[OK] inserted rows = " << total << "\n";
+ return 0;
+ }
+ catch (const std::exception &e)
+ {
+ std::cerr << "[ERR] " << e.what() << "\n";
+ return 1;
+ }
}
diff --git a/examples/http_crud/users_crud_internal.cpp b/examples/http_crud/users_crud_internal.cpp
index 750a183..20a3cb8 100644
--- a/examples/http_crud/users_crud_internal.cpp
+++ b/examples/http_crud/users_crud_internal.cpp
@@ -1,133 +1,21 @@
/**
- * @file users_crud_internal.cpp
- * @brief Contributor documentation β internals & pedagogy for users_crud example.
*
- * This file intentionally defines **no linker-visible symbols**. It documents
- * the rationale and teaching goals behind `examples/users_crud.cpp`, and serves
- * as a guide for contributors who evolve the example or the underlying ORM.
+ * @file examples/http_crud/user_crud_internal.cpp
+ * @author Gaspard Kirira
*
- * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- * Contents
- * βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- * 1) Teaching goals of the example
- * 2) Minimal domain model & Mapper
- * 3) Repository wiring & SQL safety
- * 4) Connection management (pool) & transactional hints
- * 5) Error handling policy
- * 6) Environment & schema pre-conditions
- * 7) Extending the example (roadmap)
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
*
- * ----------------------------------------------------------------------------
- * 1) Teaching goals of the example
- * ----------------------------------------------------------------------------
- * The example is deliberately small and focused:
- * - Show how to define an entity struct (`User`).
- * - Show how to specialize `Mapper` with `toInsertParams` and `toUpdateParams`.
- * - Demonstrate how to acquire a connection via `ConnectionPool`.
- * - Demonstrate a simple `INSERT` with `BaseRepository::create`.
+ * Vix.cpp
*
- * It does NOT include:
- * - Reading back rows (ResultSet adapter is introduced later).
- * - Dynamic WHERE clauses, pagination, or joins (covered in advanced samples).
- *
- * ----------------------------------------------------------------------------
- * 2) Minimal domain model & Mapper
- * ----------------------------------------------------------------------------
- * The domain struct is a plain struct with public fields; no macros or intrusive
- * base classes are required (optional `Entity` marker exists for clarity).
- *
- * `Mapper` responsibilities in the example:
- * - `toInsertParams(const User&)`: list of (column, value) for INSERT.
- * - `toUpdateParams(const User&)`: similar list for UPDATE.
- * - `fromRow(const ResultRow&)`: intentionally left unimplemented here to keep
- * the early example focused; implemented in later ResultSet-centric examples.
- *
- * Invariants:
- * - `toInsertParams` must exclude auto-increment `id`.
- * - Column names must match the DB schema exactly (no escaping done by repo).
- * - Values must be driver-supported `std::any` payloads (int, int64_t, unsigned,
- * double, float, bool, const char*, std::string).
- *
- * ----------------------------------------------------------------------------
- * 3) Repository wiring & SQL safety
- * ----------------------------------------------------------------------------
- * `BaseRepository` constructs parameterized SQL:
- * INSERT INTO (col1,col2,...) VALUES (?, ?, ...)
- * It binds parameters in the order returned by `Mapper::toInsertParams`.
- *
- * Security model:
- * - All *values* are passed through `?` placeholders (safe binding).
- * - Table and column identifiers are assumed trusted (application-owned).
- *
- * ----------------------------------------------------------------------------
- * 4) Connection management (pool) & transactional hints
- * ----------------------------------------------------------------------------
- * The example uses `ConnectionPool` β `PooledConn` automatically via the repo.
- * For multi-step atomic flows, contributors should encourage explicit
- * transactional scopes:
- *
- * @code
- * Transaction tx(pool);
- * auto& c = tx.conn();
- * auto st = c.prepare("INSERT ...");
- * // ...
- * tx.commit();
- * @endcode
- *
- * or use `UnitOfWork` for grouping multiple repo calls:
- *
- * @code
- * UnitOfWork uow(pool);
- * // repoA(uow.conn()).create(...);
- * // repoB(uow.conn()).update(...);
- * uow.commit();
- * @endcode
- *
- * ----------------------------------------------------------------------------
- * 5) Error handling policy
- * ----------------------------------------------------------------------------
- * - Driver failures propagate as `DBError` (see Errors.hpp).
- * - The example catches `std::exception` at `main` and prints a concise error.
- * - Contributors should avoid exposing secrets in error messages (no DSNs).
- *
- * ----------------------------------------------------------------------------
- * 6) Environment & schema pre-conditions
- * ----------------------------------------------------------------------------
- * The example assumes:
- * - A running MySQL instance (default host: `tcp://127.0.0.1:3306`).
- * - Credentials passed via CLI or using defaults (root / empty password).
- * - A database `vixdb` (or provided via argv) and a `users` table:
- *
- * CREATE TABLE users (
- * id BIGINT AUTO_INCREMENT PRIMARY KEY,
- * name VARCHAR(255) NOT NULL,
- * email VARCHAR(255) NOT NULL,
- * age INT NOT NULL
- * ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
- *
- * Build & run:
- * cmake -S .. -B build -DVIX_ORM_BUILD_EXAMPLES=ON -DVIX_ORM_USE_MYSQL=ON
- * cmake --build build -j
- * ./build/vix_orm_users tcp://127.0.0.1:3306 root "" vixdb
- *
- * ----------------------------------------------------------------------------
- * 7) Extending the example (roadmap)
- * ----------------------------------------------------------------------------
- * Short term:
- * - Implement `MySQLResultSet`/`MySQLResultRow` and switch the example to:
- * auto u = repo.findById(id);
- * std::cout << u->name << "\n";
- * - Add an UPDATE and DELETE example.
- *
- * Medium term:
- * - Introduce `QueryBuilder` usage for WHERE clauses and pagination:
- * qb.raw("SELECT id,name FROM users WHERE age >= ?").param(18);
- * - Show `UnitOfWork` coordinating multiple repository actions.
- *
- * Long term:
- * - Demonstrate batch inserts (multi-values) and upserts (ON DUPLICATE KEY).
- * - Add a migration-driven setup in examples (MigrationsRunner + migrations).
- * - Provide optional logging via spdlog (timings, affected rows).
*/
-// No includes or code needed; this TU is documentation-only.
+#include
+
+int main()
+{
+ std::cout << "[OK] users_crud_internal placeholder\n";
+ return 0;
+}
diff --git a/examples/http_crud/validation_user_create.cpp b/examples/http_crud/validation_user_create.cpp
deleted file mode 100644
index 0b5a551..0000000
--- a/examples/http_crud/validation_user_create.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-// ============================================================================
-// users_crud_validated.cpp β CRUD + validation (new Vix.cpp API)
-// ============================================================================
-
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-using namespace vix;
-namespace J = vix::json;
-using njson = nlohmann::json;
-using namespace vix::utils;
-
-// --------------------------- Data Model -------------------------------------
-struct User
-{
- std::string id;
- std::string name;
- std::string email;
- int age{};
-};
-
-static std::mutex g_mtx;
-static std::unordered_map g_users;
-
-// --------------------------- JSON helpers (Simple API) ----------------------
-static J::kvs to_json(const User &u)
-{
- return J::obj({"id", u.id,
- "name", u.name,
- "email", u.email,
- "age", static_cast(u.age)});
-}
-
-static std::string j_to_string(const njson &j, const char *k)
-{
- if (!j.contains(k))
- return {};
- const auto &v = j.at(k);
- if (v.is_string())
- return v.get();
- if (v.is_number_integer())
- return std::to_string(v.get());
- if (v.is_number_unsigned())
- return std::to_string(v.get());
- if (v.is_number_float())
- return std::to_string(v.get());
- if (v.is_boolean())
- return v.get() ? "true" : "false";
- return v.dump(); // objet/array -> JSON string
-}
-
-static bool parse_user(const njson &j, User &out)
-{
- try
- {
- out.name = j.value("name", std::string{});
- out.email = j.value("email", std::string{});
-
- if (j.contains("age"))
- {
- if (j["age"].is_string())
- out.age = std::stoi(j["age"].get());
- else if (j["age"].is_number_integer())
- out.age = static_cast(j["age"].get());
- else if (j["age"].is_number_unsigned())
- out.age = static_cast(j["age"].get());
- else if (j["age"].is_number_float())
- out.age = static_cast(j["age"].get());
- else
- out.age = 0;
- }
- else
- {
- out.age = 0;
- }
- return true;
- }
- catch (...)
- {
- return false;
- }
-}
-
-// --------------------------- App -------------------------------------------
-int main()
-{
- App app;
-
- // CREATE
- app.post("/users", [](auto &req, auto &res)
- {
- njson body;
- try {
- body = njson::parse(req.body());
- } catch (...) {
- res.status(http::status::bad_request).json({ "error", "Invalid JSON" });
- return;
- }
-
- std::unordered_map data{
- {"name", j_to_string(body, "name")},
- {"email", j_to_string(body, "email")},
- {"age", j_to_string(body, "age")}
- };
-
- Schema sch{
- {"name", required("name")},
- {"age", num_range(1, 150, "Age")},
- {"email", match(R"(^[^@\s]+@[^@\s]+\.[^@\s]+$)", "Invalid email")}
- };
-
- auto r = validate_map(data, sch);
- if (r.is_err()) {
- // Construire {"errors": {field: message, ...}} sans nlohmann
- std::vector flat;
- flat.reserve(r.error().size() * 2);
- for (const auto& kv : r.error()) {
- flat.emplace_back(kv.first); // clΓ©
- flat.emplace_back(kv.second); // valeur
- }
-
- // J::obj(std::move(flat)) crΓ©e un objet JSON Γ partir de la liste plate
- res.status(400).json({
- "errors", J::obj(std::move(flat))
- });
- return;
- }
-
- User u;
- if (!parse_user(body, u)) {
- res.status(400).json({ "error", "Invalid fields" });
- return;
- }
-
- // Simple ID from email hash
- u.id = std::to_string(std::hash{}(u.email) & 0xFFFFFF);
-
- {
- std::lock_guard lock(g_mtx);
- g_users[u.id] = u;
- }
-
- res.status(http::status::created).json({
- "status", "created",
- "user", to_json(u)
- }); });
-
- // READ
- app.get("/users/{id}", [](auto &, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
- std::lock_guard lock(g_mtx);
- auto it = g_users.find(id);
- if (it == g_users.end()) {
- res.status(http::status::not_found).json({ "error", "Not found" });
- return;
- }
- res.json({ "user", to_json(it->second) }); });
-
- // UPDATE
- app.put("/users/{id}", [](auto &req, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
-
- njson body;
- try {
- body = njson::parse(req.body());
- } catch (...) {
- res.status(http::status::bad_request).json({ "error", "Invalid JSON" });
- return;
- }
-
- std::lock_guard lock(g_mtx);
- auto it = g_users.find(id);
- if (it == g_users.end()) {
- res.status(http::status::not_found).json({ "error", "Not found" });
- return;
- }
-
- if (body.contains("name")) it->second.name = body["name"].get();
- if (body.contains("email")) it->second.email = body["email"].get();
- if (body.contains("age")) {
- if (body["age"].is_string()) it->second.age = std::stoi(body["age"].get());
- else if (body["age"].is_number_integer()) it->second.age = static_cast(body["age"].get());
- else if (body["age"].is_number_unsigned()) it->second.age = static_cast(body["age"].get());
- else if (body["age"].is_number_float()) it->second.age = static_cast(body["age"].get());
- }
-
- res.json({ "status", "updated", "user", to_json(it->second) }); });
-
- // DELETE
- app.del("/users/{id}", [](auto &, auto &res, auto ¶ms)
- {
- const std::string id = params["id"];
- std::lock_guard lock(g_mtx);
- const auto n = g_users.erase(id);
- if (!n) {
- res.status(http::status::not_found).json({ "error", "Not found" });
- return;
- }
- res.json({ "status", "deleted", "user_id", id }); });
-
- app.run(8080);
- return 0;
-}
diff --git a/examples/http_ws/main_basic.cpp b/examples/http_ws/main_basic.cpp
index 438318d..109cef3 100644
--- a/examples/http_ws/main_basic.cpp
+++ b/examples/http_ws/main_basic.cpp
@@ -1,21 +1,16 @@
-//
-// examples/http_ws/main_basic.cpp
-//
-// Basic example demonstrating how to run HTTP + WebSocket
-// together using Vix.cpp's high-level helpers.
-//
-// This example uses:
-// - make_http_and_ws() β constructs App + WebSocket server
-// - run_http_and_ws() β automatically runs both runtimes
-//
-// HTTP:
-// GET /
-// GET /hello/{name}
-//
-// WebSocket:
-// Broadcasts a welcome message on connection
-// Echoes typed chat messages to all clients
-//
+/**
+ *
+ * @file examples/http_ws/main_basic.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
#include
@@ -24,36 +19,26 @@ using namespace vix;
int main()
{
- // ------------------------------------------------------------
- // 1) Construct the HTTP App + WebSocket Server together
- // ------------------------------------------------------------
- // The config file path can be omitted; if omitted,
- // Vix will automatically look for config/config.json.
- //
- auto bundle = vix::make_http_and_ws("config/config.json");
- auto &[app, ws] = bundle;
+ // Construct the HTTP App + WebSocket Server together
+ // The config file path can be omitted; if omitted,
+ // Vix will automatically look for config/config.json.
+ //
+ auto bundle = vix::make_http_and_ws("config/config.json");
+ auto &[app, ws] = bundle;
- // ------------------------------------------------------------
- // 2) Register HTTP routes
- // ------------------------------------------------------------
+ // GET /
+ app.get("/", [](Request &, Response &res)
+ { res.json({"framework", "Vix.cpp",
+ "message", "HTTP + WebSocket example (basic) π"}); });
- // GET /
- app.get("/", [](auto &, auto &res)
- { res.json({"framework", "Vix.cpp",
- "message", "HTTP + WebSocket example (basic) π"}); });
+ // GET /hello/{name}
+ app.get("/hello/{name}", [](Request &req, Response &res)
+ { res.json({"greeting", "Hello " + req.param("name") + " π",
+ "powered_by", "Vix.cpp"}); });
- // GET /hello/{name}
- app.get("/hello/{name}", [](auto &, auto &res, auto ¶ms)
- { res.json({"greeting", "Hello " + params["name"] + " π",
- "powered_by", "Vix.cpp"}); });
-
- // ------------------------------------------------------------
- // 3) Register WebSocket event handlers
- // ------------------------------------------------------------
-
- // When a new WebSocket connection opens:
- ws.on_open([&ws](auto &session)
- {
+ // Register WebSocket event handlers
+ ws.on_open([&ws](auto &session)
+ {
(void)session;
ws.broadcast_json("chat.system", {
@@ -61,11 +46,12 @@ int main()
"text", "Welcome to Vix WebSocket! π"
}); });
- // When a typed message is received:
- ws.on_typed_message([&ws](auto &session,
- const std::string &type,
- const vix::json::kvs &payload)
- {
+ // When a typed message is received:
+ ws.on_typed_message(
+ [&ws](auto &session,
+ const std::string &type,
+ const vix::json::kvs &payload)
+ {
(void)session;
// Basic chat echo example
@@ -73,15 +59,13 @@ int main()
ws.broadcast_json("chat.message", payload);
} });
- // ------------------------------------------------------------
- // 4) Start HTTP + WebSocket together
- // ------------------------------------------------------------
- // This function:
- // - runs the WebSocket server in a background thread
- // - installs a shutdown callback on the HTTP server
- // - blocks on app.run(port)
- //
- vix::run_http_and_ws(app, ws, 8080);
+ // 4) Start HTTP + WebSocket together
+ // This function:
+ // - runs the WebSocket server in a background thread
+ // - installs a shutdown callback on the HTTP server
+ // - blocks on app.run(port)
+ //
+ vix::run_http_and_ws(app, ws, 8080);
- return 0;
+ return 0;
}
diff --git a/examples/http_ws/main_chat.cpp b/examples/http_ws/main_chat.cpp
index 98856cb..bacdedb 100644
--- a/examples/http_ws/main_chat.cpp
+++ b/examples/http_ws/main_chat.cpp
@@ -1,15 +1,16 @@
-//
-// examples/http_ws/main_chat.cpp
-//
-// Chat-style example on top of HTTP + WebSocket.
-//
-// Demonstrates:
-// - HTTP JSON endpoints
-// - WebSocket typed messages for chat:
-// * "chat.join" β user joined
-// * "chat.message" β broadcast chat message
-// * "chat.typing" β typing indicator
-//
+/**
+ *
+ * @file examples/http_ws/main_chat.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
#include
@@ -18,40 +19,34 @@ using namespace vix;
int main()
{
- vix::serve_http_and_ws(
- "config/config.json", 8080,
- [](auto &app, auto &ws)
- {
- // --------------------------------------------------------
- // HTTP: basic API for client bootstrapping
- // --------------------------------------------------------
+ vix::serve_http_and_ws(
+ "config/config.json", 8080,
+ [](App &app, auto &ws)
+ {
+ // HTTP: basic API for client bootstrapping
+ app.get("/", [](Request &, Response &res)
+ { res.json({"name", "Vix Chat Example",
+ "description", "HTTP + WebSocket powered chat server",
+ "framework", "Vix.cpp"}); });
- app.get("/", [](auto &, auto &res)
- { res.json({"name", "Vix Chat Example",
- "description", "HTTP + WebSocket powered chat server",
- "framework", "Vix.cpp"}); });
+ app.get("/health", [](auto &, auto &res)
+ { res.json({"status", "ok",
+ "service", "chat",
+ "version", "1.0.0"}); });
- app.get("/health", [](auto &, auto &res)
- { res.json({"status", "ok",
- "service", "chat",
- "version", "1.0.0"}); });
-
- // --------------------------------------------------------
- // WebSocket: chat protocol
- //
- // Client messages are expected as:
- // {
- // "type": "chat.join" | "chat.message" | "chat.typing",
- // "payload": {
- // "user": "Alice",
- // "text": "...", // for chat.message
- // "room": "general" // optional
- // }
- // }
- // --------------------------------------------------------
-
- ws.on_open([&ws](auto &session)
- {
+ // WebSocket: chat protocol
+ //
+ // Client messages are expected as:
+ // {
+ // "type": "chat.join" | "chat.message" | "chat.typing",
+ // "payload": {
+ // "user": "Alice",
+ // "text": "...", // for chat.message
+ // "room": "general" // optional
+ // }
+ // }
+ ws.on_open([&ws](auto &session)
+ {
(void)session;
// Notify everybody that a new connection is here
@@ -60,37 +55,42 @@ int main()
"text", "A new user connected to the chat π"
}); });
- ws.on_typed_message(
- [&ws](auto &session,
- const std::string &type,
- const vix::json::kvs &payload)
- {
- (void)session;
+ ws.on_typed_message(
+ [&ws](auto &session,
+ const std::string &type,
+ const vix::json::kvs &payload)
+ {
+ (void)session;
+
+ if (type == "chat.join")
+ {
+ nlohmann::json j = vix::websocket::detail::ws_kvs_to_nlohmann(payload);
+ std::string user = j.at("user");
- if (type == "chat.join")
- {
- // Example: { "user": "Alice", "room": "general" }
- ws.broadcast_json("chat.system", {"user", payload.at("user"),
- "text", payload.at("user") + " joined the chat π"});
- }
- else if (type == "chat.message")
- {
- // Example: { "user": "Alice", "text": "Hello!" }
- ws.broadcast_json("chat.message", payload);
- }
- else if (type == "chat.typing")
- {
- // Example: { "user": "Alice" }
- ws.broadcast_json("chat.typing", payload);
- }
- else
- {
- // Unknown type β optional debug
- ws.broadcast_json("chat.unknown", {"info", "Unknown message type",
- "type", type});
- }
- });
- });
+ // Example: { "user": "Alice", "room": "general" }
+ ws.broadcast_json("chat.system",
+ {"user", user,
+ "text", user + " joined the chat π"});
+ }
+ else if (type == "chat.message")
+ {
+ // Example: { "user": "Alice", "text": "Hello!" }
+ ws.broadcast_json("chat.message", payload);
+ }
+ else if (type == "chat.typing")
+ {
+ // Example: { "user": "Alice" }
+ ws.broadcast_json("chat.typing", payload);
+ }
+ else
+ {
+ // Unknown type β optional debug
+ ws.broadcast_json("chat.unknown",
+ {"info", "Unknown message type",
+ "type", type});
+ }
+ });
+ });
- return 0;
+ return 0;
}
diff --git a/examples/http_ws/main_minimal.cpp b/examples/http_ws/main_minimal.cpp
index cc534b0..8ec3819 100644
--- a/examples/http_ws/main_minimal.cpp
+++ b/examples/http_ws/main_minimal.cpp
@@ -1,10 +1,16 @@
-//
-// examples/http_ws/main_minimal.cpp
-//
-// Minimal HTTP + WebSocket example.
-//
-// This is intentionally tiny, to show the shape of the API.
-//
+/**
+ *
+ * @file examples/http_ws/main_minimal.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
#include
@@ -13,9 +19,9 @@ using namespace vix;
int main()
{
- // Use default config path "config/config.json" and port 8080
- vix::serve_http_and_ws([](auto &app, auto &ws)
- {
+ // Use default config path "config/config.json" and port 8080
+ vix::serve_http_and_ws([](auto &app, auto &ws)
+ {
// Minimal HTTP route
app.get("/", [](auto&, auto& res) {
res.json({
@@ -37,5 +43,5 @@ int main()
}
}); });
- return 0;
+ return 0;
}
diff --git a/examples/http_ws/main_runtime.cpp b/examples/http_ws/main_runtime.cpp
index 371811a..61ca109 100644
--- a/examples/http_ws/main_runtime.cpp
+++ b/examples/http_ws/main_runtime.cpp
@@ -1,12 +1,16 @@
-//
-// examples/http_ws/main_runtime.cpp
-//
-// High-level example using vix::serve_http_and_ws().
-//
-// This is the most friendly API for Node.js / Python developers:
-// - One call to serve_http_and_ws(config, port, lambda)
-// - Inside the lambda you configure HTTP (app) and WebSocket (ws).
-//
+/**
+ *
+ * @file examples/http_ws/main_runtime.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include
#include
@@ -15,30 +19,24 @@ using namespace vix;
int main()
{
- vix::serve_http_and_ws(
- "config/config.json", 8080,
- [](auto &app, auto &ws)
- {
- // --------------------------------------------------------
- // HTTP routes (Express / FastAPI style)
- // --------------------------------------------------------
+ vix::serve_http_and_ws(
+ "config/config.json", 8080,
+ [](auto &app, auto &ws)
+ {
+ // HTTP routes
+ app.get("/", [](auto &, auto &res)
+ { res.json({"framework", "Vix.cpp",
+ "mode", "runtime",
+ "message", "HTTP + WebSocket via serve_http_and_ws() π"}); });
- app.get("/", [](auto &, auto &res)
- { res.json({"framework", "Vix.cpp",
- "mode", "runtime",
- "message", "HTTP + WebSocket via serve_http_and_ws() π"}); });
+ app.get("/hello/{name}", [](Request &req, Response &res)
+ { res.json({"greeting", "Hello " + req.param("name") + " π",
+ "powered_by", "Vix.cpp"}); });
- app.get("/hello/{name}", [](auto &, auto &res, auto ¶ms)
- { res.json({"greeting", "Hello " + params["name"] + " π",
- "powered_by", "Vix.cpp"}); });
-
- // --------------------------------------------------------
- // WebSocket handlers
- // --------------------------------------------------------
-
- // Fired when a client opens a WebSocket connection
- ws.on_open([&ws](auto &session)
- {
+ // WebSocket handlers
+ // Fired when a client opens a WebSocket connection
+ ws.on_open([&ws](auto &session)
+ {
(void)session;
ws.broadcast_json("chat.system", {
@@ -46,21 +44,21 @@ int main()
"text", "Welcome to the runtime example! π"
}); });
- // Fired on every typed message: { "type": "...", "payload": {...} }
- ws.on_typed_message(
- [&ws](auto &session,
- const std::string &type,
- const vix::json::kvs &payload)
- {
- (void)session;
+ // Fired on every typed message: { "type": "...", "payload": {...} }
+ ws.on_typed_message(
+ [&ws](auto &session,
+ const std::string &type,
+ const vix::json::kvs &payload)
+ {
+ (void)session;
- if (type == "chat.message")
- {
- // Echo / broadcast chat messages to all clients
- ws.broadcast_json("chat.message", payload);
- }
- });
- });
+ if (type == "chat.message")
+ {
+ // Echo / broadcast chat messages to all clients
+ ws.broadcast_json("chat.message", payload);
+ }
+ });
+ });
- return 0;
+ return 0;
}
diff --git a/examples/ip_filter/ip_filter_pipeline_demo.cpp b/examples/ip_filter/ip_filter_pipeline_demo.cpp
index 5512502..51086d6 100644
--- a/examples/ip_filter/ip_filter_pipeline_demo.cpp
+++ b/examples/ip_filter/ip_filter_pipeline_demo.cpp
@@ -1,9 +1,16 @@
-// ============================================================================
-// ip_filter_pipeline_demo.cpp β IP filter pipeline demo (Vix.cpp)
-// ----------------------------------------------------------------------------
-// Run:
-// vix run ip_filter_pipeline_demo.cpp
-// ============================================================================
+/**
+ *
+ * @file examples/ip_filter/ip_filter_pipeline_demo.cpp
+ * @author Gaspard Kirira
+ *
+ * Copyright 2025, Gaspard Kirira. All rights reserved.
+ * https://github.com/vixcpp/vix
+ * Use of this source code is governed by a MIT license
+ * that can be found in the License file.
+ *
+ * Vix.cpp
+ *
+ */
#include