Elvis
Web application framework for c++. Non blocking sockets, http, websocket protocols supported. Postgresql connector for now. Multithreading app support
Install / Use
/learn @nkoukoul/ElvisREADME
Elvis
Description
Elvis intends to be a c++ web framework.
Inside elvis folder are the library source files and headers.
Inside samples folder there is an example application.
CMAKE support has been added. Two third party libraries are used,
libpqxx version 5.0.1 and cryptopp version 5.6.2
To build without postgres and crypto support (no websocket):
- install cpp devtools and cmake
- cmake ./
- make -> will generate a static Elvis.a lib and link with samples/example_app
To build with crypto support (websocket supported):
- install cpp devtools and cmake
- cmake -DUSE_CRYPTO=ON ./
- make -> will generate a static Elvis.a lib and link with samples/example_app
To build with postgres and crypto support (websocket supported):
- install cpp devtools and cmake
- cmake -DUSE_POSTGRES=ON -DUSE_CRYPTO=ON ./
- make -> will generate a static Elvis.a lib and link with samples/example_app
Other cmake options supported:
- -DDEBUG -> Debug build with connection monitor enabled.
- -DCONSOLE -> Log everything on stdout.
To run example app
./samples/example_app/server hostname port threads
Example usage
Create and access elvis from everywhere.
#include <elvis/app_context.h>
app* elvis = Elvis::App::GetInstance();
API to access internals
Use framework cache to cache data:
std::string key;
std::string data;
elvis->Cache(key, data);
Use framework cache to retrieve data:
std::string key;
std::string data = elvis->GetCacheData(key);
Use framework JSON deserializer:
std::string serializedData;
std::list<std::unordered_map<std::string, std::string>> json = elvis->JSONDeserialize(std::move(serializedData));
Use framework DB engine to create and retrieve models based on string query.
std::string query;
elvis->CreateModel(query);
elvis->RetrieveModel(query);
Create routes
std::unique_ptr<Elvis::RouteManager> routeManager = std::make_unique<Elvis::RouteManager>();
routeManager->SetRoute("/file", "GET", std::move(std::make_unique<FileGetController>()));
routeManager->SetRoute("/file", "POST", std::move(std::make_unique<FilePostController>()));
Configure app with hostname, port, thread number, routes logfile and loglevel.
elvis->Configure(ipaddr, port, thread_number, routeManager, "server.log", Elvis::LogLevel::INFO);
Default configure provides
- IOContext (elvis/io_context.h)
- Logger (elvis/logger.h)
- Concurrent Queue with thread pooling (elvis/queue.h)
- CryptoManager utils (elvis/crypto_manager.h, elvis/utils.h)
- Http Request/Response Context (elvis/request_context.h, elvis/response_context.h)
- WS Request/Response Context (if a crypto library is present) (elvis/request_context.h, elvis/response_context.h)
- JSON parsing and validating utils (elvis/json_utils.h)
- LRU Cache (there is also a timer based cash) (elvis/cache.h)
- Monitor for incoming connections available for debug builds (elvis/monitor.h)
Run threaded applications. The call below will block.
elvis->Run();
Create models and define the CRUD api (here only Create and Retrieve are implemented, display serializes model to string for display).
// Override IModel
class FileModel final: IModel {
private:
std::unique_ptr<Attribute<std::string>> m_Filename;
std::unique_ptr<Attribute<std::string>> m_Md5;
public:
FileModel() = delete;
explicit FileModel(std::string filename, std::string md5);
virtual void Create() const override;
virtual void Retrieve() const override;
virtual void Display() const override;
};
void FileModel::Create() const
{
std::string sql = "insert into operations (filename, md5) values ('test.txt', '1234')";
auto elvis = App::GetInstance();
elvis->CreateModel(sql);
}
Endpoint Example
// Override Elvis::IController
class FilePostController final: public Elvis::IController
{
public:
explicit FilePostController();
void DoStuff(std::unordered_map<std::string, std::string> &deserialized_input_data) override;
};
void FilePostController::DoStuff(std::unordered_map<std::string, std::string> &deserialized_input_data)
{
// This is json data so further deserialization is needed. The result is a list of objects.
// Here we expect only one.
auto elvis = App::GetInstance();
auto input = elvis->JSONDeserialize(std::move(deserialized_input_data["data"])).front();
if (input.empty())
{
std::cout << "FilePostController: 400 Bad Request\n";
deserialized_input_data["status"] = "400 Bad Request";
return;
}
auto file_model = std::make_unique<FileModel>(input["filename"], input["md5sum"]);
file_model->Create();
elvis->Cache(input["filename"], read_from_file("", input["filename"]));
}
// Register the controller.
std::unique_ptr<Elvis::RouteManager> routeManager = std::make_unique<Elvis::RouteManager>();
routeManager->SetRoute("/file", "POST", std::move(std::make_unique<FilePostController>()));
Related Skills
feishu-drive
347.2k|
things-mac
347.2kManage Things 3 via the `things` CLI on macOS (add/update projects+todos via URL scheme; read/search/list from the local Things database)
clawhub
347.2kUse the ClawHub CLI to search, install, update, and publish agent skills from clawhub.com
codebase-memory-mcp
1.2kHigh-performance code intelligence MCP server. Indexes codebases into a persistent knowledge graph — average repo in milliseconds. 66 languages, sub-ms queries, 99% fewer tokens. Single static binary, zero dependencies.
