Refactor configuration handling and directive parsing

- Introduced AConfig class to handle common configuration functionalities.
- Added GlobalConfig class to manage multiple ServerConfig instances.
- Updated ServerConfig to utilize the new AConfig base class.
- Refactored directive parsing logic to improve clarity and maintainability.
- Enhanced utility functions for removing comments and empty lines from configuration blocks.
- Updated directive classes to use consistent naming for value retrieval methods.
- Improved logging for better traceability during configuration parsing.
- Removed unused includes and cleaned up code for better readability.
This commit is contained in:
whaffman 2025-09-26 18:06:37 +02:00
parent d3d1445264
commit c841142e79
38 changed files with 476 additions and 463 deletions

View File

@ -22,20 +22,20 @@ server {
location / {
autoindex off;
index index.html;
allow_methods GET POST DELETE;
allowed_methods GET POST DELETE;
}
location /uploads {
root /var/www/uploads;
autoindex on;
allow_methods GET POST;
allowed_methods GET POST;
}
location /images {
root /var/www/images;
autoindex off;
index index.jpg;
allow_methods GET;
allowed_methods GET;
}
cgi_pass /cgi-bin/;
@ -63,20 +63,20 @@ server {
location / {
autoindex off;
index index.html;
allow_methods GET POST DELETE;
allowed_methods GET POST DELETE;
}
location /2uploads {
root /var/www/uploads;
autoindex on;
allow_methods GET POST;
allowed_methods GET POST;
}
location /2images {
root /var/www/images;
autoindex off;
index index.jpg;
allow_methods GET;
allowed_methods GET;
}
cgi_pass /cgi-bin/;

View File

@ -4,11 +4,11 @@
#include <webserv/server/Server.hpp> // for Server
#include <webserv/socket/Socket.hpp> // for Socket
#include <cstdint> // for uint8_t
#include <functional> // for reference_wrapper, cref, ref
#include <map> // for map
#include <utility> // for pair, move
#include <cstdint> // for uint8_t
#include <sys/types.h> // for ssize_t
Client::Client(std::unique_ptr<Socket> socket, Server &server, const ServerConfig &server_config)

View File

@ -5,11 +5,10 @@
#include <webserv/server/Server.hpp>
#include <webserv/socket/Socket.hpp>
#include <cstddef> // for size_t
#include <memory> // for unique_ptr
#include <string> // for string
#include <cstddef> // for size_t
class Server;
class Socket;

View File

@ -0,0 +1,62 @@
#include <webserv/config/AConfig.hpp> // for AConfig
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <webserv/config/directive/DirectiveFactory.hpp> // for DirectiveFactory
#include <webserv/config/utils.hpp> // for trim
#include <webserv/log/Log.hpp> // for Log, LOCATION
AConfig::AConfig(const AConfig *parent) : parent_(parent) {}
void AConfig::addDirective(const std::string &line)
{
auto directive = DirectiveFactory::createDirective(line);
if (directive)
{
directives_[directive->getName()] = std::move(directive);
}
}
const ADirective *AConfig::getDirective(const std::string &name) const
{
auto it = directives_.find(name);
if (it != directives_.end())
{
return it->second.get();
}
if (parent_ != nullptr)
{
return parent_->getDirective(name);
}
return nullptr;
}
bool AConfig::hasDirective(const std::string &name) const
{
if (directives_.contains(name)) // NOLINT
{
return true;
}
if (parent_ != nullptr)
{
return parent_->hasDirective(name);
}
return false;
}
void AConfig::parseDirectives(const std::string &declarations)
{
Log::trace(LOCATION);
std::stringstream ss(declarations);
std::string line;
while (ss.good())
{
std::getline(ss, line);
line = utils::trim(line);
if (line.empty())
{
continue;
}
Log::info("Global Declaration: " + line);
auto directive = DirectiveFactory::createDirective(line);
directives_[directive->getName()] = std::move(directive);
}
}

View File

@ -0,0 +1,50 @@
#pragma once
#include "webserv/config/directive/DirectiveValue.hpp"
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <map>
#include <memory>
#include <string>
class AConfig
{
public:
AConfig() = default;
AConfig(const AConfig *parent);
AConfig(const AConfig &other) = delete;
AConfig &operator=(const AConfig &other) = delete;
AConfig(AConfig &&other) noexcept = delete;
AConfig &operator=(AConfig &&other) noexcept = delete;
virtual ~AConfig() = default;
void addDirective(const std::string &line);
[[nodiscard]] const ADirective *getDirective(const std::string &name) const;
[[nodiscard]] bool hasDirective(const std::string &name) const;
template <typename T> T getDirectiveValue(const std::string &name, const T &defaultValue = T{}) const
{
const auto *directive = getDirective(name);
if (!directive)
{
return defaultValue;
}
auto value = directive->getValue();
if (value.holds<T>())
{
return value.get<T>();
}
return defaultValue;
}
protected:
virtual void parseBlock(const std::string &block) = 0;
void parseDirectives(const std::string &declarations);
std::map<std::string, std::unique_ptr<ADirective>>
directives_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
const AConfig *parent_ = nullptr; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
};

View File

@ -2,13 +2,12 @@
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
#include <webserv/config/directive/DirectiveFactory.hpp> // for DirectiveFactory
#include <webserv/config/utils.hpp> // for trim, findCorrespondingClosingBrace, trimSemi
#include <webserv/log/Log.hpp> // for Log
#include <webserv/log/Log.hpp> // for Log, LOCATION
#include <cstddef> // for size_t
#include <fstream> // for basic_ifstream, basic_istream, basic_filebuf, basic_ostream::operator<<, ifstream, istringstream, stringstream
#include <fstream> // for basic_ifstream, basic_istream, basic_filebuf, basic_ostream::operator<<, stringstream, ifstream, istringstream
#include <sstream> // for basic_stringstream, basic_istringstream
#include <stdexcept> // for runtime_error
#include <string>
#include <string> // for basic_string, char_traits, string, operator+, to_string, getline, operator<=>
ConfigManager::ConfigManager() : initialized_(false) {}
@ -32,40 +31,6 @@ void ConfigManager::init(const std::string &filePath)
initialized_ = true;
}
void removeEmptyLines(std::string &str)
{
std::istringstream stream(str);
std::string line;
std::string result;
while (std::getline(stream, line))
{
if (!utils::trim(line).empty())
{
result += utils::trimSemi(utils::trim(line)) + '\n';
}
}
str = result;
}
void removeComments(std::string &str)
{
size_t pos = 0;
while ((pos = str.find('#', pos)) != std::string::npos)
{
size_t end = str.find('\n', pos);
if (end == std::string::npos)
{
str.erase(pos);
}
else
{
str.erase(pos, end - pos);
}
}
removeEmptyLines(str);
}
void ConfigManager::parseConfigFile(const std::string &filePath)
{
// Placeholder for actual file parsing logic
@ -81,56 +46,18 @@ void ConfigManager::parseConfigFile(const std::string &filePath)
std::stringstream buffer;
buffer << file.rdbuf();
std::string content = buffer.str();
removeComments(content);
utils::removeComments(content);
globalConfig_ = std::make_unique<GlobalConfig>(content);
std::string globalDeclarations;
Log::trace("Content before parsing servers:\n" + content);
size_t pos = 0;
while (true)
{
size_t serverPos = content.find("server", pos);
size_t bracePos = content.find('{', serverPos);
if (serverPos == std::string::npos || bracePos == std::string::npos)
{
// No more server blocks, remaining is global
globalDeclarations += content.substr(pos);
break;
}
// Add global declarations before this server block
globalDeclarations += content.substr(pos, serverPos - pos);
Log::trace(LOCATION, {{"pos", std::to_string(pos)},
{"serverPos", std::to_string(serverPos)},
{"globalDeclarations", globalDeclarations}});
size_t closeBrace = utils::findCorrespondingClosingBrace(content, bracePos);
if (closeBrace == std::string::npos)
{
throw std::runtime_error("Malformed block in config file.");
}
// Optionally parse the server block here
std::string serverBlock = content.substr(bracePos + 1, closeBrace - bracePos - 1);
serverConfigs_.emplace_back(serverBlock);
pos = closeBrace + 1;
}
parseGlobalDeclarations(globalDeclarations); // Implement this function to handle global config
// Implement this function to handle global config
file.close();
}
void ConfigManager::parseGlobalDeclarations(const std::string &declarations)
std::vector<ServerConfig *> ConfigManager::getServerConfigs() const
{
Log::trace(LOCATION);
std::stringstream ss(declarations);
std::string line;
while (ss.good())
if (!initialized_)
{
std::getline(ss, line);
line = utils::trim(line);
if (line.empty())
{
continue;
}
Log::info("Global Declaration: " + line);
auto directive = DirectiveFactory::createDirective(line);
globalDirectives_.push_back(std::move(directive));
throw std::runtime_error("ConfigManager is not initialized.");
}
return globalConfig_->getServerConfigs();
}

View File

@ -1,11 +1,13 @@
#pragma once
#include "webserv/config/directive/ADirective.hpp"
#include <webserv/config/ServerConfig.hpp>
#include <webserv/config/GlobalConfig.hpp>
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
#include <memory>
#include <string>
#include <vector>
#include <memory> // for unique_ptr
#include <string> // for string
#include <vector> // for vector
class ADirective;
class ConfigManager
{
@ -18,15 +20,13 @@ class ConfigManager
void init(const std::string &filePath);
static ConfigManager &getInstance();
[[nodiscard]] const std::vector<ServerConfig> &getServerConfigs() const { return serverConfigs_; }
[[nodiscard]] std::vector<ServerConfig *> getServerConfigs() const;
private:
bool initialized_;
ConfigManager();
~ConfigManager();
std::vector<ServerConfig> serverConfigs_;
std::vector<std::unique_ptr<ADirective>> globalDirectives_;
std::unique_ptr<GlobalConfig> globalConfig_;
void parseConfigFile(const std::string &filePath);
void parseGlobalDeclarations(const std::string &declarations);
};

View File

@ -0,0 +1,52 @@
#include <webserv/config/GlobalConfig.hpp>
#include <webserv/config/utils.hpp>
#include <webserv/log/Log.hpp> // for Log, LOCATION
#include <vector>
GlobalConfig::GlobalConfig(const std::string &block)
{
parseBlock(block);
}
void GlobalConfig::parseBlock(const std::string &block)
{
std::string directives;
Log::trace("Content before parsing servers:\n" + block);
size_t pos = 0;
while (true)
{
size_t serverPos = block.find("server", pos);
size_t bracePos = block.find('{', serverPos);
if (serverPos == std::string::npos || bracePos == std::string::npos)
{
// No more server blocks, remaining is global
directives += block.substr(pos);
break;
}
// Add global declarations before this server block
directives += block.substr(pos, serverPos - pos);
size_t closeBrace = utils::findCorrespondingClosingBrace(block, bracePos);
if (closeBrace == std::string::npos)
{
throw std::runtime_error("Malformed block in config file.");
}
// Optionally parse the server block here
std::string serverBlock = block.substr(bracePos + 1, closeBrace - bracePos - 1);
servers_.emplace_back(std::make_unique<ServerConfig>(serverBlock, this));
pos = closeBrace + 1;
}
parseDirectives(directives);
}
std::vector<ServerConfig *> GlobalConfig::getServerConfigs() const
{
std::vector<ServerConfig *> serverConfigs;
serverConfigs.reserve(servers_.size());
for (const auto &serverPtr : servers_)
{
serverConfigs.push_back(serverPtr.get());
}
return serverConfigs;
}

View File

@ -0,0 +1,25 @@
#pragma once
#include <webserv/config/AConfig.hpp> // for AConfig
#include <webserv/config/ServerConfig.hpp>
class GlobalConfig : public AConfig
{
public:
GlobalConfig() = delete;
GlobalConfig(const std::string &Block);
GlobalConfig(const GlobalConfig &other) = delete;
GlobalConfig &operator=(const GlobalConfig &other) = delete;
GlobalConfig(GlobalConfig &&other) noexcept = delete;
GlobalConfig &operator=(GlobalConfig &&other) noexcept = delete;
~GlobalConfig() override = default;
[[nodiscard]] std::vector<ServerConfig *> getServerConfigs() const;
private:
AConfig *parent_ = nullptr;
std::vector<std::unique_ptr<ServerConfig>> servers_;
void parseBlock(const std::string &block) override;
};

View File

@ -1,47 +1,14 @@
#include <webserv/config/AConfig.hpp> // for AConfig
#include <webserv/config/LocationConfig.hpp>
#include <webserv/config/utils.hpp>
#include <webserv/log/Log.hpp>
#include <webserv/log/Log.hpp> // for Log, LOCATION
#include <sstream>
#include <string>
LocationConfig::LocationConfig(const std::string &locationBlock) : autoIndex_(false)
LocationConfig::LocationConfig(const std::string &block, const AConfig *parent) : AConfig(parent)
{
parseLocationBlock(locationBlock);
parseBlock(block);
}
void LocationConfig::parseLocationBlock(const std::string &block)
void LocationConfig::parseBlock(const std::string &block)
{
Log::trace(LOCATION);
parseDirectives(block);
}
void LocationConfig::parseDirectives(const std::string &declarations)
{
std::istringstream stream(declarations);
std::string line;
while (std::getline(stream, line))
{
std::string directive;
std::istringstream lineStream{utils::trim(line)};
lineStream >> directive;
if (!directive.empty())
{
std::string value;
lineStream >> value;
if (directive == "autoindex")
{
autoIndex_ = (value == "on");
Log::info("Set autoindex to " + std::string(autoIndex_ ? "on" : "off"));
}
else if (directive == "index")
{
indexFile_ = value;
Log::info("Set index file to " + indexFile_);
}
else
{
directives_[directive] = value;
}
}
}
}

View File

@ -1,19 +1,20 @@
#pragma once
#include <map>
#include <string>
#include <webserv/config/AConfig.hpp> // for AConfig
class LocationConfig
class LocationConfig : public AConfig
{
public:
LocationConfig(const std::string &locationBlock);
LocationConfig() = delete;
LocationConfig(const std::string &Block, const AConfig *parent = nullptr);
LocationConfig(const LocationConfig &other) = delete;
LocationConfig &operator=(const LocationConfig &other) = delete;
LocationConfig(LocationConfig &&other) noexcept = delete;
LocationConfig &operator=(LocationConfig &&other) noexcept = delete;
~LocationConfig() override = default;
private:
std::string path_;
bool autoIndex_;
std::string indexFile_;
std::map<std::string, std::string> directives_;
void parseLocationBlock(const std::string &block);
void parseDirectives(const std::string &declarations);
void parseBlock(const std::string &block) override;
};

View File

@ -1,30 +1,18 @@
#include <webserv/config/LocationConfig.hpp> // for LocationConfig
#include <webserv/config/LocationConfig.hpp>
#include <webserv/config/ServerConfig.hpp>
#include <webserv/config/utils.hpp> // for findCorrespondingClosingBrace, trim
#include <webserv/config/utils.hpp>
#include <webserv/log/Log.hpp> // for Log, LOCATION
#include <webserv/config/directive/DirectiveFactory.hpp> // for DirectiveFactory
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <cstddef> // for size_t
#include <sstream> // for basic_istringstream, basic_istream, istringstream
#include <stdexcept> // for runtime_error
#include <string> // for basic_string, char_traits, operator+, allocator, string, operator==, operator>>, operator<=>, to_string, stoi, getline
#include <utility> // for pair
ServerConfig::ServerConfig(std::string const &serverBlock) : port_(80)
ServerConfig::ServerConfig(const std::string &block, const AConfig *parent) : AConfig(parent)
{
parseServerBlock(serverBlock);
parseBlock(block);
}
void ServerConfig::parseServerBlock(const std::string &block)
void ServerConfig::parseBlock(const std::string &block)
{
// Placeholder for actual server block parsing logic
Log::trace(LOCATION);
// Placeholder for actual file parsing logic
std::string serverDeclarations;
std::string directives;
size_t pos = 0;
while (true)
@ -35,12 +23,12 @@ void ServerConfig::parseServerBlock(const std::string &block)
if (locationPos == std::string::npos || bracePos == std::string::npos)
{
// No more server blocks, remaining is global
serverDeclarations += block.substr(pos);
directives += block.substr(pos);
break;
}
std::string locationPath = utils::trim(block.substr(locationPos, bracePos - (locationPos)));
// Add global declarations before this server block
serverDeclarations += block.substr(pos, locationPos - pos);
directives += block.substr(pos, locationPos - pos);
size_t closeBrace = utils::findCorrespondingClosingBrace(block, bracePos);
if (closeBrace == std::string::npos)
{
@ -48,138 +36,28 @@ void ServerConfig::parseServerBlock(const std::string &block)
}
// Optionally parse the server block here
std::string locationBlock = block.substr(bracePos + 1, closeBrace - bracePos - 1);
locations_.emplace(locationPath, locationBlock);
locations_[locationPath] = std::make_unique<LocationConfig>(locationBlock, this);
Log::debug("Added location: " + locationPath, {{"block", locationBlock}});
pos = closeBrace + 1;
}
// parseGlobalDeclarations(Declarations); // Implement this function to handle global config
parseDirectives(serverDeclarations);
parseDirectives(directives);
}
// void ServerConfig::parseDirectives(const std::string &declarations)
// {
// Log::info("Parsing server directives");
// std::string line;
// std::istringstream stream(declarations);
// while (std::getline(stream, line))
// {
// std::string directive;
// std::istringstream lineStream{line};
// lineStream >> directive;
// if (!directive.empty())
// {
// std::string value;
// lineStream >> value;
// if (directive == "listen")
// {
// port_ = std::stoi(value);
// if (port_ < 1 || port_ > 65535)
// {
// throw std::runtime_error("Invalid port number: " + std::to_string(port_));
// }
// Log::debug("Set port to " + std::to_string(port_));
// }
// else if (directive == "root")
// {
// root_ = value;
// Log::debug("Set root to " + root_);
// }
// else if (directive == "host")
// {
// host_ = value;
// Log::debug("Set host to " + host_);
// }
// else if (directive == "cgi_pass")
// {
// cgi_pass_ = value;
// Log::debug("Set cgi_pass to " + cgi_pass_);
// }
// else if (directive == "cgi_ext")
// {
// cgi_ext_ = value;
// Log::debug("Set cgi_ext to " + cgi_ext_);
// }
// else if (directive == "index")
// {
// index_files_.clear();
// std::string indexFile;
// while (lineStream >> indexFile)
// {
// index_files_.push_back(indexFile);
// Log::debug("Added index file: " + indexFile);
// }
// }
// else if (directive == "error_page")
// {
// int statusCode = std::stoi("-1");
// std::string errorPagePath;
// lineStream >> errorPagePath;
// Log::debug("Set error_page for status " + std::to_string(statusCode) + " to " + errorPagePath);
// }
// else
// {
// Log::warning("Unknown directive: " + directive);
// }
// }
// }
// }
// const LocationConfig &ServerConfig::getLocation(const std::string &path) const
// {
// if (locations_.count(path) > 0) // NOLINT
// {
// return locations_.at(path);
// }
// Log::error("Location not found: " + path);
// throw std::runtime_error("Location not found: " + path);
// }
// std::vector<std::string> ServerConfig::getLocationPaths() const
// {
// std::vector<std::string> paths;
// paths.reserve(locations_.size());
// for (const auto &pair : locations_)
// {
// paths.push_back(pair.first);
// }
// return paths;
// }
void ServerConfig::parseDirectives(const std::string &declarations)
const LocationConfig *ServerConfig::getLocation(const std::string &path) const
{
Log::trace(LOCATION);
std::stringstream ss(declarations);
std::string line;
while (ss.good())
{
std::getline(ss, line);
line = utils::trim(line);
if (line.empty())
{
continue;
}
auto directive = DirectiveFactory::createDirective(line);
directives_.push_back(std::move(directive));
}
Log::info("Parsed " + std::to_string(directives_.size()) + " directives.");
for (const auto &dir : directives_)
{
std::stringstream debugStream;
debugStream << "Directive parsed: " << *dir;
Log::debug(debugStream.str());
}
auto it = locations_.find(path);
return (it != locations_.end()) ? it->second.get() : nullptr;
}
DirectiveValue ServerConfig::operator[](const std::string &directive) const
std::vector<std::string> ServerConfig::getLocationPaths() const
{
for (const auto& dir : directives_)
std::vector<std::string> paths;
paths.reserve(locations_.size());
for (const auto &pair : locations_)
{
if (dir->getName() == directive)
{
return dir->get();
paths.push_back(pair.first);
}
}
throw std::runtime_error("Directive not found: " + directive);
return paths;
}

View File

@ -1,49 +1,27 @@
#pragma once
#include "webserv/config/directive/ADirective.hpp"
#include <webserv/config/LocationConfig.hpp>
#include <webserv/config/AConfig.hpp> // for AConfig
#include <webserv/config/LocationConfig.hpp> // for LocationConfig
#include <map>
#include <memory>
#include <string>
#include <vector>
// TODO remove implementation details from header
class ServerConfig
class ServerConfig : public AConfig
{
public:
ServerConfig(const std::string &serverBlock);
ServerConfig() = delete;
ServerConfig(const std::string &Block, const AConfig *parent = nullptr);
// [[nodiscard]] const std::string &getHost() const { return host_; }
ServerConfig(const ServerConfig &other) = delete;
ServerConfig &operator=(const ServerConfig &other) = delete;
ServerConfig(ServerConfig &&other) noexcept = delete;
ServerConfig &operator=(ServerConfig &&other) noexcept = delete;
// [[nodiscard]] int getPort() const { return port_; }
~ServerConfig() override = default;
// [[nodiscard]] const std::string &getRoot() const { return root_; }
// [[nodiscard]] const std::string &getCgiPass() const { return cgi_pass_; }
// [[nodiscard]] const std::string &getCgiExt() const { return cgi_ext_; }
// [[nodiscard]] const std::map<int, std::string> &getErrorPages() const { return error_page_; }
// [[nodiscard]] const std::vector<std::string> &getIndexFiles() const { return index_files_; }
// [[nodiscard]] const LocationConfig &getLocation(const std::string &path) const;
// [[nodiscard]] std::vector<std::string> getLocationPaths() const;
DirectiveValue operator[](const std::string &directive) const;
[[nodiscard]] const LocationConfig *getLocation(const std::string &path) const;
[[nodiscard]] std::vector<std::string> getLocationPaths() const;
private:
std::string host_;
int port_;
std::string root_;
std::string cgi_pass_;
std::string cgi_ext_;
std::map<int, std::string> error_page_;
std::vector<std::string> index_files_;
std::map<std::string, LocationConfig> locations_;
std::vector<std::unique_ptr<ADirective>> directives_;
std::map<std::string, std::unique_ptr<LocationConfig>> locations_;
AConfig *parent_ = nullptr;
void parseServerBlock(const std::string &block);
void parseDirectives(const std::string &declarations);
void parseBlock(const std::string &block) override;
};

View File

@ -1,8 +1,9 @@
#include <webserv/config/directive/ADirective.hpp>
#include <webserv/config/directive/DirectiveValue.hpp> // for DirectiveValue, operator<<
DirectiveValue ADirective::get() const
DirectiveValue ADirective::getValue() const
{
return {getValue()};
return {getValueType()};
}
std::string ADirective::getName() const
@ -16,8 +17,8 @@ void ADirective::setName(const std::string &name)
}
// Non-member stream operator implementations
std::ostream &operator<<(std::ostream &os, const DirectiveValue &dv)
{
return os << dv.toString();
}
std::ostream &operator<<(std::ostream &os, const ADirective &directive)
{
return os << directive.getName() << ": " << directive.getValue().toString();
}

View File

@ -1,10 +1,10 @@
#pragma once
#include <webserv/config/directive/DirectiveValue.hpp>
#include <iostream>
#include <string>
#include <webserv/config/directive/DirectiveValue.hpp> // for DirectiveValue, DirectiveValueType
#include <iostream> // for ostream
#include <string> // for string, basic_string
#include <utility> // for move
class ADirective
{
@ -23,8 +23,8 @@ class ADirective
void setName(const std::string &name);
virtual void parse(const std::string &value) = 0;
[[nodiscard]] virtual DirectiveValueType getValue() const = 0;
[[nodiscard]] DirectiveValue get() const;
[[nodiscard]] virtual DirectiveValueType getValueType() const = 0;
[[nodiscard]] DirectiveValue getValue() const;
[[nodiscard]] std::string getName() const;
// [[nodiscard]] std::string toString() const;

View File

@ -1,14 +1,19 @@
#include <webserv/config/directive/BoolDirective.hpp> // for IntDirective
#include <webserv/config/utils.hpp> // for trim
#include <algorithm>
#include <any>
#include <stdexcept>
#include <algorithm> // for __transform_fn, transform
#include <cctype> // for tolower
#include <stdexcept> // for invalid_argument
BoolDirective::BoolDirective(const std::string &name, const std::string &value)
: ADirective(name) // NOLINT(bugprone-easily-swappable-parameters)
{
parse(value);
}
void BoolDirective::parse(const std::string &arg)
{
std::string value = arg;
value = utils::trim(value);
std::string value = utils::trim(arg);
std::ranges::transform(value, value.begin(), ::tolower);
if (value == "true" || value == "1" || value == "on" || value == "yes")
{
@ -24,7 +29,7 @@ void BoolDirective::parse(const std::string &arg)
}
}
DirectiveValueType BoolDirective::getValue() const
DirectiveValueType BoolDirective::getValueType() const
{
return value_;
}

View File

@ -1,15 +1,16 @@
#pragma once
#include "ADirective.hpp"
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <webserv/config/directive/DirectiveValue.hpp> // for DirectiveValueType
#include <any>
#include <string> // for string, basic_string
class BoolDirective : public ADirective
{
public:
BoolDirective() = delete;
BoolDirective(const std::string &name, const std::string &value) : ADirective(name) { parse(value); }
BoolDirective(const std::string &name, const std::string &value);
BoolDirective(const BoolDirective &other) = delete;
BoolDirective &operator=(const BoolDirective &other) = delete;
@ -18,9 +19,9 @@ class BoolDirective : public ADirective
~BoolDirective() override = default;
void parse(const std::string &value) override;
void parse(const std::string &arg) override;
[[nodiscard]] DirectiveValueType getValue() const override;
[[nodiscard]] DirectiveValueType getValueType() const override;
private:
bool value_ = false;

View File

@ -1,19 +1,22 @@
#include <webserv/config/directive/ADirective.hpp>
#include <webserv/config/directive/BoolDirective.hpp>
#include "webserv/log/Log.hpp"
#include <webserv/config/directive/BoolDirective.hpp> // for BoolDirective
#include <webserv/config/directive/DirectiveFactory.hpp> // for DirectiveFactory
#include <webserv/config/directive/IntDirective.hpp>
#include <webserv/config/directive/SizeDirective.hpp>
#include <webserv/config/directive/IntStringDirective.hpp>
#include <webserv/config/directive/StringDirective.hpp>
#include <webserv/config/directive/VectorDirective.hpp>
#include <webserv/config/utils.hpp> // for trim, findCorrespondingClosingBrace, trimSemi
#include <webserv/log/Log.hpp> // for Log
#include <sstream>
#include <webserv/config/directive/IntDirective.hpp> // for IntDirective
#include <webserv/config/directive/IntStringDirective.hpp> // for IntStringDirective
#include <webserv/config/directive/SizeDirective.hpp> // for SizeDirective
#include <webserv/config/directive/StringDirective.hpp> // for StringDirective
#include <webserv/config/directive/VectorDirective.hpp> // for VectorDirective
#include <webserv/config/utils.hpp> // for trim, trimSemi
#include <sstream> // for basic_stringstream, stringstream
#include <stdexcept> // for invalid_argument
class ADirective;
std::unique_ptr<ADirective> DirectiveFactory::createDirective(const std::string &line)
{
Log::trace(LOCATION);
std::stringstream ss(line);
std::string name;
ss >> name;
@ -61,8 +64,8 @@ const std::unordered_map<std::string_view, DirectiveFactory::CreatorFunc> &Direc
[](const std::string &name, const std::string &arg) { return std::make_unique<SizeDirective>(name, arg); }},
{"StringDirective",
[](const std::string &name, const std::string &arg) { return std::make_unique<StringDirective>(name, arg); }},
{"IntStringDirective",
[](const std::string &name, const std::string &arg) { return std::make_unique<IntStringDirective>(name, arg); }},
{"IntStringDirective", [](const std::string &name,
const std::string &arg) { return std::make_unique<IntStringDirective>(name, arg); }},
{"VectorDirective",
[](const std::string &name, const std::string &arg) { return std::make_unique<VectorDirective>(name, arg); }},
};

View File

@ -1,9 +1,12 @@
#include "webserv/config/directive/ADirective.hpp"
#pragma once
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <functional>
#include <memory>
#include <string_view>
#include <unordered_map>
#include <array> // for array
#include <functional> // for function
#include <memory> // for unique_ptr
#include <string> // for string
#include <string_view> // for string_view
#include <unordered_map> // for unordered_map
class DirectiveFactory
{

View File

@ -1,13 +1,13 @@
#include <webserv/config/directive/ADirective.hpp>
#include <webserv/config/directive/ADirective.hpp> // for ADirective, operator<<
#include <webserv/config/directive/DirectiveValue.hpp>
#include <cstddef>
#include <string>
#include <type_traits> // for is_same_v, decay_t
#include <utility> // for pair, move
#include <variant> // for variant, visit
#include <cstddef> // for size_t
#include <string> // for string, basic_string, allocator, char_traits, operator+, to_string, operator<<
#include <utility> // for pair
#include <variant> // for visit
#include <vector> // for vector
//
//
// std::string DirectiveValue::toString() const
// {
@ -78,7 +78,7 @@ std::string DirectiveValue::toString() const
value_);
}
std::ostream &operator<<(std::ostream &os, const ADirective &directive)
std::ostream &operator<<(std::ostream &os, const DirectiveValue &dv)
{
return os << directive.getName() << ": " << directive.get().toString();
return os << dv.toString();
}

View File

@ -3,20 +3,17 @@
#include <cstddef> // for size_t
#include <iostream> // for ostream, operator<<
#include <string> // for string, basic_string, char_traits, to_string
#include <utility> // for pair, move
#include <variant> // for variant, visit, get, holds_alternative
#include <vector> // for vector
#include <utility> // for pair, move
// Visitor overload pattern for std::visit
template<class... Ts>
struct overloaded : Ts... {
template <class... Ts> struct overloaded : Ts...
{
using Ts::operator()...;
};
template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
// Define all possible directive value types
using DirectiveValueType = std::variant<int, // listen, error_page status, cgi_timeout
@ -38,7 +35,6 @@ class DirectiveValue
[[nodiscard]] std::string toString() const;
private:
DirectiveValueType value_;
};

View File

@ -1,13 +1,17 @@
#include <webserv/config/directive/IntDirective.hpp> // for IntDirective
#include <any>
IntDirective::IntDirective(const std::string &name, const std::string &value)
: ADirective(name) // NOLINT(bugprone-easily-swappable-parameters)
{
parse(value);
}
void IntDirective::parse(const std::string &value)
{
value_ = std::stoi(value); // TODO: check parsing
}
DirectiveValueType IntDirective::getValue() const
DirectiveValueType IntDirective::getValueType() const
{
return value_;
}

View File

@ -1,15 +1,16 @@
#pragma once
#include "ADirective.hpp"
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <webserv/config/directive/DirectiveValue.hpp> // for DirectiveValueType
#include <any>
#include <string> // for string, basic_string
class IntDirective : public ADirective
{
public:
IntDirective() = delete;
IntDirective(const std::string &name, const std::string &value) : ADirective(name) { parse(value); }
IntDirective(const std::string &name, const std::string &value);
IntDirective(const IntDirective &other) = delete;
IntDirective &operator=(const IntDirective &other) = delete;
@ -20,7 +21,7 @@ class IntDirective : public ADirective
void parse(const std::string &value) override;
[[nodiscard]] DirectiveValueType getValue() const override;
[[nodiscard]] DirectiveValueType getValueType() const override;
private:
int value_ = 0;

View File

@ -1,8 +1,13 @@
#include "webserv/log/Log.hpp"
#include <webserv/config/directive/IntStringDirective.hpp> // for IntDirective
#include <webserv/config/utils.hpp> // for trim
#include <sstream> // for std::getline, std::basic_istream, std::char_traits, std::basic_stringbuf
#include <sstream> // for basic_istringstream, basic_istream::operator>>, istringstream
IntStringDirective::IntStringDirective(const std::string &name, const std::string &value)
: ADirective(name) // NOLINT(bugprone-easily-swappable-parameters)
{
parse(value);
}
void IntStringDirective::parse(const std::string &value)
{
@ -15,7 +20,7 @@ void IntStringDirective::parse(const std::string &value)
value_ = std::make_pair(intPart, strPart);
}
DirectiveValueType IntStringDirective::getValue() const
DirectiveValueType IntStringDirective::getValueType() const
{
return value_;
}

View File

@ -1,15 +1,16 @@
#pragma once
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <webserv/config/directive/DirectiveValue.hpp> // for DirectiveValueType
#include "ADirective.hpp"
#include <any>
#include <string> // for basic_string, string
#include <utility> // for pair
class IntStringDirective : public ADirective
{
public:
IntStringDirective() = delete;
IntStringDirective(const std::string &name, const std::string &value) : ADirective(name) { parse(value); }
IntStringDirective(const std::string &name, const std::string &value);
IntStringDirective(const IntStringDirective &other) = delete;
IntStringDirective &operator=(const IntStringDirective &other) = delete;
@ -20,7 +21,7 @@ class IntStringDirective : public ADirective
void parse(const std::string &value) override;
[[nodiscard]] DirectiveValueType getValue() const override;
[[nodiscard]] DirectiveValueType getValueType() const override;
private:
std::pair<int, std::string> value_ = {0, ""};

View File

@ -1,10 +1,15 @@
#include <webserv/config/directive/SizeDirective.hpp> // for SizeDirective
#include <webserv/config/utils.hpp> // for trim
#include <algorithm>
#include <any>
#include <cctype>
#include <stdexcept>
#include <algorithm> // for __transform_fn, transform
#include <cctype> // for tolower
#include <stdexcept> // for invalid_argument
SizeDirective::SizeDirective(const std::string &name, const std::string &value)
: ADirective(name) // NOLINT(bugprone-easily-swappable-parameters)
{
parse(value);
}
void SizeDirective::parse(const std::string &value)
{
@ -43,7 +48,7 @@ void SizeDirective::parse(const std::string &value)
value_ *= multiplier;
}
DirectiveValueType SizeDirective::getValue() const
DirectiveValueType SizeDirective::getValueType() const
{
return value_;
}

View File

@ -1,15 +1,17 @@
#pragma once
#include "ADirective.hpp"
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <webserv/config/directive/DirectiveValue.hpp> // for DirectiveValueType
#include <any>
#include <cstddef> // for size_t
#include <string> // for string, basic_string
class SizeDirective : public ADirective
{
public:
SizeDirective() = delete;
SizeDirective(const std::string &name, const std::string &value) : ADirective(name) { parse(value); }
SizeDirective(const std::string &name, const std::string &value);
SizeDirective(const SizeDirective &other) = delete;
SizeDirective &operator=(const SizeDirective &other) = delete;
@ -20,7 +22,7 @@ class SizeDirective : public ADirective
void parse(const std::string &value) override;
[[nodiscard]] DirectiveValueType getValue() const override;
[[nodiscard]] DirectiveValueType getValueType() const override;
private:
size_t value_ = 0;

View File

@ -1,13 +1,17 @@
#include <webserv/config/directive/StringDirective.hpp> // for IntDirective
#include <any>
StringDirective::StringDirective(const std::string &name, const std::string &value)
: ADirective(name) // NOLINT(bugprone-easily-swappable-parameters)
{
parse(value);
}
void StringDirective::parse(const std::string &value)
{
value_ = value;
}
DirectiveValueType StringDirective::getValue() const
DirectiveValueType StringDirective::getValueType() const
{
return value_;
}

View File

@ -1,14 +1,16 @@
#pragma once
#include "ADirective.hpp"
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <webserv/config/directive/DirectiveValue.hpp> // for DirectiveValueType
#include <string> // for string, basic_string
class StringDirective : public ADirective
{
public:
StringDirective() = delete;
StringDirective(const std::string &name, const std::string &value) : ADirective(name) { parse(value); }
StringDirective(const std::string &name, const std::string &value);
StringDirective(const StringDirective &other) = delete;
StringDirective &operator=(const StringDirective &other) = delete;
StringDirective(StringDirective &&other) noexcept = delete;
@ -18,7 +20,7 @@ class StringDirective : public ADirective
void parse(const std::string &value) override;
[[nodiscard]] DirectiveValueType getValue() const override;
[[nodiscard]] DirectiveValueType getValueType() const override;
private:
std::string value_;

View File

@ -1,7 +1,12 @@
#include <webserv/config/directive/VectorDirective.hpp> // for IntDirective
#include <any>
#include <sstream> // for std::getline, std::basic_istream, std::char_traits, std::basic_stringbuf
#include <sstream> // for basic_stringstream, stringstream
VectorDirective::VectorDirective(const std::string &name, const std::string &value)
: ADirective(name) // NOLINT(bugprone-easily-swappable-parameters)
{
parse(value);
}
void VectorDirective::parse(const std::string &value)
{
@ -17,7 +22,7 @@ void VectorDirective::parse(const std::string &value)
}
}
DirectiveValueType VectorDirective::getValue() const
DirectiveValueType VectorDirective::getValueType() const
{
return value_;
}

View File

@ -1,16 +1,17 @@
#pragma once
#include "ADirective.hpp"
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <webserv/config/directive/DirectiveValue.hpp> // for DirectiveValueType
#include <string>
#include <vector>
#include <string> // for basic_string, string
#include <vector> // for vector
class VectorDirective : public ADirective
{
public:
VectorDirective() = delete;
VectorDirective(const std::string &name, const std::string &value) : ADirective(name) { parse(value); }
VectorDirective(const std::string &name, const std::string &value);
VectorDirective(const VectorDirective &other) = delete;
VectorDirective &operator=(const VectorDirective &other) = delete;
@ -21,7 +22,7 @@ class VectorDirective : public ADirective
void parse(const std::string &value) override;
[[nodiscard]] DirectiveValueType getValue() const override;
[[nodiscard]] DirectiveValueType getValueType() const override;
private:
std::vector<std::string> value_;

View File

@ -1,6 +1,7 @@
#include <webserv/config/utils.hpp>
#include <sstream>
#include <stdexcept>
#include <string>
@ -69,4 +70,38 @@ size_t findCorrespondingClosingBrace(const std::string &str, size_t openPos)
}
return std::string::npos;
}
void removeEmptyLines(std::string &str)
{
std::istringstream stream(str);
std::string line;
std::string result;
while (std::getline(stream, line))
{
if (!utils::trim(line).empty())
{
result += utils::trimSemi(utils::trim(line)) + '\n';
}
}
str = result;
}
void removeComments(std::string &str)
{
size_t pos = 0;
while ((pos = str.find('#', pos)) != std::string::npos)
{
size_t end = str.find('\n', pos);
if (end == std::string::npos)
{
str.erase(pos);
}
else
{
str.erase(pos, end - pos);
}
}
removeEmptyLines(str);
}
} // namespace utils

View File

@ -9,4 +9,6 @@ size_t stoul(const std::string &str, int base = 10);
std::string trimSemi(const std::string &str);
std::string trim(const std::string &str);
size_t findCorrespondingClosingBrace(const std::string &str, size_t openPos);
void removeEmptyLines(std::string &str);
void removeComments(std::string &str);
} // namespace utils

View File

@ -1,11 +1,13 @@
#include "webserv/config/utils.hpp"
#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 <optional> // for optional, operator>
#include <map> // for map
#include <optional> // for optional
#include <sstream> // for basic_stringstream, basic_istream, stringstream
#include <utility> // for pair
#include <vector> // for vector
class ServerConfig;

View File

@ -2,6 +2,7 @@
#include <array> // for array
#include <chrono> // for steady_clock
#include <cstdint> // for uint8_t
#include <ios> // for ios_base
#include <map> // for map
#include <memory> // for unique_ptr
@ -9,8 +10,6 @@
#include <string_view> // for string_view
#include <unordered_map> // for unordered_map
#include <cstdint> // for uint8_t
class Channel; // Forward declaration
constexpr const char *extractFilename(const char *path)

View File

@ -1,12 +1,9 @@
#include <webserv/config/ConfigManager.hpp> // for ConfigManager
#include <webserv/config/directive/ADirective.hpp> // for ADirective
#include <webserv/config/directive/IntDirective.hpp> // for IntDirective
#include <webserv/log/Log.hpp> // for Log, LOCATION
#include <webserv/server/Server.hpp> // for Server
#include <iostream> // for basic_ostream, operator<<, cerr, ios_base
#include <map> // for map
#include <numeric>
#include <string> // for basic_string, char_traits, allocator, operator+, operator<=>
#include <utility> // for pair

View File

@ -4,15 +4,15 @@
#include <webserv/server/Server.hpp>
#include <webserv/socket/Socket.hpp> // for Socket
#include <cerrno> // for errno
#include <cstring> // for strerror, strlen
#include <exception> // for exception
#include <memory> // for unique_ptr, allocator, make_unique
#include <stdexcept> // for runtime_error
#include <string> // for operator+, to_string, basic_string, char_traits, string
#include <string> // for basic_string, operator+, to_string, char_traits, string
#include <utility> // for move, pair
#include <vector> // for vector
#include <cerrno> // for errno
#include <sys/epoll.h> // for epoll_event, epoll_ctl, EPOLLIN, EPOLLOUT, epoll_create1, epoll_wait, EPOLLERR, EPOLLHUP, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD
#include <sys/socket.h> // for send, SOMAXCONN
#include <sys/types.h> // for ssize_t
@ -48,7 +48,7 @@ void Server::start()
for (const auto &config : configManager_.getServerConfigs())
{
setupServerSocket(config);
setupServerSocket(*config);
}
if (fdToConfig_.empty())
{
@ -86,8 +86,8 @@ void Server::setupServerSocket(const ServerConfig &config)
{
try
{
auto host = config["host"].get<std::string>();
auto port = config["listen"].get<int>();
auto host = config.getDirectiveValue<std::string>("host");
auto port = config.getDirectiveValue<int>("listen");
std::unique_ptr<Socket> serverSocket = std::make_unique<Socket>();
serverSocket->bind(host, port);
serverSocket->listen(SOMAXCONN);
@ -97,7 +97,8 @@ void Server::setupServerSocket(const ServerConfig &config)
listeners_.push_back(std::move(serverSocket));
fdToConfig_.insert({server_fd, std::cref(config)});
// Log::info("Server listening on " + std::string(config["host"]) + ":" + static_cast<std::string>(config["listen"]) + "...");
Log::info("Server listening on " + host + ":" + std::to_string(port) + "...");
// static_cast<std::string>(config["listen"]) + "...");
}
catch (const std::exception &e)
{

View File

@ -5,13 +5,12 @@
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
#include <webserv/socket/Socket.hpp> // for Socket
#include <cstdint> // for uint32_t
#include <functional> // for reference_wrapper
#include <memory> // for unique_ptr
#include <unordered_map> // for unordered_map
#include <vector> // for vector
#include <cstdint> // for uint32_t
class Client;
class ConfigManager;