C-REST is a lightweight, high-performance, and memory-safe RESTful web framework written in C. It provides a robust foundation for building HTTP servers with dynamic routing, JSON support, and optimized TCP handling.
Designed for efficiency, C-REST implements TCP Keep-Alive and TCP_NODELAY mechanisms to achieve low latency and high throughput (capable of handling 30k+ requests per second on standard hardware).
- High Performance: Optimized for speed using TCP Keep-Alive and disabling Nagle's algorithm (TCP_NODELAY).
- Robust Networking: Implements a receive loop to correctly handle TCP packet fragmentation and partial reads.
- Dynamic Routing: Supports parametric routes (e.g.,
/users/:id) using thread-safe parsing (strtok_r). - Memory Safe: Rigorously tested against memory leaks; uses
callocfor clean buffer initialization. - JSON Support: Built-in JSON parsing and stringification via the integrated
c_dictlibrary. - Middleware-ready Architecture: Supports request headers inspection for authentication and logic implementation.
- Zero-Dependency (External): Depends only on the standard C library and the included
c_dictlibrary.
.
├── examples/ # Example usage and showcase application
├── src/
│ ├── exception/ # Error handling and exception types
│ ├── libs/ # Internal libraries (c_dict)
│ ├── request/ # HTTP request parsing logic
│ └── server/ # Core TCP server and routing logic
├── test/ # Functional testing scripts (Python)
├── LICENSE # MIT License file
└── Makefile # Build configuration
This project uses Make for compilation. It automatically handles the compilation of the internal c_dict library.
- GCC Compiler
- Make
-
Build the Static Library: Generates
libcrest.ain the root directory.make
-
Build the Example Application: Compiles the library and the example server.
make example
-
Clean Build Artifacts: Removes object files and binaries.
make fclean
Below is a minimal example of how to create a server, define routes, and handle JSON data.
#include <stdio.h>
#include <stdlib.h>
#include "server.h"
#define PORT 3001
// 1. Basic Text Response
void ping_handler(Request *req, Response *res) {
res_plain(res, "pong");
}
// 2. Dynamic Path Parameter Example (GET /users/:id)
void get_user(Request *req, Response *res) {
// Extract 'id' from the route parameters
variable id_var = getDictVariable_var(req->params, "id");
if (id_var.type == TYPE_STRING) {
// Create a JSON response
Dict *user = createDict_string("id", user_id);
addDict_string(user, "name", "Demo User");
addDict_string(user, "role", "admin");
res_json(res, user);
free_dict(user);
} else {
res_status(res, 400);
res_plain(res, "Invalid ID");
}
}
// 3. JSON Body Parsing Example (POST /data)
void post_data(Request *req, Response *res) {
Dict *body = NULL;
if (req->body) {
body = json_parse(req->body);
}
// Echo the received JSON back to the client
res_json(res, body);
if (body) {
free_dict(body);
}
}
int main() {
Exception *exception = NULL;
// Initialize Server
Server *app = create_server(PORT, &exception);
if (exception) {
fprintf(stderr, "Failed to start server.\n");
exit(1);
}
// Register Routes
add_route(app, HTTP_GET, "/ping", ping_handler);
add_route(app, HTTP_GET, "/users/:id", get_user);
add_route(app, HTTP_POST, "/data", post_data);
printf("Server listening on port %d\n", PORT);
// Start Listening
listen_server(app);
return 0;
}The project includes a Python script to verify the functionality of the framework (routing, parsing, keep-alive connections).
-
Build and run the example server:
make example ./example_server
-
In a separate terminal, run the test suite:
python3 test/tester.py
This project is licensed under the MIT License. See the LICENSE file for details.