A C++20 framework for building REST APIs with job processing, metrics callbacks, and WebSocket support.
- REST API Development: Built on top of Pistache HTTP library
- OpenAPI Documentation:
DocAPIhelpers record request/response examples and exportopenapi.json - Input Validation: Validators for request fields, types, and formats
- WebSocket Support: Real-time bidirectional communication
- HTTP Wrappers: Simplified request/response handling
- HTTPS Client Utilities: Poco HTTP/HTTPS connection pooling and SSL client initialization
- Queueable Jobs: Asynchronous job processing with serialization support
- Job Execution: Worker loop with optional execution in a forked process
- Metrics Collection: Job lifecycle callbacks and a console metrics implementation
- Job Retry Logic: Automatic retry mechanisms for failed jobs
- Queue Management: Named queues and scheduled jobs with in-memory and Redis backends
- MySQL Integration: Native MySQL C++ Connector support
- Redis Support: Caching and job queues via Poco Redis
- Storage Controllers: File and data storage abstractions
- Database Migrations: Schema management utilities
- Code Generation: Automatic job class generation (
newjob.sh) - Testing Framework: Google Test integration
- Code Quality: Clang-tidy and clang-format support
Important Notice: This is a personal project currently under development and is provided without any warranties or guarantees. The framework is experimental and should not be used in production environments without thorough testing and evaluation. Features may change, and compatibility is not guaranteed across versions.
This project serves primarily as a learning exercise and concept exploration for modern C++20 API development patterns.
- Compiler: C++20 support required; the CI configuration uses Clang 18
- Build System: CMake 3.16+
- Libraries:
- Poco C++ Libraries (JSON, Net, NetSSL, Redis, Crypto)
- Pistache HTTP
- MySQL C++ Connector
- Google Test (for testing)
- OpenSSL
- Linux (CI runs on
ubuntu-latest) - Redis Server (for Redis-backed caching, queues, and Redis integration tests)
- MySQL Server (optional, for database features)
# Install build tools
sudo apt-get update && sudo apt-get install build-essential cmake ninja-build
# Install Clang (recommended)
sudo apt install clang-18 clang-tidy-18 clang-format
# Install Pistache
sudo add-apt-repository ppa:pistache+team/unstable
sudo apt update && sudo apt install libpistache-dev
# Install other dependencies
sudo apt-get install libpoco-dev libmysqlcppconn-dev libgtest-dev libssl-dev pkg-config
sudo apt-get install redis-server redis-tools # Required for Redis integration tests# Clone the repository
git clone https://github.com/Fabio3rs/cppapiframework.git
cd cppapiframework
# Configure build
mkdir build && cd build
export CC=$(which clang-18) # Optional: use Clang
export CXX=$(which clang++-18)
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Debug
# Build
cmake --build . --config Debug --target all -j $(nproc)
# Run tests
ctest -j 20 -C Debug -T test --output-on-failure#include "projstdafx.hpp"
#include "WebInterface/WebApp.hpp"
void hello(httpwrappers::Req, httpwrappers::Resp response) {
response.send(httpwrappers::Code::Ok,
R"({"message":"Hello, World!"})",
httpwrappers::jsonMimeType());
}
int main() {
webapp::WebApp app;
app.init(Pistache::Address("127.0.0.1", 8080), 4);
app.get("/hello", hello);
app.start([]() {
std::cout << "Server running on http://127.0.0.1:8080" << std::endl;
});
}For controller-based routing, implement CController::register_routes and
attach the controller with CPistacheEndpoint::register_controller.
#include "projstdafx.hpp"
#include "jobhandler/QueueableJob.hpp"
#include "jobhandler/QueueWorker.hpp"
#include "queues/StdQueue.hpp"
// Define a job class
class EmailJob : public job::QueueableJob {
std::string recipient;
std::string subject;
std::string body;
public:
QUEUEABLE_SERIALIZE(recipient, subject, body)
[[nodiscard]] auto getName() const -> std::string override {
return getTypeNameByInst(*this);
}
void handle() override {
// Send email logic here
std::cout << "Sending email to: " << recipient << std::endl;
std::cout << "Subject: " << subject << std::endl;
// Simulate processing time
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
EmailJob() = default;
EmailJob(std::string to, std::string subj, std::string content)
: recipient(std::move(to)), subject(std::move(subj)), body(std::move(content)) {}
};
int main() {
// Create job handler and worker
auto handler = std::make_shared<job::JobsHandler>();
handler->register_job_handler<EmailJob>();
auto queue = std::make_shared<StdQueue>();
job::QueueWorker worker(handler, queue);
// Queue some jobs
worker.push("email_queue", EmailJob("user@example.com", "Welcome!", "Welcome to our service"));
worker.push("email_queue", EmailJob("admin@example.com", "Alert", "System status update"));
// Process jobs
while (worker.do_one("email_queue")) {}
return 0;
}Use the provided console callback with the worker from the previous example, before queuing jobs:
#include "jobhandler/SimpleConsoleMetrics.hpp"
// Inside main(), after constructing worker:
worker.setMetricsCallback(std::make_shared<job::SimpleConsoleMetrics>());Custom collectors can derive from job::WorkerMetricsCallback.
See the callback interface and
its tests for the supported events and signatures.
cppapiframework/
βββ src/
β βββ WebInterface/ # HTTP/REST API components
β β βββ WebApp.hpp # Main web application class
β β βββ CController.hpp # Base controller class
β β βββ httpwrappers.hpp # HTTP utilities
β βββ jobhandler/ # Background job processing
β β βββ QueueWorker.hpp # Job worker implementation
β β βββ QueueableJob.hpp # Base job class
β β βββ JobsHandler.hpp # Job management
β βββ Database/ # Database integration
β βββ Storage/ # File storage utilities
β βββ WebSocket/ # WebSocket support
β βββ utils/ # Utility classes
β β βββ DocAPI.hpp # OpenAPI documentation
β βββ boot.hpp # Application bootstrap
βββ tests/ # Unit tests
βββ example_metrics_usage.cpp # Usage examples
- Controllers:
CControllersubclasses register HTTP routes withCPistacheEndpoint - Observer Pattern: Metrics collection via callbacks
- Template Metaprogramming: Job serialization system
- RAII: Resource management throughout
- Factory Pattern: Job creation and handling
Run the test suite:
cd build
ctest -j 20 -C Debug -T test --output-on-failureIndividual test categories:
# Run specific tests
./bin/apiframework_test --gtest_filter='InputValidatorTest.*'
./bin/apiframework_test --gtest_filter='TestWorkerMetrics.*'- Metrics System: Comprehensive guide to job metrics collection
- Implementation Summary: Recent feature implementations
- API Documentation:
DocAPIrecording macros are enabled whenNDEBUGis not defined; callDocAPI::singleton().dump()to writeopenapi.json
Generate new job classes:
mkdir -p src/jobs
./newjob.sh MyNewJobThe project uses enhanced security-focused static analysis tools:
# Format code
clang-format -i src/**/*.cpp src/**/*.hpp
# Run enhanced security-focused static analysis
clang-tidy src/**/*.cpp --checks='-*,cert-*,bugprone-*,clang-analyzer-security*,cppcoreguidelines-*' -- -std=c++20
# Run additional security analysis
cppcheck --enable=all --std=c++20 src/The repository includes static analysis configuration and CI workflows for security checks:
- CodeQL: GitHub's semantic code analysis engine
- Enhanced clang-tidy: Security-focused static analysis with cert-, bugprone-, and security rules
- cppcheck: Additional static analysis for memory safety and undefined behavior
- Dependabot: Weekly update checks for GitHub Actions dependencies
- SBOM Generation: The security workflow invokes Syft to generate an SBOM and Grype to scan it
- Input Validation: Field validators in
InputValidatorsand request validation throughWebInputValidator - SQL Helpers: MySQL string escaping in
CSqland prepared statements in migration lookup
For security vulnerabilities, please refer to our Security Policy. DO NOT create public issues for security vulnerabilities.
The CI workflows pass additional compiler and linker hardening flags explicitly. To use similar flags locally:
# Security-hardened build
cmake .. -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-Wall -Wextra -fstack-protector-strong -D_FORTIFY_SOURCE=3 -fPIE" \
-DCMAKE_EXE_LINKER_FLAGS="-pie -Wl,-z,relro,-z,now"# GCC
export CC=gcc CXX=g++
# Clang (recommended)
export CC=clang-18 CXX=clang++-18
cmake .. -G Ninja- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes following the existing code style
- Add tests for new functionality
- Ensure all tests pass:
ctest - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Use C++20 features when appropriate
- Follow RAII principles
- Add comprehensive tests for new features
- Document public APIs with Doxygen comments
- Use
clang-formatfor consistent formatting
This project is licensed under the MIT License - see the LICENSE file for details.
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Note: This framework is actively developed and some features may be experimental. Please check the issues and documentation for the latest information.