-
Notifications
You must be signed in to change notification settings - Fork 2
Router: 1. Router Setup Procedure
Cluster object using config() method and configuration file as argument setups Router
// main.cpp
Cluster cluster;
try {
cluster.config(av[1]); // setup Router
cluster.create();
cluster.run();
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}The same function in action
// av[1] => _configs
_router.setupRouter(_configs);_configs is a list of Server structures
std::vector<Server> _configs;The Server class represents a web server instance, which listens for incoming HTTP requests and handles them based on its configuration and associated Location blocks.
class Server {
private:
uint32_t _address; // IP address to bind (e.g., 127.0.0.1)
int _port; // Port to listen on (e.g., 80, 443)
std::string _name; // Server name (e.g., "example.com")
std::string _root; // Root directory for serving files
std::string _index; // Default index file for the server
std::map<int, std::string> _error_pages; // Error code to error page mapping
size_t _client_max_body_size = MAX_BODY_SIZE; // Max size for client request body
std::vector<Location> _locations; // List of location blocks
public:
...
};The Location struct represents a specific location (or route) on the server, such as a URL path (e.g., /, /api, or /images). It defines how the server handles requests to that path.
struct Location
{
std::string location; // The URL path (e.g., "/", "/api")
std::vector<std::string> allowed_methods; // HTTP methods allowed (e.g., "GET", "POST")
std::string index; // Default file to serve (e.g., "index.html")
bool autoindex; // Enable/disable directory listing
std::string cgi_path; // Path to CGI executable for dynamic content
std::vector<std::string> cgi_ext; // File extensions for CGI scripts (e.g., ".php", ".py")
std::string upload_path; // Directory for file uploads
std::string return_url; // URL for redirection
};This declares a nested std::map data structure with three levels of key-value mappings, where the innermost value is of type Handler.
std::map<std::string, std::map<std::string, std::map<std::string, Handler>>> _routes;The _routes variable can be visualized as:
_routes
├── "example.com" (server name)
│ ├── "/users" (path)
│ │ ├── "GET" → Handler (function/class to handle GET /users)
│ │ ├── "POST" → Handler (function/class to handle POST /users)
│ ├── "/login" (path)
│ │ ├── "POST" → Handler (function/class to handle POST /login)
├── "api.example.com" (server name)
│ ├── "/data" (path)
│ │ ├── "GET" → Handler (function/class to handle GET /data)std::map is a sorted associative container that stores key-value pairs.
Keys are unique and sorted (in this case, std::string keys are sorted lexicographically).
Lookup time is logarithmic (O(log n)).
void Router::setupRouter(const std::vector<Server>& configs);The loop iterates through each Server object in the configs vector to process its configuration and set up routing rules for the web server using addRoute() method.
void Router::setupRouter(const std::vector<Server>& configs) {
// ...
for (const auto& server : configs) {
// Process each server configuration
// ...
// Register the route in the routing table
addRoute(server.getName(), method, location_path, handler);
}
}Process each location block in the server configuration.
void Router::setupRouter(const std::vector<Server>& configs) {
_routes.clear();
for (const auto& server : configs) {
for (const auto& location : server.getLocations()) {
std::string location_path = location.location;
for (const auto& method : location.allowed_methods) { // <--- Process a location block
// Process HTTP methods and assign handlers
Handler handler;
// ...
addRoute(server.getName(), method, location_path, handler);
// ...
}
}
}
// ...
}The core of the routing logic, determining how HTTP requests to a specific server and URL path are handled based on the HTTP method and Location configuration.
// Register routes for each allowed HTTP method in this location
for (const auto& method : location.allowed_methods) {
// Choose the appropriate handler based on location configuration and method
Handler handler;
// Handler selection logic based on location properties:
if (!location.return_url.empty()) {
// Redirect location: return_url is configured
// Use redirect handler for all HTTP methods
handler = redirect;
} else if (!location.cgi_path.empty() && !location.cgi_ext.empty()) {
// CGI location: Both CGI path and extension are configured
// Use CGI handler for script execution (supports any HTTP method)
handler = cgi;
} else if (method == "POST" && !location.upload_path.empty()) {
// POST request to upload location: Handle file uploads
handler = post;
} else if (method == "DELETE" && !location.upload_path.empty()) {
// DELETE request from upload location: Handle file deletions
handler = del;
} else {
// Default handler for other methods or configurations
handler = get;
}
// Register the route in the routing table
addRoute(server.getName(), method, location_path, handler);
}
}
}
// ...
}