feat: implement router request handling and error management
This commit is contained in:
parent
e1acf5b515
commit
927b9549c2
@ -1,4 +1,5 @@
|
||||
#include "webserv/http/HttpConstants.hpp"
|
||||
|
||||
#include <webserv/client/Client.hpp>
|
||||
#include <webserv/config/ConfigManager.hpp> // for ConfigManager
|
||||
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
||||
@ -75,14 +76,14 @@ void Client::request()
|
||||
{"body", httpRequest_->getBody()},
|
||||
{"state", std::to_string(static_cast<uint8_t>(httpRequest_->getState()))},
|
||||
});
|
||||
server_config_ =
|
||||
ConfigManager::getInstance().getMatchingServerConfig(httpRequest_->getHeaders().getHost().value_or(""));
|
||||
if (server_config_ == nullptr)
|
||||
{
|
||||
Log::warning("No matching server config found for Host: " +
|
||||
httpRequest_->getHeaders().getHost().value_or("unknown host"));
|
||||
setError(Http::StatusCode::BAD_REQUEST);
|
||||
}
|
||||
// server_config_ =
|
||||
// ConfigManager::getInstance().getMatchingServerConfig(httpRequest_->getHeaders().getHost().value_or(""));
|
||||
// if (server_config_ == nullptr)
|
||||
// {
|
||||
// Log::warning("No matching server config found for Host: " +
|
||||
// httpRequest_->getHeaders().getHost().value_or("unknown host"));
|
||||
// setError(Http::StatusCode::BAD_REQUEST);
|
||||
// }
|
||||
|
||||
// Example usage, replace with actual host and port extraction from request
|
||||
server_.responseReady(client_socket_->getFd());
|
||||
@ -107,23 +108,23 @@ bool Client::isResponseReady() const
|
||||
std::vector<uint8_t> Client::getResponse() const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
Log::trace(LOCATION);
|
||||
if (statusCode_ == Http::StatusCode::OK)
|
||||
{
|
||||
httpResponse_->setStatus(200);
|
||||
httpResponse_->addHeader("Content-Type", "text/plain");
|
||||
httpResponse_->appendBody("Hello, World!\n");
|
||||
}
|
||||
return httpResponse_->toBytes();
|
||||
// if (statusCode_ != Http::StatusCode::OK)
|
||||
// {
|
||||
// return httpResponse_->toBytes();
|
||||
// }
|
||||
|
||||
const Router &router = server_.getRouter();
|
||||
auto response = router.handleRequest(*httpRequest_);
|
||||
return response.toBytes();
|
||||
}
|
||||
|
||||
void Client::setError(int statusCode)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
statusCode_ = statusCode;
|
||||
Log::debug("Setting error response with status code: " + std::to_string(statusCode));
|
||||
auto errorResponse = std::make_unique<HttpResponse>(
|
||||
ErrorHandler::getErrorResponse(statusCode, const_cast<ServerConfig *>(server_config_)));
|
||||
httpResponse_ = std::move(errorResponse);
|
||||
Log::debug("Error response set successfully");
|
||||
}
|
||||
// void Client::setError(int statusCode)
|
||||
// {
|
||||
// Log::trace(LOCATION);
|
||||
// statusCode_ = statusCode;
|
||||
// Log::debug("Setting error response with status code: " + std::to_string(statusCode));
|
||||
// auto errorResponse = std::make_unique<HttpResponse>(
|
||||
// ErrorHandler::getErrorResponse(statusCode, const_cast<ServerConfig *>(server_config_)));
|
||||
// httpResponse_ = std::move(errorResponse);
|
||||
// Log::debug("Error response set successfully");
|
||||
// }
|
||||
|
||||
@ -39,7 +39,7 @@ class Client
|
||||
[[nodiscard]] int getStatusCode() const;
|
||||
|
||||
[[nodiscard]] Socket &getSocket() const { return *client_socket_; }
|
||||
void setError(int statusCode);
|
||||
// void setError(int statusCode);
|
||||
|
||||
void setStatusCode(int code);
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
#include <webserv/config/LocationConfig.hpp>
|
||||
|
||||
#include <webserv/config/AConfig.hpp> // for AConfig
|
||||
#include <webserv/config/LocationConfig.hpp>
|
||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||
|
||||
LocationConfig::LocationConfig(const std::string &block, const AConfig *parent) : AConfig(parent)
|
||||
LocationConfig::LocationConfig(const std::string &block, const std::string &path, const AConfig *parent)
|
||||
: AConfig(parent), _path(path)
|
||||
{
|
||||
parseBlock(block);
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ class LocationConfig : public AConfig
|
||||
{
|
||||
public:
|
||||
LocationConfig() = delete;
|
||||
LocationConfig(const std::string &Block, const AConfig *parent = nullptr);
|
||||
LocationConfig(const std::string &Block, const std::string &path, const AConfig *parent = nullptr);
|
||||
|
||||
LocationConfig(const LocationConfig &other) = delete;
|
||||
LocationConfig &operator=(const LocationConfig &other) = delete;
|
||||
@ -17,6 +17,9 @@ class LocationConfig : public AConfig
|
||||
|
||||
~LocationConfig() override = default;
|
||||
|
||||
[[nodiscard]] const std::string &getPath() const { return _path; }
|
||||
|
||||
private:
|
||||
void parseBlock(const std::string &block) override;
|
||||
std::string _path;
|
||||
};
|
||||
@ -1,7 +1,6 @@
|
||||
#include <webserv/config/ServerConfig.hpp>
|
||||
|
||||
#include <webserv/config/AConfig.hpp> // for AConfig
|
||||
#include <webserv/config/LocationConfig.hpp> // for LocationConfig
|
||||
#include <webserv/config/ServerConfig.hpp>
|
||||
#include <webserv/config/utils.hpp> // for findCorrespondingClosingBrace, trim
|
||||
#include <webserv/log/Log.hpp> // for Log, LOCATION
|
||||
|
||||
@ -44,7 +43,7 @@ void ServerConfig::parseBlock(const std::string &block)
|
||||
}
|
||||
// Optionally parse the server block here
|
||||
std::string locationBlock = block.substr(bracePos + 1, closeBrace - bracePos - 1);
|
||||
locations_[locationPath] = std::make_unique<LocationConfig>(locationBlock, this);
|
||||
locations_[locationPath] = std::make_unique<LocationConfig>(locationBlock, locationPath, this);
|
||||
Log::debug("Added location: " + locationPath, {{"block", locationBlock}});
|
||||
pos = closeBrace + 1;
|
||||
}
|
||||
|
||||
@ -1,3 +1,81 @@
|
||||
#include "webserv/config/AConfig.hpp"
|
||||
#include "webserv/config/ConfigManager.hpp"
|
||||
#include "webserv/config/ServerConfig.hpp"
|
||||
#include "webserv/handler/ErrorHandler.hpp"
|
||||
#include "webserv/http/HttpResponse.hpp"
|
||||
#include "webserv/log/Log.hpp"
|
||||
|
||||
#include <webserv/router/Router.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
Router::Router() {}
|
||||
|
||||
HttpResponse Router::handleRequest(const HttpRequest &request) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
|
||||
ServerConfig *config =
|
||||
ConfigManager::getInstance().getMatchingServerConfig(request.getHeaders().getHost().value_or(""));
|
||||
HttpResponse response;
|
||||
|
||||
if (config == nullptr)
|
||||
{
|
||||
Log::warning("No matching server config found");
|
||||
handleError(400, response);
|
||||
return response;
|
||||
}
|
||||
|
||||
const std::string &target = request.getTarget();
|
||||
const std::string &method = request.getMethod();
|
||||
|
||||
const LocationConfig *location = getLocation(target, *config);
|
||||
if (location == nullptr)
|
||||
{
|
||||
Log::warning("No matching location found for target: " + target);
|
||||
handleError(404, response, config);
|
||||
return response;
|
||||
}
|
||||
|
||||
response.setStatus(200);
|
||||
response.addHeader("Content-Type", "text/plain");
|
||||
response.setBody("Hello, World! You requested " + target + " on " + request.getHeaders().getHost().value_or("") +
|
||||
". Current resource is " + location->getPath());
|
||||
response.setComplete();
|
||||
return response;
|
||||
}
|
||||
|
||||
void Router::handleError(int statusCode, HttpResponse &response, AConfig *config) const
|
||||
{
|
||||
response = ErrorHandler::getErrorResponse(statusCode, config);
|
||||
response.setComplete();
|
||||
}
|
||||
|
||||
const LocationConfig *Router::getLocation(const std::string &path, const ServerConfig &serverConfig) const
|
||||
{
|
||||
const LocationConfig *bestMatch = nullptr;
|
||||
size_t maxSize = 0;
|
||||
|
||||
std::vector<std::string> locations = serverConfig.getLocationPaths();
|
||||
|
||||
for (const auto &locPath : locations)
|
||||
{
|
||||
if (!path.starts_with(locPath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (locPath.length() > maxSize &&
|
||||
(path.length() == locPath.length() || locPath.back() == '/' || path[locPath.length()] == '/'))
|
||||
{
|
||||
maxSize = locPath.length();
|
||||
bestMatch = serverConfig.getLocation(locPath);
|
||||
Log::debug("Found new best match: " + locPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (bestMatch == nullptr)
|
||||
{
|
||||
Log::warning("No location matched for path: " + path);
|
||||
}
|
||||
return bestMatch;
|
||||
}
|
||||
@ -1,10 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "webserv/config/LocationConfig.hpp"
|
||||
|
||||
#include <webserv/http/HttpRequest.hpp>
|
||||
#include <webserv/http/HttpResponse.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
class Router
|
||||
{
|
||||
public:
|
||||
Router();
|
||||
|
||||
[[nodiscard]] HttpResponse handleRequest(const HttpRequest &request) const;
|
||||
|
||||
private:
|
||||
void handleError(int statusCode, HttpResponse &response, AConfig *config = nullptr) const;
|
||||
[[nodiscard]] const LocationConfig *getLocation(const std::string &path, const ServerConfig &serverConfig) const;
|
||||
};
|
||||
@ -20,7 +20,8 @@
|
||||
#include <sys/types.h> // for ssize_t
|
||||
#include <unistd.h> // for close
|
||||
|
||||
Server::Server(const ConfigManager &configManager) : epoll_fd_(epoll_create1(0)), configManager_(configManager)
|
||||
Server::Server(const ConfigManager &configManager)
|
||||
: epoll_fd_(epoll_create1(0)), configManager_(configManager), router_()
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
const auto &serverConfigs = configManager.getServerConfigs();
|
||||
@ -230,3 +231,8 @@ void Server::eventLoop()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Router &Server::getRouter() const
|
||||
{
|
||||
return router_;
|
||||
}
|
||||
@ -1,16 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "webserv/router/Router.hpp"
|
||||
|
||||
#include <webserv/client/Client.hpp>
|
||||
#include <webserv/config/ConfigManager.hpp>
|
||||
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
||||
#include <webserv/socket/Socket.hpp> // for Socket
|
||||
|
||||
#include <cstdint> // for uint32_t
|
||||
|
||||
#include <memory> // for unique_ptr
|
||||
#include <set> // for set
|
||||
#include <unordered_map> // for unordered_map
|
||||
#include <vector> // for vector
|
||||
#include <set> // for set
|
||||
|
||||
class Client;
|
||||
class ConfigManager;
|
||||
@ -41,13 +42,15 @@ class Server
|
||||
void handleRequest(struct epoll_event *event) const;
|
||||
void responseReady(int client_fd) const;
|
||||
void eventLoop();
|
||||
|
||||
Socket &getListener(int fd) const;
|
||||
Client &getClient(int fd) const;
|
||||
|
||||
const Router &getRouter() const;
|
||||
|
||||
private:
|
||||
int epoll_fd_;
|
||||
const ConfigManager &configManager_;
|
||||
const Router router_;
|
||||
std::vector<std::unique_ptr<Socket>> listeners_;
|
||||
std::set<int> listener_fds_;
|
||||
std::unordered_map<int, std::unique_ptr<Client>> clients_;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user