From 787432ff0c003ede0fe4b054e36d5917b78d73ba Mon Sep 17 00:00:00 2001 From: whaffman Date: Mon, 29 Sep 2025 16:09:40 +0200 Subject: [PATCH] refactor: simplify Client and HttpRequest constructors, add status code management --- webserv/client/Client.cpp | 36 +++++++++++++++---- webserv/client/Client.hpp | 11 ++++-- webserv/config/ConfigManager.cpp | 36 +++++++++++++++++++ webserv/config/ConfigManager.hpp | 3 ++ webserv/config/directive/ADirective.hpp | 2 +- webserv/config/directive/DirectiveFactory.hpp | 2 +- webserv/handler/ErrorHandler.hpp | 12 ++++++- webserv/handler/Errorhandler.cpp | 19 ++++++++++ webserv/http/HttpRequest.cpp | 17 ++++++--- webserv/http/HttpRequest.hpp | 6 ++-- webserv/main.cpp | 12 +++---- webserv/server/Server.cpp | 2 +- 12 files changed, 132 insertions(+), 26 deletions(-) create mode 100644 webserv/handler/Errorhandler.cpp diff --git a/webserv/client/Client.cpp b/webserv/client/Client.cpp index 4da4193..3574249 100644 --- a/webserv/client/Client.cpp +++ b/webserv/client/Client.cpp @@ -1,3 +1,4 @@ +#include "webserv/config/ConfigManager.hpp" #include #include // for HttpHeaders #include // for Log, LOCATION @@ -13,9 +14,9 @@ class ServerConfig; -Client::Client(std::unique_ptr socket, Server &server, const ServerConfig &server_config) - : client_socket_(std::move(socket)), server_(std::ref(server)), server_config_(std::cref(server_config)), - httpRequest_(std::make_unique(&server_config, this)) +Client::Client(std::unique_ptr socket, Server &server) + : client_socket_(std::move(socket)), server_(std::ref(server)), + httpRequest_(std::make_unique(this)) { } @@ -25,6 +26,16 @@ Client::~Client() server_.removeFromEpoll(*client_socket_); }; +int Client::getStatusCode() const +{ + return statusCode_; +} + +void Client::setStatusCode(int code) +{ + statusCode_ = code; +} + void Client::request() { char buffer[bufferSize_] = {}; // NOLINT(cppcoreguidelines-avoid-c-arrays) @@ -56,6 +67,13 @@ void Client::request() {"body", httpRequest_->getBody()}, {"state", std::to_string(static_cast(httpRequest_->getState()))}, }); + server_config_ = ConfigManager::getInstance().getMatchingServerConfig(httpRequest_->getHeaders().get("Host")); + if (server_config_ == nullptr) + { + Log::warning("No matching server config found for Host: " + httpRequest_->getHeaders().get("Host")); + httpRequest_->setState(HttpRequest::State::ParseError); + } + // Example usage, replace with actual host and port extraction from request server_.responseReady(client_socket_->getFd()); } else @@ -79,10 +97,16 @@ std::string Client::getResponse() const else { response += "200 OK\r\n"; - } + // further validation can be added here - response += "Content-Length: 18\r\n\r\n"; - response += "Server port 8080\r\n"; + + auto serverName = server_config_->getDirectiveValue("server_name"); + auto port = server_config_->getDirectiveValue("listen"); + std::string body = "Server Name " + serverName + "\r\n"; + body += "Server port " + std::to_string(port) + "\r\n"; + response += "Content-Length: " + std::to_string(body.size()) + "\r\n\r\n"; + response += body; + } Log::debug("Sending response:\n" + response); return response; diff --git a/webserv/client/Client.hpp b/webserv/client/Client.hpp index da88db7..da81985 100644 --- a/webserv/client/Client.hpp +++ b/webserv/client/Client.hpp @@ -1,6 +1,7 @@ #pragma once #include // for ServerConfig +#include // for StatusCode, HTTP #include // for HttpRequest #include #include @@ -16,7 +17,7 @@ class ServerConfig; class Client { public: - Client(std::unique_ptr socket, Server &server, const ServerConfig &server_config); + Client(std::unique_ptr socket, Server &server); Client(const Client &other) = delete; // Disable copy constructor Client &operator=(const Client &other) = delete; // Disable copy assignment @@ -28,10 +29,14 @@ class Client void request(); [[nodiscard]] std::string getResponse() const; + [[nodiscard]] int getStatusCode() const; + void setStatusCode(int code); + private: + int statusCode_ = Http::StatusCode::OK; constexpr static size_t bufferSize_ = 4096; std::unique_ptr httpRequest_ = nullptr; std::unique_ptr client_socket_; - const Server &server_; - const ServerConfig &server_config_; + Server &server_; + mutable const ServerConfig *server_config_ = nullptr; }; \ No newline at end of file diff --git a/webserv/config/ConfigManager.cpp b/webserv/config/ConfigManager.cpp index 626a3a8..4c8beb9 100644 --- a/webserv/config/ConfigManager.cpp +++ b/webserv/config/ConfigManager.cpp @@ -1,3 +1,4 @@ +#include "webserv/config/ServerConfig.hpp" #include #include // for GlobalConfig #include // for removeComments @@ -59,4 +60,39 @@ std::vector ConfigManager::getServerConfigs() const throw std::runtime_error("ConfigManager is not initialized."); } return globalConfig_->getServerConfigs(); +} + +ServerConfig *ConfigManager::getMatchingServerConfig(const std::string &host_port) const +{ + if (!initialized_) + { + throw std::runtime_error("ConfigManager is not initialized."); + } + // split host and port on the colon: + size_t colonPos = host_port.find(':'); + std::string host = (colonPos != std::string::npos) ? host_port.substr(0, colonPos) : host_port; + int port = (colonPos != std::string::npos) ? std::stoi(host_port.substr(colonPos + 1)) : 0; + return getMatchingServerConfig(host, port); +} + +ServerConfig *ConfigManager::getMatchingServerConfig(const std::string &host, int port) const +{ + if (!initialized_) + { + throw std::runtime_error("ConfigManager is not initialized."); + } + std::vector serverConfigs = globalConfig_->getServerConfigs(); + for (ServerConfig *serverConfig : serverConfigs) + { + auto serverName = serverConfig->getDirectiveValue("server_name", ""); + auto listenPorts = serverConfig->getDirectiveValue("listen", 80); + Log::debug("Checking server config: " + serverName + " on port " + std::to_string(listenPorts)); + if ((serverName == host) && (listenPorts == port)) + { + Log::info("Found matching server config for host: " + host + " and port: " + std::to_string(port)); + return serverConfig; + } + } + Log::warning("No matching server config found for host: " + host + " and port: " + std::to_string(port)); + return nullptr; } \ No newline at end of file diff --git a/webserv/config/ConfigManager.hpp b/webserv/config/ConfigManager.hpp index 6ab1f7c..08b2cdd 100644 --- a/webserv/config/ConfigManager.hpp +++ b/webserv/config/ConfigManager.hpp @@ -22,6 +22,9 @@ class ConfigManager static ConfigManager &getInstance(); [[nodiscard]] std::vector getServerConfigs() const; + [[nodiscard]] ServerConfig *getMatchingServerConfig(const std::string &host, int port) const; + [[nodiscard]] ServerConfig *getMatchingServerConfig(const std::string &host_port) const; + [[nodiscard]] GlobalConfig *getGlobalConfig() const; private: bool initialized_; diff --git a/webserv/config/directive/ADirective.hpp b/webserv/config/directive/ADirective.hpp index 5930452..9e1936c 100644 --- a/webserv/config/directive/ADirective.hpp +++ b/webserv/config/directive/ADirective.hpp @@ -38,7 +38,7 @@ class ADirective } protected: - std::string name_; + std::string name_; //NOLINT(cppcoreguidelines-non-private-member-variables-in-classes) }; // Non-member stream operator for ADirective diff --git a/webserv/config/directive/DirectiveFactory.hpp b/webserv/config/directive/DirectiveFactory.hpp index b8df032..59cde9b 100644 --- a/webserv/config/directive/DirectiveFactory.hpp +++ b/webserv/config/directive/DirectiveFactory.hpp @@ -29,7 +29,7 @@ class DirectiveFactory constexpr static std::array supportedDirectives = {{ {.name = "listen", .type = "IntDirective", .context = "SL"}, {.name = "host", .type = "StringDirective", .context = "SL"}, - {.name = "server_name", .type = "VectorDirective", .context = "SL"}, + {.name = "server_name", .type = "StringDirective", .context = "SL"}, {.name = "root", .type = "StringDirective", .context = "SL"}, {.name = "index", .type = "VectorDirective", .context = "SL"}, {.name = "error_page", .type = "IntStringDirective", .context = "SL"}, diff --git a/webserv/handler/ErrorHandler.hpp b/webserv/handler/ErrorHandler.hpp index 7b9637e..b84ecd8 100644 --- a/webserv/handler/ErrorHandler.hpp +++ b/webserv/handler/ErrorHandler.hpp @@ -1 +1,11 @@ -#pragma once \ No newline at end of file +#pragma once + +// #include "webserv/config/AConfig.hpp" +// class ErrorHandler +// { +// public: +// static std::string generateErrorPage(int statusCode, AConfig *config = nullptr); +// static std::string getStatusMessage(int statusCode); +// static bool isValidStatusCode(int statusCode); + +// }; \ No newline at end of file diff --git a/webserv/handler/Errorhandler.cpp b/webserv/handler/Errorhandler.cpp new file mode 100644 index 0000000..4b66923 --- /dev/null +++ b/webserv/handler/Errorhandler.cpp @@ -0,0 +1,19 @@ +#include + +#include // for StatusCode +#include +#include + + + +// std::string ErrorHandler::generateErrorPage(int statusCode, AConfig *config) +// { + +// std::string statusMessage = getStatusMessage(statusCode); +// std::string html = +// "" + std::to_string(statusCode) + " " + statusMessage + +// "

" + std::to_string(statusCode) + " " + statusMessage + +// "


webserv

"; +// return html; +// } + diff --git a/webserv/http/HttpRequest.cpp b/webserv/http/HttpRequest.cpp index cc7c8f6..a0fc7f7 100644 --- a/webserv/http/HttpRequest.cpp +++ b/webserv/http/HttpRequest.cpp @@ -1,7 +1,9 @@ #include // for stoul #include // for CRLF, DOUBLE_CRLF #include -#include // for Log, LOCATION +#include // for Log, LOCATION +#include // for Client + #include // for map #include // for optional @@ -11,8 +13,7 @@ class ServerConfig; -HttpRequest::HttpRequest(const ServerConfig *serverConfig, const Client *client) - : serverConfig_(serverConfig), client_(client) +HttpRequest::HttpRequest(Client *client) : client_(client) { Log::trace(LOCATION); } @@ -28,6 +29,11 @@ HttpRequest::State HttpRequest::getState() const return state_; } +void HttpRequest::setState(State state) +{ + state_ = state; +} + const HttpHeaders &HttpRequest::getHeaders() const { return headers_; @@ -80,7 +86,10 @@ void HttpRequest::parseBuffer() case State::Complete: Log::debug("HttpRequest::parseBuffer() request is complete"); return; // Request is complete - case State::ParseError: Log::warning("Parse error occurred, stopping further processing"); return; + case State::ParseError: + Log::warning("Parse error occurred, stopping further processing"); + client_->setStatusCode(Http::StatusCode::BAD_REQUEST); + return; } } catch (...) diff --git a/webserv/http/HttpRequest.hpp b/webserv/http/HttpRequest.hpp index c4d04af..fdfe39d 100644 --- a/webserv/http/HttpRequest.hpp +++ b/webserv/http/HttpRequest.hpp @@ -23,7 +23,7 @@ class HttpRequest ParseError }; - HttpRequest(const ServerConfig *serverConfig, const Client *client); + HttpRequest(Client *client); HttpRequest(const HttpRequest &other) = delete; HttpRequest(HttpRequest &&other) noexcept = delete; @@ -32,6 +32,7 @@ class HttpRequest ~HttpRequest(); [[nodiscard]] State getState() const; + void setState(State state); [[nodiscard]] const HttpHeaders &getHeaders() const; [[nodiscard]] const std::string &getBody() const; @@ -54,8 +55,7 @@ class HttpRequest void parseContentLength(); - const ServerConfig *serverConfig_; - const Client *client_; + Client *client_; State state_ = State::RequestLine; diff --git a/webserv/main.cpp b/webserv/main.cpp index c087787..6de542b 100644 --- a/webserv/main.cpp +++ b/webserv/main.cpp @@ -23,12 +23,12 @@ int main(int argc, char **argv) Log::info("ConfigManager initialized successfully."); - auto serverConfigs = configManager.getServerConfigs(); - auto *firstServer = serverConfigs[0]; - const auto *location = firstServer->getLocation("/"); - const auto *listenDirective = location->getDirective("listen"); - int listenPort = listenDirective->getValueAs(); - Log::warning("Listen port for '/' location: " + std::to_string(listenPort)); + // auto serverConfigs = configManager.getServerConfigs(); + // auto *firstServer = serverConfigs[0]; + // const auto *location = firstServer->getLocation("/"); + // const auto *listenDirective = location->getDirective("listen"); + // int listenPort = listenDirective->getValueAs(); + // Log::warning("Listen port for '/' location: " + std::to_string(listenPort)); diff --git a/webserv/server/Server.cpp b/webserv/server/Server.cpp index 02b45ff..e29cd97 100644 --- a/webserv/server/Server.cpp +++ b/webserv/server/Server.cpp @@ -113,7 +113,7 @@ void Server::handleConnection(struct epoll_event *event) std::unique_ptr clientSocket = listener.accept(); addToEpoll(*clientSocket, EPOLLIN); clients_.insert( - {clientSocket->getFd(), std::make_unique(std::move(clientSocket), *this, getConfig(listener))}); + {clientSocket->getFd(), std::make_unique(std::move(clientSocket), *this)}); } Socket &Server::getListener(int fd) const