From 935837004417c82f858e1aa848ee267b941b473d Mon Sep 17 00:00:00 2001 From: Quinten Date: Mon, 27 Oct 2025 09:25:26 +0100 Subject: [PATCH] extend validation logic --- webserv/client/Client.cpp | 15 ++++++++++++--- webserv/http/RequestValidator.cpp | 12 ++++++++++++ webserv/http/RequestValidator.hpp | 16 +++++++++++++++- webserv/router/Router.cpp | 17 +++-------------- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/webserv/client/Client.cpp b/webserv/client/Client.cpp index 5a0c4ca..ac179e9 100644 --- a/webserv/client/Client.cpp +++ b/webserv/client/Client.cpp @@ -1,3 +1,5 @@ +#include "webserv/http/RequestValidator.hpp" + #include #include // for CgiHandler #include // for ErrorHandler @@ -93,15 +95,22 @@ void Client::request() try { - // Thoughts: if a handler isn't returned, this could because of the error handler already setting up the response - // so, maybe we don't need to throw a 500 when no handler. Because that would override the actual error response. - // How about the router, or a handler, throws an exception if something goes wrong, and we catch it here to make a 500 response? + // Thoughts: if a handler isn't returned, this could because of the error handler already setting up the + // response so, maybe we don't need to throw a 500 when no handler. Because that would override the actual + // error response. How about the router, or a handler, throws an exception if something goes wrong, and we + // catch it here to make a 500 response? handler_ = router_->handleRequest(); if (handler_ != nullptr) { handler_->handle(); } } + catch (const RequestValidator::ValidationException &e) + { + Log::error("Exception during request handling: " + std::string(e.what())); + ErrorHandler::createErrorResponse(e.code(), *httpResponse_); + return; + } catch (const std::exception &e) { Log::error("Exception during request handling: " + std::string(e.what())); diff --git a/webserv/http/RequestValidator.cpp b/webserv/http/RequestValidator.cpp index 7ee1055..f2e5db7 100644 --- a/webserv/http/RequestValidator.cpp +++ b/webserv/http/RequestValidator.cpp @@ -65,3 +65,15 @@ std::optional RequestValidator::validateMetho } return ValidationError{405, "Method Not Allowed"}; } + +RequestValidator::ValidationException::ValidationException(int code) : code_(code){}; + +int RequestValidator::ValidationException::code() const noexcept +{ + return code_; +} + +const char *RequestValidator::ValidationException::what() const noexcept +{ + return "Request validation failed"; +} \ No newline at end of file diff --git a/webserv/http/RequestValidator.hpp b/webserv/http/RequestValidator.hpp index 961a720..d7031f3 100644 --- a/webserv/http/RequestValidator.hpp +++ b/webserv/http/RequestValidator.hpp @@ -1,9 +1,11 @@ #pragma once #include "webserv/config/AConfig.hpp" + #include #include +#include #include #include @@ -15,6 +17,18 @@ class RequestValidator int statusCode; std::string message; }; + + class ValidationException : public std::exception + { + public: + ValidationException(int code); + [[nodiscard]] const char *what() const noexcept override; + [[nodiscard]] int code() const noexcept; + + private: + int code_; + }; + RequestValidator(const AConfig *config, const HttpRequest *request); [[nodiscard]] std::optional validate() const; @@ -25,4 +39,4 @@ class RequestValidator [[nodiscard]] std::optional validateContentLength() const; [[nodiscard]] std::optional validateMethod() const; - }; \ No newline at end of file +}; \ No newline at end of file diff --git a/webserv/router/Router.cpp b/webserv/router/Router.cpp index 84c8dd5..302f8aa 100644 --- a/webserv/router/Router.cpp +++ b/webserv/router/Router.cpp @@ -1,4 +1,5 @@ #include "webserv/handler/ErrorHandler.hpp" +#include "webserv/http/RequestValidator.hpp" #include // for Client #include // for AConfig @@ -50,26 +51,15 @@ std::unique_ptr Router::handleRequest() return nullptr; } HttpResponse &response = client_->getHttpResponse(); - - // const std::string &target = request.getTarget(); - // static_cast(target); // Suppress unused variable warning - // const std::string &method = request.getMethod(); - const AConfig *config = request.getUri().getConfig(); + auto validator = std::make_unique(config, &request); auto error = validator->validate(); if (error.has_value()) { Log::warning("Request validation failed: " + error->message); - ErrorHandler::createErrorResponse(error->statusCode, response, config); - return nullptr; + throw RequestValidator::ValidationException{error->statusCode}; } - - // if (!isMethodSupported(method, *config)) - // { - // return nullptr; - // // return ErrorHandler::getErrorResponse(405, config); - // } if (request.getUri().isCgi()) { try @@ -80,7 +70,6 @@ std::unique_ptr Router::handleRequest() catch (const std::exception &e) { Log::error("CGI process failed: " + std::string(e.what())); - // return ErrorHandler::getErrorResponse(500, config); } } else