classDiagram direction TB class Server { +Server(const ConfigManager&) +~Server() +start() +addToEpoll(Socket&, uint32_t) +removeFromEpoll(Socket&) +setupServerSocket(ServerConfig&) +handleConnection(epoll_event*) +handleRequest(epoll_event*) +responseReady(int) +eventLoop() +getListener(int) Socket& +getClient(int) Client& +getConfig(int) ServerConfig& +getConfig(Socket&) ServerConfig& -int epoll_fd_ -ConfigManager& configManager_ -vector> listeners_ -unordered_map fdToConfig_ -unordered_map> clients_ } class Socket { +Socket() +Socket(int) +~Socket() +listen(int) void +bind(string, int) void +accept() Socket* +recv(void*, size_t) ssize_t +send(const void*, size_t) ssize_t +setNonBlocking() void +getFd() int -int _fd } class Client { +Client(unique_ptr, Server&, ServerConfig&) +~Client()std::move(clientSocket), *this, getConfig(listener) +request() void +getResponse() string -unique_ptr client_socket_ -Server& server -ServerConfig& server_config } class ConfigManager { +init(string) +getInstance() ConfigManager& +getServerConfigs() vector -bool _initialized -vector serverConfigs } class ServerConfig { +ServerConfig(string) +getHost() string +getPort() int +getRoot() string +getCgiPass() string +getCgiExt() string +getErrorPages() map +getIndexFiles() vector +getLocation(string) LocationConfig& +getLocationPaths() vector +setServerFD(int) +getServerFD() int -string host -int port -int server_fd -string root -string cgi_pass -string cgi_ext -map error_page -vector index_files -map locations } class LocationConfig { +LocationConfig(string) -string path -bool autoIndex -string indexFile -map directives } class HttpRequest { +HttpRequest() +parse(string) bool +getMethod() string +getPath() string +getVersion() string +getHeader(string) string +getHeaders() map +getBody() string +hasHeader(string) bool +isComplete() bool -string method -string path -string version -map headers -string body -bool complete } class HttpResponse { +HttpResponse() +setStatus(int) +setHeader(string, string) +setBody(string) +toString() string +sendFile(string) +sendError(int) -int status_code -string status_message -map headers -string body } class Router { +Router(ServerConfig&) +route(HttpRequest&) HttpResponse +handleGet(HttpRequest&) HttpResponse +handlePost(HttpRequest&) HttpResponse +handleDelete(HttpRequest&) HttpResponse +serveFile(string) HttpResponse +listDirectory(string) HttpResponse +matchLocation(string) LocationConfig& -ServerConfig& config } class CgiHandler { +CgiHandler(LocationConfig&) +execute(HttpRequest&) HttpResponse +setupEnvironment(HttpRequest&) +executeScript(string, HttpRequest&) string +setTimeout(int) -LocationConfig& location -map env_vars -int timeout } class ConfigValidator { +validate(ConfigManager&) bool +validateServerConfig(ServerConfig&) bool +validateLocationConfig(LocationConfig&) bool +checkPortConflicts() bool +checkPathExists(string) bool +validateDirective(string, string) bool -vector errors -vector warnings } class Logger { +info(string) +warn(string) +error(string) +debug(string) +setLevel(LogLevel) -LogLevel level -ofstream logFile } class MimeTypeHandler { +getMimeType(string) string +loadMimeTypes() -map mimeTypes } Server "1" o-- "1..*" Socket : listens on Server "1" o-- "0..*" Client : manages Server "1" -- "1" ConfigManager : uses Client "1" *-- "1" Socket : owns Client "1" -- "1" Server : references Client "1" -- "1" ServerConfig : references Client "1" -- "1" HttpRequest : processes Client "1" -- "1" HttpResponse : generates ServerConfig "1" o-- "*" LocationConfig : has Router "1" -- "1" ServerConfig : uses Router "1" -- "*" CgiHandler : may use CgiHandler "1" -- "1" LocationConfig : uses ConfigManager "1" -- "1" ConfigValidator : validates with Router "1" -- "1" MimeTypeHandler : uses Server "1" -- "1" Logger : logs to