Examples
Collection of practical examples using Crest.
Basic Examples
Hello World
#include "crest/crest.h"
void handle_root(crest_request_t* req, crest_response_t* res) {
crest_response_json(res, 200, "{\"message\":\"Hello, World!\"}");
}
int main(void) {
crest_app_t* app = crest_create();
crest_route(app, CREST_GET, "/", handle_root, "Root");
crest_run(app, "0.0.0.0", 8000);
crest_destroy(app);
return 0;
}
Multiple Routes
#include "crest/crest.hpp"
int main() {
crest::App app;
app.get("/", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({"message":"Home"})");
}, "Home page");
app.get("/about", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({"message":"About page"})");
}, "About page");
app.get("/contact", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({"message":"Contact page"})");
}, "Contact page");
app.run("0.0.0.0", 8000);
return 0;
}
CRUD API Examples
User Management API
#include "crest/crest.hpp"
#include <map>
#include <mutex>
#include <sstream>
std::map<int, std::string> users;
std::mutex users_mutex;
int next_id = 1;
std::string users_to_json() {
std::ostringstream oss;
oss << "{\"users\":[";
bool first = true;
for (const auto& [id, name] : users) {
if (!first) oss << ",";
oss << "{\"id\":" << id << ",\"name\":\"" << name << "\"}";
first = false;
}
oss << "]}";
return oss.str();
}
int main() {
crest::App app;
// List users
app.get("/users", [](crest::Request& req, crest::Response& res) {
std::lock_guard<std::mutex> lock(users_mutex);
res.json(200, users_to_json());
}, "List all users");
// Create user
app.post("/users", [](crest::Request& req, crest::Response& res) {
std::lock_guard<std::mutex> lock(users_mutex);
int id = next_id++;
users[id] = "User " + std::to_string(id);
std::ostringstream oss;
oss << "{\"id\":" << id << ",\"name\":\"" << users[id] << "\"}";
res.json(201, oss.str());
}, "Create a user");
// Update user
app.put("/users/:id", [](crest::Request& req, crest::Response& res) {
std::lock_guard<std::mutex> lock(users_mutex);
// Parse ID from path in real implementation
res.json(200, R"({"message":"User updated"})");
}, "Update a user");
// Delete user
app.del("/users/:id", [](crest::Request& req, crest::Response& res) {
std::lock_guard<std::mutex> lock(users_mutex);
// Parse ID from path in real implementation
res.json(200, R"({"message":"User deleted"})");
}, "Delete a user");
app.run("0.0.0.0", 8000);
return 0;
}
Blog API
#include "crest/crest.hpp"
#include <vector>
#include <string>
struct Post {
int id;
std::string title;
std::string content;
std::string author;
};
std::vector<Post> posts;
int next_post_id = 1;
int main() {
crest::App app;
app.get("/posts", [](crest::Request& req, crest::Response& res) {
// Return all posts
res.json(200, R"({"posts":[]})");
}, "Get all blog posts");
app.get("/posts/:id", [](crest::Request& req, crest::Response& res) {
// Return single post
res.json(200, R"({"id":1,"title":"Post"})");
}, "Get a blog post");
app.post("/posts", [](crest::Request& req, crest::Response& res) {
// Create new post
res.json(201, R"({"message":"Post created"})");
}, "Create a blog post");
app.run("0.0.0.0", 8000);
return 0;
}
Configuration Examples
Custom Configuration
#include "crest/crest.hpp"
int main() {
crest::Config config;
config.title = "My Custom API";
config.description = "A fully customized API";
config.version = "2.0.0";
config.docs_enabled = true;
config.max_connections = 500;
config.timeout_seconds = 45;
crest::App app(config);
app.get("/", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({"status":"running"})");
});
app.run("0.0.0.0", 8000);
return 0;
}
Environment-Based Configuration
#include "crest/crest.hpp"
#include <cstdlib>
#include <iostream>
std::string getEnv(const char* key, const char* default_val) {
const char* val = std::getenv(key);
return val ? std::string(val) : std::string(default_val);
}
int main() {
std::string env = getEnv("ENVIRONMENT", "development");
crest::Config config;
config.title = getEnv("API_TITLE", "My API");
config.version = getEnv("API_VERSION", "1.0.0");
config.docs_enabled = (env != "production");
crest::App app(config);
app.get("/", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({"status":"ok"})");
});
std::string host = getEnv("HOST", "0.0.0.0");
int port = std::stoi(getEnv("PORT", "8000"));
std::cout << "Running in " << env << " mode\n";
app.run(host, port);
return 0;
}
Response Type Examples
JSON Responses
app.get("/json", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({
"status": "success",
"data": {
"id": 1,
"name": "Example"
}
})");
});
Text Responses
app.get("/text", [](crest::Request& req, crest::Response& res) {
res.text(200, "This is plain text");
});
HTML Responses
app.get("/html", [](crest::Request& req, crest::Response& res) {
res.html(200, R"(
<!DOCTYPE html>
<html>
<head><title>Crest</title></head>
<body>
<h1>Welcome to Crest</h1>
<p>This is an HTML response</p>
</body>
</html>
)");
});
Request Handling Examples
Reading Request Body
app.post("/data", [](crest::Request& req, crest::Response& res) {
std::string body = req.body();
// Process body (parse JSON, etc.)
res.json(200, R"({"received": true})");
});
Query Parameters
app.get("/search", [](crest::Request& req, crest::Response& res) {
std::string query = req.query("q");
std::string page = req.query("page");
// Use parameters
res.json(200, R"({"query":")" + query + "\"}");
});
Headers
app.get("/auth", [](crest::Request& req, crest::Response& res) {
std::string auth = req.header("Authorization");
if (auth.empty()) {
res.json(401, R"({"error":"Unauthorized"})");
return;
}
// Validate token
res.json(200, R"({"status":"authorized"})");
});
Error Handling Examples
Try-Catch Pattern
int main() {
try {
crest::App app;
app.get("/", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({"status":"ok"})");
});
app.run("0.0.0.0", 8000);
} catch (const crest::Exception& e) {
std::cerr << "Crest error: " << e.what() << "\n";
return 1;
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << "\n";
return 1;
}
return 0;
}
Route-Level Error Handling
app.get("/risky", [](crest::Request& req, crest::Response& res) {
try {
// Potentially failing operation
throw std::runtime_error("Something went wrong");
} catch (const std::exception& e) {
res.json(500, R"({"error":"Internal server error"})");
}
});
Advanced Examples
API with Authentication
#include "crest/crest.hpp"
#include <string>
bool validate_token(const std::string& token) {
// Implement token validation
return token == "secret-token";
}
int main() {
crest::App app;
app.post("/login", [](crest::Request& req, crest::Response& res) {
// Validate credentials
res.json(200, R"({"token":"secret-token"})");
}, "Login endpoint");
app.get("/protected", [](crest::Request& req, crest::Response& res) {
std::string auth = req.header("Authorization");
if (!validate_token(auth)) {
res.json(401, R"({"error":"Unauthorized"})");
return;
}
res.json(200, R"({"data":"Protected resource"})");
}, "Protected endpoint");
app.run("0.0.0.0", 8000);
return 0;
}
File Upload API
app.post("/upload", [](crest::Request& req, crest::Response& res) {
std::string body = req.body();
// Process file upload
// Save to disk, etc.
res.json(200, R"({"message":"File uploaded"})");
}, "Upload a file");
Pagination Example
app.get("/items", [](crest::Request& req, crest::Response& res) {
std::string page_str = req.query("page");
std::string limit_str = req.query("limit");
int page = page_str.empty() ? 1 : std::stoi(page_str);
int limit = limit_str.empty() ? 10 : std::stoi(limit_str);
// Fetch paginated data
res.json(200, R"({
"page": )" + std::to_string(page) + R"(,
"limit": )" + std::to_string(limit) + R"(,
"items": []
})");
}, "Get paginated items");
Testing Examples
Health Check
app.get("/health", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({
"status": "healthy",
"timestamp": )" + std::to_string(time(nullptr)) + R"(,
"uptime": 12345
})");
}, "Health check endpoint");
Version Info
app.get("/version", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({
"version": "1.0.0",
"api_version": "v1",
"crest_version": ")" + std::string(crest::VERSION) + R"("
})");
}, "Version information");
Production Examples
Production-Ready Setup
#include "crest/crest.hpp"
#include <csignal>
#include <atomic>
std::atomic<bool> running{true};
void signal_handler(int signal) {
running = false;
}
int main() {
std::signal(SIGINT, signal_handler);
std::signal(SIGTERM, signal_handler);
crest::Config config;
config.title = "Production API";
config.version = "1.0.0";
#ifdef PRODUCTION
config.docs_enabled = false;
#else
config.docs_enabled = true;
#endif
crest::App app(config);
app.get("/", [](crest::Request& req, crest::Response& res) {
res.json(200, R"({"status":"running"})");
});
try {
app.run("0.0.0.0", 8000);
} catch (const crest::Exception& e) {
std::cerr << "Error: " << e.what() << "\n";
return 1;
}
return 0;
}
More Examples
Check the examples/
directory in the repository for more complete examples:
examples/cpp/main.cpp
- Full C++ exampleexamples/c/main.c
- Full C example
Running Examples
# Build examples
xmake build crest_example_cpp
xmake build crest_example_c
# Run C++ example
xmake run crest_example_cpp
# Run C example
xmake run crest_example_c
Visit http://127.0.0.1:8000/docs
to see the generated documentation!