refactor: simplify Client and HttpRequest constructors, add status code management
This commit is contained in:
parent
ae1b10c60b
commit
787432ff0c
@ -1,3 +1,4 @@
|
||||
#include "webserv/config/ConfigManager.hpp"
|
||||
#include <webserv/client/Client.hpp>
|
||||
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||
@ -13,9 +14,9 @@
|
||||
|
||||
class ServerConfig;
|
||||
|
||||
Client::Client(std::unique_ptr<Socket> 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<HttpRequest>(&server_config, this))
|
||||
Client::Client(std::unique_ptr<Socket> socket, Server &server)
|
||||
: client_socket_(std::move(socket)), server_(std::ref(server)),
|
||||
httpRequest_(std::make_unique<HttpRequest>(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<uint8_t>(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<std::string>("server_name");
|
||||
auto port = server_config_->getDirectiveValue<int>("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;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
||||
#include <webserv/http/HttpConstants.hpp> // for StatusCode, HTTP
|
||||
#include <webserv/http/HttpRequest.hpp> // for HttpRequest
|
||||
#include <webserv/server/Server.hpp>
|
||||
#include <webserv/socket/Socket.hpp>
|
||||
@ -16,7 +17,7 @@ class ServerConfig;
|
||||
class Client
|
||||
{
|
||||
public:
|
||||
Client(std::unique_ptr<Socket> socket, Server &server, const ServerConfig &server_config);
|
||||
Client(std::unique_ptr<Socket> 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> httpRequest_ = nullptr;
|
||||
std::unique_ptr<Socket> client_socket_;
|
||||
const Server &server_;
|
||||
const ServerConfig &server_config_;
|
||||
Server &server_;
|
||||
mutable const ServerConfig *server_config_ = nullptr;
|
||||
};
|
||||
@ -1,3 +1,4 @@
|
||||
#include "webserv/config/ServerConfig.hpp"
|
||||
#include <webserv/config/ConfigManager.hpp>
|
||||
#include <webserv/config/GlobalConfig.hpp> // for GlobalConfig
|
||||
#include <webserv/config/utils.hpp> // for removeComments
|
||||
@ -60,3 +61,38 @@ std::vector<ServerConfig *> ConfigManager::getServerConfigs() const
|
||||
}
|
||||
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<ServerConfig *> serverConfigs = globalConfig_->getServerConfigs();
|
||||
for (ServerConfig *serverConfig : serverConfigs)
|
||||
{
|
||||
auto serverName = serverConfig->getDirectiveValue<std::string>("server_name", "");
|
||||
auto listenPorts = serverConfig->getDirectiveValue<int>("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;
|
||||
}
|
||||
@ -22,6 +22,9 @@ class ConfigManager
|
||||
static ConfigManager &getInstance();
|
||||
|
||||
[[nodiscard]] std::vector<ServerConfig *> 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_;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -29,7 +29,7 @@ class DirectiveFactory
|
||||
constexpr static std::array<DirectiveInfo, 15> 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"},
|
||||
|
||||
@ -1 +1,11 @@
|
||||
#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);
|
||||
|
||||
// };
|
||||
19
webserv/handler/Errorhandler.cpp
Normal file
19
webserv/handler/Errorhandler.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
#include <webserv/handler/ErrorHandler.hpp>
|
||||
|
||||
#include <webserv/http/HttpConstants.hpp> // for StatusCode
|
||||
#include <webserv/config/AConfig.hpp>
|
||||
#include <webserv/log/Log.hpp>
|
||||
|
||||
|
||||
|
||||
// std::string ErrorHandler::generateErrorPage(int statusCode, AConfig *config)
|
||||
// {
|
||||
|
||||
// std::string statusMessage = getStatusMessage(statusCode);
|
||||
// std::string html =
|
||||
// "<html><head><title>" + std::to_string(statusCode) + " " + statusMessage +
|
||||
// "</title></head><body><h1>" + std::to_string(statusCode) + " " + statusMessage +
|
||||
// "</h1><hr><p>webserv</p></body></html>";
|
||||
// return html;
|
||||
// }
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
#include <webserv/config/utils.hpp> // for stoul
|
||||
#include <webserv/http/HttpConstants.hpp> // for CRLF, DOUBLE_CRLF
|
||||
#include <webserv/http/HttpRequest.hpp>
|
||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||
#include <webserv/client/Client.hpp> // for Client
|
||||
|
||||
|
||||
#include <map> // for map
|
||||
#include <optional> // 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 (...)
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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<int>();
|
||||
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<int>();
|
||||
// Log::warning("Listen port for '/' location: " + std::to_string(listenPort));
|
||||
|
||||
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ void Server::handleConnection(struct epoll_event *event)
|
||||
std::unique_ptr<Socket> clientSocket = listener.accept();
|
||||
addToEpoll(*clientSocket, EPOLLIN);
|
||||
clients_.insert(
|
||||
{clientSocket->getFd(), std::make_unique<Client>(std::move(clientSocket), *this, getConfig(listener))});
|
||||
{clientSocket->getFd(), std::make_unique<Client>(std::move(clientSocket), *this)});
|
||||
}
|
||||
|
||||
Socket &Server::getListener(int fd) const
|
||||
|
||||
Loading…
Reference in New Issue
Block a user