Goldfish/README.md
2025-06-22 14:40:33 -05:00

164 lines
3.7 KiB
Markdown

# Goldfish HTTP Router
A fast radix tree-based HTTP router for C++.
## Quick Start
```cpp
#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
```cpp
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
```cpp
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:
```cpp
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
```cpp
#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
```bash
g++ -std=c++20 -O3 your_app.cpp -o your_app
```