From bd01a172c52f7f4b5f8f662862c6887c09de2e99 Mon Sep 17 00:00:00 2001 From: Quinten Date: Tue, 30 Sep 2025 16:05:08 +0200 Subject: [PATCH] feat: refactor HttpResponse and ErrorHandler for improved response handling and error management --- webserv/client/Client.cpp | 21 ++++------- webserv/client/Client.hpp | 3 +- webserv/handler/ErrorHandler.hpp | 9 ++--- webserv/handler/Errorhandler.cpp | 61 ++++++++++++-------------------- webserv/http/HttpHeaders.hpp | 9 ----- webserv/http/HttpResponse.cpp | 24 ++++++++++++- webserv/http/HttpResponse.hpp | 14 ++++---- 7 files changed, 66 insertions(+), 75 deletions(-) diff --git a/webserv/client/Client.cpp b/webserv/client/Client.cpp index 14b4a29..61207aa 100644 --- a/webserv/client/Client.cpp +++ b/webserv/client/Client.cpp @@ -16,7 +16,7 @@ Client::Client(std::unique_ptr socket, Server &server) : client_socket_(std::move(socket)), server_(std::ref(server)), httpRequest_(std::make_unique(this)), - httpResponse_(std::make_unique(this)) + httpResponse_(std::make_unique()) { Log::info("New client connected, fd: " + std::to_string(client_socket_->getFd())); } @@ -93,26 +93,17 @@ void Client::request() bool Client::isResponseReady() const { // todo: poll the httpResponse_ object + return httpResponse_->isComplete(); } std::vector Client::getResponse() const { Log::trace(LOCATION); - // if (httpRequest_->getState() == HttpRequest::State::ParseError) - // { - // return ErrorHandler::generateErrorPage(Http::StatusCode::BAD_REQUEST); - // } - // std::string response = "HTTP/1.1 "; - // response += "200 OK\r\n"; + if (httpRequest_->getState() == HttpRequest::State::ParseError) + { + return ErrorHandler::getErrorResponse(Http::StatusCode::BAD_REQUEST).toBytes(); + } - // 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::info("Prepared response for client fd: " + std::to_string(client_socket_->getFd())); - // Log::debug("Sending response:\n" + response); httpResponse_->setStatus(200); httpResponse_->addHeader("Content-Type", "text/plain"); httpResponse_->appendBody("Hello, World!\n"); diff --git a/webserv/client/Client.hpp b/webserv/client/Client.hpp index 47319ae..fa7e02f 100644 --- a/webserv/client/Client.hpp +++ b/webserv/client/Client.hpp @@ -12,8 +12,7 @@ #include // for size_t #include -#include // for unique_ptr -#include // for string +#include // for unique_ptr #include class Server; diff --git a/webserv/handler/ErrorHandler.hpp b/webserv/handler/ErrorHandler.hpp index 339eab2..7c38474 100644 --- a/webserv/handler/ErrorHandler.hpp +++ b/webserv/handler/ErrorHandler.hpp @@ -1,15 +1,16 @@ #pragma once +#include "webserv/http/HttpResponse.hpp" + #include class ErrorHandler { public: - static std::string getErrorResponse(int statusCode, AConfig *config = nullptr); + static HttpResponse getErrorResponse(int statusCode, AConfig *config = nullptr); + + private: static std::string generateErrorPage(int statusCode, AConfig *config = nullptr); - static std::string generateErrorHeader(int statusCode, const std::string &body); static std::string generateDefaultErrorPage(int statusCode); - static std::string_view getStatusMessage(int statusCode); - // static bool isValidStatusCode(int statusCode); static std::string getErrorPageFile(const std::string &path); }; \ No newline at end of file diff --git a/webserv/handler/Errorhandler.cpp b/webserv/handler/Errorhandler.cpp index 101ad9b..f7db9fa 100644 --- a/webserv/handler/Errorhandler.cpp +++ b/webserv/handler/Errorhandler.cpp @@ -1,3 +1,5 @@ +#include "webserv/http/HttpResponse.hpp" + #include // for AConfig #include // for ConfigManager #include // for GlobalConfig @@ -5,43 +7,39 @@ #include // for StatusCodeInfo, CRLF, DOUBLE_CRLF, INTERNAL_SERVER_ERROR, statusCodeInfos #include // for Log -#include // for array -#include // for basic_ifstream, basic_filebuf, basic_ostream::operator<<, ifstream, stringstream -#include // for basic_stringstream -#include // for basic_string, operator+, allocator, char_traits, string, to_string -#include // for string_view +#include // for basic_ifstream, basic_filebuf, basic_ostream::operator<<, ifstream, stringstream +#include // for basic_stringstream +#include // for basic_string, operator+, allocator, char_traits, string, to_string -std::string ErrorHandler::getErrorResponse(int statusCode, AConfig *config) +HttpResponse ErrorHandler::getErrorResponse(int statusCode, AConfig *config) { + HttpResponse response; + std::string body = generateErrorPage(statusCode, config); - Log::debug("Generated error page : " + generateErrorHeader(statusCode, body) + body); - return generateErrorHeader(statusCode, body) + body; -} - -std::string ErrorHandler::generateErrorHeader(int statusCode, const std::string &body) -{ - std::string response = "HTTP/1.1 "; - response += std::to_string(statusCode) + " "; - response += std::string(getStatusMessage(statusCode)) + std::string(Http::Protocol::CRLF); - response += "Content-Type: text/html" + std::string(Http::Protocol::CRLF); - response += - "Content-Length: " + std::to_string(body.size()) + std::string(Http::Protocol::DOUBLE_CRLF); // End of headers + response.appendBody(body); + response.setStatus(statusCode); + response.addHeader("Content-Type", "text/html"); + response.addHeader("Connection", "close"); return response; } std::string ErrorHandler::generateErrorPage(int statusCode, AConfig *config) { - - if (config != nullptr) + Log::trace(LOCATION); + if (config == nullptr) { config = ConfigManager::getInstance().getGlobalConfig(); + Log::debug("Using global config for error page generation"); + } + if (config != nullptr) + { Log::info("Checking for custom error page for status code: " + std::to_string(statusCode)); std::string customPage = config->getErrorPage(statusCode); if (!customPage.empty()) { return getErrorPageFile(customPage); } - Log::warning("No custom error page foundin config for status code: " + std::to_string(statusCode)); + Log::warning("No custom error page found in config for status code: " + std::to_string(statusCode)); } return generateDefaultErrorPage(statusCode); } @@ -49,24 +47,11 @@ std::string ErrorHandler::generateErrorPage(int statusCode, AConfig *config) std::string ErrorHandler::generateDefaultErrorPage(int statusCode) { Log::info("Generating default error page for status code: " + std::to_string(statusCode)); - - std::string_view statusMessage = getStatusMessage(statusCode); - std::string html = "" + std::to_string(statusCode) + " " + std::string(statusMessage) + - "

" + std::to_string(statusCode) + " " + std::string(statusMessage) + + std::string statusMessage = Http::getStatusCodeReason(statusCode); + std::string html = "" + std::to_string(statusCode) + " " + statusMessage + + "

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


webserv

"; - return generateErrorHeader(statusCode, html) + html; -} - -std::string_view ErrorHandler::getStatusMessage(int statusCode) -{ - for (const auto info : Http::statusCodeInfos) - { - if (info.code == statusCode) - { - return info.reason; - } - } - return "Unknown Status"; + return html; } std::string ErrorHandler::getErrorPageFile(const std::string &path) diff --git a/webserv/http/HttpHeaders.hpp b/webserv/http/HttpHeaders.hpp index d1bdfbc..bf61e3e 100644 --- a/webserv/http/HttpHeaders.hpp +++ b/webserv/http/HttpHeaders.hpp @@ -18,15 +18,6 @@ class HttpHeaders { public: - HttpHeaders() = default; - - HttpHeaders(const HttpHeaders &other) = delete; - HttpHeaders(HttpHeaders &&other) noexcept = delete; - HttpHeaders &operator=(const HttpHeaders &other) = delete; - HttpHeaders &operator=(HttpHeaders &&other) noexcept = delete; - - ~HttpHeaders() = default; - const std::string &get(const std::string &name) const; bool has(const std::string &name) const; diff --git a/webserv/http/HttpResponse.cpp b/webserv/http/HttpResponse.cpp index 0b3486a..244b165 100644 --- a/webserv/http/HttpResponse.cpp +++ b/webserv/http/HttpResponse.cpp @@ -5,7 +5,7 @@ #include #include -HttpResponse::HttpResponse(Client *client) : client_(client), headers_(std::make_unique()) {} +HttpResponse::HttpResponse() : headers_(std::make_unique()) {} void HttpResponse::addHeader(const std::string &key, const std::string &value) { @@ -22,11 +22,33 @@ void HttpResponse::appendBody(const std::string &body) body_.insert(body_.end(), body.begin(), body.end()); } +void HttpResponse::setBody(const std::vector &data) +{ + body_ = data; + setComplete(); +} + +void HttpResponse::setBody(const std::string &body) +{ + body_.assign(body.begin(), body.end()); + setComplete(); +} + void HttpResponse::setStatus(int statusCode) { statusCode_ = statusCode; } +void HttpResponse::setComplete() +{ + complete_ = true; +} + +bool HttpResponse::isComplete() const +{ + return complete_; +} + const HttpHeaders &HttpResponse::getHeaders() const { return *headers_; diff --git a/webserv/http/HttpResponse.hpp b/webserv/http/HttpResponse.hpp index 45ecef5..c537cbe 100644 --- a/webserv/http/HttpResponse.hpp +++ b/webserv/http/HttpResponse.hpp @@ -12,12 +12,12 @@ class Client; class HttpResponse { public: - HttpResponse(Client *client); + HttpResponse(); - HttpResponse(const HttpResponse &other) = delete; // Disable copy constructor - HttpResponse &operator=(const HttpResponse &other) = delete; // Disable copy assignment - HttpResponse(HttpResponse &&other) noexcept = delete; // Move constructor - HttpResponse &operator=(HttpResponse &&other) noexcept = delete; // Move assignment + HttpResponse(const HttpResponse &other) = delete; // Disable copy constructor + HttpResponse &operator=(const HttpResponse &other) = delete; // Disable copy assignment + HttpResponse(HttpResponse &&other) noexcept = default; // Move constructor + HttpResponse &operator=(HttpResponse &&other) noexcept = default; // Move assignment ~HttpResponse() = default; @@ -26,6 +26,9 @@ class HttpResponse void appendBody(const std::vector &data); void appendBody(const std::string &body); + void setBody(const std::vector &data); + void setBody(const std::string &body); + void setComplete(); void setStatus(int statusCode); @@ -40,7 +43,6 @@ class HttpResponse [[nodiscard]] std::string getStatusLine() const; [[nodiscard]] std::string getContentLength() const; - Client *client_; std::vector body_; std::unique_ptr headers_; bool complete_ = false;