Quark is a lightweight, low-level HTTP server built from scratch in C++ using raw TCP sockets. It is designed as an educational project to explore networking fundamentals, HTTP parsing, and systems-level programming with modern C++.
- Basic HTTP/1.1 request parsing
- Support for common HTTP methods (GET, POST, etc.)
- Custom routing via a lightweight router
- Serving HTML and other file types from custom routes
- Static file serving with MIME type resolution
- Request + response middleware hooks
- Thread-per-connection concurrency model
- Graceful socket management
- Modular design with support for controller-based route handling
- Static library build (
libquark.a) for integration into other apps
make # builds libquark.a into build/cd example
make # builds example_app into ../build/
./build/example_appInside your app, you can define routes like:
Quark::Router::GET("/hello", [](Quark::HttpRequest &req) {
return Quark::HttpResponse::ok()
.setBody("Hello, world!")
.addHeader("Content-Type", "text/plain");
});or pass a reference to a static controller method:
Quark::Router::GET("/hello", YourController::someStaticMethod);Your routes can also return files!
Quark::Router::GET("/cat", [](Quark::HttpRequest &req) {
return Quark::HttpResponse::sendFile("path/to/kitty.png");
});or
Quark::Router::GET("/home", [](Quark::HttpRequest &req) {
return Quark::HttpResponse::sendFile("public/index.html");
})Path parameters are also supported, by passing in a : followed by the path parameter name:
Quark::ROUTER::GET("/:userId/details", [](Quark::HttpRequest &req) {
std::string userId = req.pathParams["userId"]; // will contain whatever userId was passed in the url
return Quark::HttpResponse::ok();
})By default, Quark will serve static files from a public/ directory contained
in the root of your project. Requests to the server such as /img/cat.png
will be routed to /public/img/cat.png if the file exists.
Quark can also be configured to serve static files from a different directory, if needed:
Quark::Server server = Quark::Server("9669");
server.staticServe("images");Often times, it is necessary to parse the body or augment a request / response. For this purpose, you can register middleware functions with the Quark server, which will run in the order they are defined.
Quark::Server server = Quark::Server("9669");
server
.registerRequestMiddleware([](Quark::HttpRequest& request) {
request.setBody("Overwritten body!");
})
.registerResponseMiddleware([](Quark::HttpResponse& response) {
response.addHeader("Access-Control-Allow-Origin", "*");
});
server.run();- C++17 compiler (tested with
clang++andg++) - POSIX-compatible environment (macOS, Linux)
- TLS support (OpenSSL)
- Streaming responses and chunked encoding