Goldfish HTTP Router
A fast radix tree-based HTTP router for C++.
Quick Start
#include "goldfish.hpp"
using namespace goldfish;
Router router;
// Basic route
router.get("/hello", [](IRequest& req, IResponse& res, Params params) {
res.set_body("Hello, World!");
});
// Route with parameters
router.get("/users/:id", [](IRequest& req, IResponse& res, Params params) {
string user_id = string(params[0]);
res.set_body("User ID: " + user_id);
});
// Multiple parameters
router.get("/users/:userId/posts/:postId", [](IRequest& req, IResponse& res, Params params) {
string user_id = string(params[0]);
string post_id = string(params[1]);
res.set_json("{\"user\":\"" + user_id + "\",\"post\":\"" + post_id + "\"}");
});
API Reference
Router Methods
void get(string_view path, Handler handler);
void post(string_view path, Handler handler);
void put(string_view path, Handler handler);
void del(string_view path, Handler handler); // DELETE
void patch(string_view path, Handler handler);
bool handle(IRequest& request, IResponse& response);
Handler Signature
using Params = const std::vector<string_view>&;
using Handler = std::function<void(IRequest&, IResponse&, Params)>;
Path Parameters
Use :name
syntax for parameters:
/users/:id
matches/users/123
/api/:version/users/:id
matches/api/v1/users/456
Parameters are accessed by index in order of appearance:
router.get("/api/:version/users/:id", [](IRequest& req, IResponse& res, Params params) {
string version = string(params[0]); // :version
string id = string(params[1]); // :id
});
HTTP Server Example
#include "goldfish.hpp"
#include <iostream>
#include <thread>
// Your HTTP server headers here
using namespace goldfish;
class MyRequest : public IRequest {
private:
HttpMethod method_;
string_view path_;
// ... other fields
public:
MyRequest(const ServerRequest& req) {
// Parse from your server's request format
method_ = parse_method(req.method);
path_ = req.path;
}
HttpMethod method() const override { return method_; }
string_view path() const override { return path_; }
// ... implement other methods
};
class MyResponse : public IResponse {
private:
ServerResponse& response_;
public:
MyResponse(ServerResponse& res) : response_(res) {}
void set_status(int status) override {
response_.status = status;
}
void set_body(string_view body) override {
response_.body = string(body);
}
// ... implement other methods
};
int main() {
Router router;
// Define routes
router.get("/", [](IRequest& req, IResponse& res, Params params) {
res.set_content_type("text/html");
res.set_body("<h1>Welcome to Goldfish!</h1>");
});
router.get("/api/users/:id", [](IRequest& req, IResponse& res, Params params) {
string user_id = string(params[0]);
res.set_content_type("application/json");
res.set_body("{\"id\":\"" + user_id + "\",\"name\":\"User " + user_id + "\"}");
});
router.post("/api/users", [](IRequest& req, IResponse& res, Params params) {
// Create user logic
res.set_status(201);
res.set_body("{\"message\":\"User created\"}");
});
// Start server
HttpServer server;
server.on_request([&](ServerRequest& req, ServerResponse& res) {
MyRequest request(req);
MyResponse response(res);
if (!router.handle(request, response)) {
response.set_status(404);
response.set_body("Not Found");
}
});
server.listen(8080);
std::cout << "Server running on port 8080\n";
return 0;
}
Performance
Benchmarked on typical hardware:
- Lookup speed: 364K lookups/second
- Average latency: 2.75μs per lookup
- Memory: Zero allocations during routing
- Scalability: Linear with route count
Building
g++ -std=c++20 -O3 your_app.cpp -o your_app
Description
Languages
C++
100%