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/client/Client.hpp>
|
||||||
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
#include <webserv/http/HttpHeaders.hpp> // for HttpHeaders
|
||||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||||
@ -13,9 +14,9 @@
|
|||||||
|
|
||||||
class ServerConfig;
|
class ServerConfig;
|
||||||
|
|
||||||
Client::Client(std::unique_ptr<Socket> socket, Server &server, const ServerConfig &server_config)
|
Client::Client(std::unique_ptr<Socket> socket, Server &server)
|
||||||
: client_socket_(std::move(socket)), server_(std::ref(server)), server_config_(std::cref(server_config)),
|
: client_socket_(std::move(socket)), server_(std::ref(server)),
|
||||||
httpRequest_(std::make_unique<HttpRequest>(&server_config, this))
|
httpRequest_(std::make_unique<HttpRequest>(this))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +26,16 @@ Client::~Client()
|
|||||||
server_.removeFromEpoll(*client_socket_);
|
server_.removeFromEpoll(*client_socket_);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int Client::getStatusCode() const
|
||||||
|
{
|
||||||
|
return statusCode_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::setStatusCode(int code)
|
||||||
|
{
|
||||||
|
statusCode_ = code;
|
||||||
|
}
|
||||||
|
|
||||||
void Client::request()
|
void Client::request()
|
||||||
{
|
{
|
||||||
char buffer[bufferSize_] = {}; // NOLINT(cppcoreguidelines-avoid-c-arrays)
|
char buffer[bufferSize_] = {}; // NOLINT(cppcoreguidelines-avoid-c-arrays)
|
||||||
@ -56,6 +67,13 @@ void Client::request()
|
|||||||
{"body", httpRequest_->getBody()},
|
{"body", httpRequest_->getBody()},
|
||||||
{"state", std::to_string(static_cast<uint8_t>(httpRequest_->getState()))},
|
{"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());
|
server_.responseReady(client_socket_->getFd());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -79,10 +97,16 @@ std::string Client::getResponse() const
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
response += "200 OK\r\n";
|
response += "200 OK\r\n";
|
||||||
}
|
|
||||||
// further validation can be added here
|
// 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);
|
Log::debug("Sending response:\n" + response);
|
||||||
return response;
|
return response;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
||||||
|
#include <webserv/http/HttpConstants.hpp> // for StatusCode, HTTP
|
||||||
#include <webserv/http/HttpRequest.hpp> // for HttpRequest
|
#include <webserv/http/HttpRequest.hpp> // for HttpRequest
|
||||||
#include <webserv/server/Server.hpp>
|
#include <webserv/server/Server.hpp>
|
||||||
#include <webserv/socket/Socket.hpp>
|
#include <webserv/socket/Socket.hpp>
|
||||||
@ -16,7 +17,7 @@ class ServerConfig;
|
|||||||
class Client
|
class Client
|
||||||
{
|
{
|
||||||
public:
|
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(const Client &other) = delete; // Disable copy constructor
|
||||||
Client &operator=(const Client &other) = delete; // Disable copy assignment
|
Client &operator=(const Client &other) = delete; // Disable copy assignment
|
||||||
@ -28,10 +29,14 @@ class Client
|
|||||||
void request();
|
void request();
|
||||||
[[nodiscard]] std::string getResponse() const;
|
[[nodiscard]] std::string getResponse() const;
|
||||||
|
|
||||||
|
[[nodiscard]] int getStatusCode() const;
|
||||||
|
void setStatusCode(int code);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
int statusCode_ = Http::StatusCode::OK;
|
||||||
constexpr static size_t bufferSize_ = 4096;
|
constexpr static size_t bufferSize_ = 4096;
|
||||||
std::unique_ptr<HttpRequest> httpRequest_ = nullptr;
|
std::unique_ptr<HttpRequest> httpRequest_ = nullptr;
|
||||||
std::unique_ptr<Socket> client_socket_;
|
std::unique_ptr<Socket> client_socket_;
|
||||||
const Server &server_;
|
Server &server_;
|
||||||
const ServerConfig &server_config_;
|
mutable const ServerConfig *server_config_ = nullptr;
|
||||||
};
|
};
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include "webserv/config/ServerConfig.hpp"
|
||||||
#include <webserv/config/ConfigManager.hpp>
|
#include <webserv/config/ConfigManager.hpp>
|
||||||
#include <webserv/config/GlobalConfig.hpp> // for GlobalConfig
|
#include <webserv/config/GlobalConfig.hpp> // for GlobalConfig
|
||||||
#include <webserv/config/utils.hpp> // for removeComments
|
#include <webserv/config/utils.hpp> // for removeComments
|
||||||
@ -60,3 +61,38 @@ std::vector<ServerConfig *> ConfigManager::getServerConfigs() const
|
|||||||
}
|
}
|
||||||
return globalConfig_->getServerConfigs();
|
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();
|
static ConfigManager &getInstance();
|
||||||
|
|
||||||
[[nodiscard]] std::vector<ServerConfig *> getServerConfigs() const;
|
[[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:
|
private:
|
||||||
bool initialized_;
|
bool initialized_;
|
||||||
|
|||||||
@ -38,7 +38,7 @@ class ADirective
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string name_;
|
std::string name_; //NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Non-member stream operator for ADirective
|
// Non-member stream operator for ADirective
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class DirectiveFactory
|
|||||||
constexpr static std::array<DirectiveInfo, 15> supportedDirectives = {{
|
constexpr static std::array<DirectiveInfo, 15> supportedDirectives = {{
|
||||||
{.name = "listen", .type = "IntDirective", .context = "SL"},
|
{.name = "listen", .type = "IntDirective", .context = "SL"},
|
||||||
{.name = "host", .type = "StringDirective", .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 = "root", .type = "StringDirective", .context = "SL"},
|
||||||
{.name = "index", .type = "VectorDirective", .context = "SL"},
|
{.name = "index", .type = "VectorDirective", .context = "SL"},
|
||||||
{.name = "error_page", .type = "IntStringDirective", .context = "SL"},
|
{.name = "error_page", .type = "IntStringDirective", .context = "SL"},
|
||||||
|
|||||||
@ -1 +1,11 @@
|
|||||||
#pragma once
|
#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/config/utils.hpp> // for stoul
|
||||||
#include <webserv/http/HttpConstants.hpp> // for CRLF, DOUBLE_CRLF
|
#include <webserv/http/HttpConstants.hpp> // for CRLF, DOUBLE_CRLF
|
||||||
#include <webserv/http/HttpRequest.hpp>
|
#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 <map> // for map
|
||||||
#include <optional> // for optional
|
#include <optional> // for optional
|
||||||
@ -11,8 +13,7 @@
|
|||||||
|
|
||||||
class ServerConfig;
|
class ServerConfig;
|
||||||
|
|
||||||
HttpRequest::HttpRequest(const ServerConfig *serverConfig, const Client *client)
|
HttpRequest::HttpRequest(Client *client) : client_(client)
|
||||||
: serverConfig_(serverConfig), client_(client)
|
|
||||||
{
|
{
|
||||||
Log::trace(LOCATION);
|
Log::trace(LOCATION);
|
||||||
}
|
}
|
||||||
@ -28,6 +29,11 @@ HttpRequest::State HttpRequest::getState() const
|
|||||||
return state_;
|
return state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HttpRequest::setState(State state)
|
||||||
|
{
|
||||||
|
state_ = state;
|
||||||
|
}
|
||||||
|
|
||||||
const HttpHeaders &HttpRequest::getHeaders() const
|
const HttpHeaders &HttpRequest::getHeaders() const
|
||||||
{
|
{
|
||||||
return headers_;
|
return headers_;
|
||||||
@ -80,7 +86,10 @@ void HttpRequest::parseBuffer()
|
|||||||
case State::Complete:
|
case State::Complete:
|
||||||
Log::debug("HttpRequest::parseBuffer() request is complete");
|
Log::debug("HttpRequest::parseBuffer() request is complete");
|
||||||
return; // 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 (...)
|
catch (...)
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class HttpRequest
|
|||||||
ParseError
|
ParseError
|
||||||
};
|
};
|
||||||
|
|
||||||
HttpRequest(const ServerConfig *serverConfig, const Client *client);
|
HttpRequest(Client *client);
|
||||||
|
|
||||||
HttpRequest(const HttpRequest &other) = delete;
|
HttpRequest(const HttpRequest &other) = delete;
|
||||||
HttpRequest(HttpRequest &&other) noexcept = delete;
|
HttpRequest(HttpRequest &&other) noexcept = delete;
|
||||||
@ -32,6 +32,7 @@ class HttpRequest
|
|||||||
~HttpRequest();
|
~HttpRequest();
|
||||||
|
|
||||||
[[nodiscard]] State getState() const;
|
[[nodiscard]] State getState() const;
|
||||||
|
void setState(State state);
|
||||||
[[nodiscard]] const HttpHeaders &getHeaders() const;
|
[[nodiscard]] const HttpHeaders &getHeaders() const;
|
||||||
[[nodiscard]] const std::string &getBody() const;
|
[[nodiscard]] const std::string &getBody() const;
|
||||||
|
|
||||||
@ -54,8 +55,7 @@ class HttpRequest
|
|||||||
|
|
||||||
void parseContentLength();
|
void parseContentLength();
|
||||||
|
|
||||||
const ServerConfig *serverConfig_;
|
Client *client_;
|
||||||
const Client *client_;
|
|
||||||
|
|
||||||
State state_ = State::RequestLine;
|
State state_ = State::RequestLine;
|
||||||
|
|
||||||
|
|||||||
@ -23,12 +23,12 @@ int main(int argc, char **argv)
|
|||||||
Log::info("ConfigManager initialized successfully.");
|
Log::info("ConfigManager initialized successfully.");
|
||||||
|
|
||||||
|
|
||||||
auto serverConfigs = configManager.getServerConfigs();
|
// auto serverConfigs = configManager.getServerConfigs();
|
||||||
auto *firstServer = serverConfigs[0];
|
// auto *firstServer = serverConfigs[0];
|
||||||
const auto *location = firstServer->getLocation("/");
|
// const auto *location = firstServer->getLocation("/");
|
||||||
const auto *listenDirective = location->getDirective("listen");
|
// const auto *listenDirective = location->getDirective("listen");
|
||||||
int listenPort = listenDirective->getValueAs<int>();
|
// int listenPort = listenDirective->getValueAs<int>();
|
||||||
Log::warning("Listen port for '/' location: " + std::to_string(listenPort));
|
// 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();
|
std::unique_ptr<Socket> clientSocket = listener.accept();
|
||||||
addToEpoll(*clientSocket, EPOLLIN);
|
addToEpoll(*clientSocket, EPOLLIN);
|
||||||
clients_.insert(
|
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
|
Socket &Server::getListener(int fd) const
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user