feat(directives): implement DirectiveValue class and IntStringDirective for enhanced directive handling and use std::variant instead of any
This commit is contained in:
parent
1e80839864
commit
17b69afd2c
@ -163,7 +163,13 @@ void ServerConfig::parseDirectives(const std::string &declarations)
|
|||||||
auto directive = DirectiveFactory::createDirective(line);
|
auto directive = DirectiveFactory::createDirective(line);
|
||||||
directives_.push_back(std::move(directive));
|
directives_.push_back(std::move(directive));
|
||||||
}
|
}
|
||||||
Log::info("Parsed " + std::to_string(directives_.size()) + " directives.", {{"declarations", declarations}});
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DirectiveValue ServerConfig::operator[](const std::string &directive) const
|
DirectiveValue ServerConfig::operator[](const std::string &directive) const
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include <webserv/config/directive/ADirective.hpp> // for ADirective
|
#include <webserv/config/directive/ADirective.hpp>
|
||||||
|
|
||||||
DirectiveValue ADirective::get() const
|
DirectiveValue ADirective::get() const
|
||||||
{
|
{
|
||||||
@ -14,3 +14,10 @@ void ADirective::setName(const std::string &name)
|
|||||||
{
|
{
|
||||||
name_ = name;
|
name_ = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Non-member stream operator implementations
|
||||||
|
std::ostream &operator<<(std::ostream &os, const DirectiveValue &dv)
|
||||||
|
{
|
||||||
|
return os << dv.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <any>
|
#include <webserv/config/directive/DirectiveValue.hpp>
|
||||||
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class DirectiveValue
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
DirectiveValue(std::any value) : value_(value) {}
|
|
||||||
|
|
||||||
template <typename T> operator T() const { return std::any_cast<T>(value_); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::any value_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ADirective
|
class ADirective
|
||||||
{
|
{
|
||||||
@ -26,36 +18,19 @@ class ADirective
|
|||||||
ADirective(ADirective &&other) noexcept = delete;
|
ADirective(ADirective &&other) noexcept = delete;
|
||||||
ADirective &operator=(ADirective &&other) noexcept = delete;
|
ADirective &operator=(ADirective &&other) noexcept = delete;
|
||||||
|
|
||||||
virtual ~ADirective() {}
|
virtual ~ADirective() = default;
|
||||||
|
|
||||||
virtual void parse(const std::string &value) = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] virtual std::any getValue() const = 0;
|
|
||||||
|
|
||||||
[[nodiscard]] DirectiveValue get() const;
|
|
||||||
|
|
||||||
[[nodiscard]] std::string getName() const;
|
|
||||||
|
|
||||||
void setName(const std::string &name);
|
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]] std::string getName() const;
|
||||||
|
// [[nodiscard]] std::string toString() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string name_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Supported directives:
|
// Non-member stream operator for ADirective
|
||||||
|
std::ostream &operator<<(std::ostream &os, const ADirective &directive);
|
||||||
// - listen INT {server}
|
|
||||||
// - host STRING {server}
|
|
||||||
// - server_name STRING {server}
|
|
||||||
// - root STRING {server, location}
|
|
||||||
// - index STRING[] {server, location}
|
|
||||||
// - error_page INT STIRNG {server, location}
|
|
||||||
// - client_max_body_size SIZE {server, location}
|
|
||||||
// - autoindex BOOL {location}
|
|
||||||
// - allowed_methods STRING[] {location}
|
|
||||||
// - cgi_pass STRING {location}
|
|
||||||
// - cgi_ext STRING[] {location}
|
|
||||||
// - cgi_timout INT {location}
|
|
||||||
// - upload_enabled BOOL {location}
|
|
||||||
// - upload_store STRING {location}
|
|
||||||
// - redirect INT STRING {location}
|
|
||||||
@ -24,7 +24,7 @@ void BoolDirective::parse(const std::string &arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any BoolDirective::getValue() const
|
DirectiveValueType BoolDirective::getValue() const
|
||||||
{
|
{
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ class BoolDirective : public ADirective
|
|||||||
|
|
||||||
void parse(const std::string &value) override;
|
void parse(const std::string &value) override;
|
||||||
|
|
||||||
[[nodiscard]] std::any getValue() const override;
|
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool value_ = false;
|
bool value_ = false;
|
||||||
|
|||||||
@ -3,10 +3,14 @@
|
|||||||
#include <webserv/config/directive/DirectiveFactory.hpp> // for DirectiveFactory
|
#include <webserv/config/directive/DirectiveFactory.hpp> // for DirectiveFactory
|
||||||
#include <webserv/config/directive/IntDirective.hpp>
|
#include <webserv/config/directive/IntDirective.hpp>
|
||||||
#include <webserv/config/directive/SizeDirective.hpp>
|
#include <webserv/config/directive/SizeDirective.hpp>
|
||||||
|
#include <webserv/config/directive/IntStringDirective.hpp>
|
||||||
#include <webserv/config/directive/StringDirective.hpp>
|
#include <webserv/config/directive/StringDirective.hpp>
|
||||||
#include <webserv/config/directive/VectorDirective.hpp>
|
#include <webserv/config/directive/VectorDirective.hpp>
|
||||||
#include <webserv/config/utils.hpp> // for trim, findCorrespondingClosingBrace, trimSemi
|
#include <webserv/config/utils.hpp> // for trim, findCorrespondingClosingBrace, trimSemi
|
||||||
#include <webserv/log/Log.hpp> // for Log
|
#include <webserv/log/Log.hpp> // for Log
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<ADirective> DirectiveFactory::createDirective(const std::string &line)
|
std::unique_ptr<ADirective> DirectiveFactory::createDirective(const std::string &line)
|
||||||
{
|
{
|
||||||
@ -57,6 +61,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); }},
|
[](const std::string &name, const std::string &arg) { return std::make_unique<SizeDirective>(name, arg); }},
|
||||||
{"StringDirective",
|
{"StringDirective",
|
||||||
[](const std::string &name, const std::string &arg) { return std::make_unique<StringDirective>(name, arg); }},
|
[](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); }},
|
||||||
{"VectorDirective",
|
{"VectorDirective",
|
||||||
[](const std::string &name, const std::string &arg) { return std::make_unique<VectorDirective>(name, arg); }},
|
[](const std::string &name, const std::string &arg) { return std::make_unique<VectorDirective>(name, arg); }},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class DirectiveFactory
|
|||||||
{.name = "server_name", .type = "VectorDirective", .context = "SL"},
|
{.name = "server_name", .type = "VectorDirective", .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 = "VectorDirective", .context = "SL"},
|
{.name = "error_page", .type = "IntStringDirective", .context = "SL"},
|
||||||
{.name = "client_max_body_size", .type = "SizeDirective", .context = "SL"},
|
{.name = "client_max_body_size", .type = "SizeDirective", .context = "SL"},
|
||||||
{.name = "autoindex", .type = "BoolDirective", .context = "L"},
|
{.name = "autoindex", .type = "BoolDirective", .context = "L"},
|
||||||
{.name = "allowed_methods", .type = "VectorDirective", .context = "L"},
|
{.name = "allowed_methods", .type = "VectorDirective", .context = "L"},
|
||||||
|
|||||||
58
webserv/config/directive/DirectiveValue.cpp
Normal file
58
webserv/config/directive/DirectiveValue.cpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include <webserv/config/directive/ADirective.hpp>
|
||||||
|
#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 <vector> // for vector
|
||||||
|
|
||||||
|
std::string DirectiveValue::toString() const
|
||||||
|
{
|
||||||
|
return std::visit(
|
||||||
|
[](const auto &val) -> std::string {
|
||||||
|
using T = std::decay_t<decltype(val)>;
|
||||||
|
|
||||||
|
if constexpr (std::is_same_v<T, int> || std::is_same_v<T, size_t>)
|
||||||
|
{
|
||||||
|
return std::to_string(val);
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::string>)
|
||||||
|
{
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, bool>)
|
||||||
|
{
|
||||||
|
return val ? "true" : "false";
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::vector<std::string>>)
|
||||||
|
{
|
||||||
|
std::string result = "[";
|
||||||
|
for (size_t i = 0; i < val.size(); ++i)
|
||||||
|
{
|
||||||
|
if (i > 0)
|
||||||
|
{
|
||||||
|
result += ", ";
|
||||||
|
}
|
||||||
|
result += "\"" + val[i] + "\"";
|
||||||
|
}
|
||||||
|
result += "]";
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, std::pair<int, std::string>>)
|
||||||
|
{
|
||||||
|
return std::to_string(val.first) + " \"" + val.second + "\"";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "<unknown>";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
value_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const ADirective &directive)
|
||||||
|
{
|
||||||
|
return os << directive.getName() << ": " << directive.get().toString();
|
||||||
|
}
|
||||||
36
webserv/config/directive/DirectiveValue.hpp
Normal file
36
webserv/config/directive/DirectiveValue.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef> // for size_t
|
||||||
|
#include <iostream> // for ostream, operator<<
|
||||||
|
#include <string> // for string, basic_string, char_traits, to_string
|
||||||
|
#include <variant> // for variant, visit, get, holds_alternative
|
||||||
|
#include <vector> // for vector
|
||||||
|
#include <utility> // for pair, move
|
||||||
|
|
||||||
|
// Define all possible directive value types
|
||||||
|
using DirectiveValueType = std::variant<int, // listen, error_page status, cgi_timeout
|
||||||
|
size_t,
|
||||||
|
bool, // autoindex, upload_enabled
|
||||||
|
std::string, // host, server_name, root, cgi_pass, upload_store
|
||||||
|
std::vector<std::string>, // index, allowed_methods, cgi_ext
|
||||||
|
std::pair<int, std::string> // error_page (status, path), redirect
|
||||||
|
>;
|
||||||
|
|
||||||
|
class DirectiveValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DirectiveValue(DirectiveValueType value) : value_(std::move(value)) {}
|
||||||
|
|
||||||
|
template <typename T> T get() const { return std::get<T>(value_); }
|
||||||
|
|
||||||
|
template <typename T> [[nodiscard]] bool holds() const { return std::holds_alternative<T>(value_); }
|
||||||
|
|
||||||
|
[[nodiscard]] std::string toString() const;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
DirectiveValueType value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Non-member stream operator for DirectiveValue
|
||||||
|
std::ostream &operator<<(std::ostream &os, const DirectiveValue &dv);
|
||||||
@ -7,7 +7,7 @@ void IntDirective::parse(const std::string &value)
|
|||||||
value_ = std::stoi(value); // TODO: check parsing
|
value_ = std::stoi(value); // TODO: check parsing
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any IntDirective::getValue() const
|
DirectiveValueType IntDirective::getValue() const
|
||||||
{
|
{
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ class IntDirective : public ADirective
|
|||||||
|
|
||||||
void parse(const std::string &value) override;
|
void parse(const std::string &value) override;
|
||||||
|
|
||||||
[[nodiscard]] std::any getValue() const override;
|
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int value_ = 0;
|
int value_ = 0;
|
||||||
|
|||||||
21
webserv/config/directive/IntStringDirective.cpp
Normal file
21
webserv/config/directive/IntStringDirective.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
void IntStringDirective::parse(const std::string &value)
|
||||||
|
{
|
||||||
|
std::istringstream iss(value);
|
||||||
|
int intPart = 0;
|
||||||
|
std::string strPart;
|
||||||
|
iss >> intPart;
|
||||||
|
std::getline(iss, strPart);
|
||||||
|
strPart = utils::trim(strPart); // Remove leading space
|
||||||
|
value_ = std::make_pair(intPart, strPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectiveValueType IntStringDirective::getValue() const
|
||||||
|
{
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
27
webserv/config/directive/IntStringDirective.hpp
Normal file
27
webserv/config/directive/IntStringDirective.hpp
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ADirective.hpp"
|
||||||
|
|
||||||
|
#include <any>
|
||||||
|
|
||||||
|
class IntStringDirective : public ADirective
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IntStringDirective() = delete;
|
||||||
|
|
||||||
|
IntStringDirective(const std::string &name, const std::string &value) : ADirective(name) { parse(value); }
|
||||||
|
|
||||||
|
IntStringDirective(const IntStringDirective &other) = delete;
|
||||||
|
IntStringDirective &operator=(const IntStringDirective &other) = delete;
|
||||||
|
IntStringDirective(IntStringDirective &&other) noexcept = delete;
|
||||||
|
IntStringDirective &operator=(IntStringDirective &&other) noexcept = delete;
|
||||||
|
|
||||||
|
~IntStringDirective() override = default;
|
||||||
|
|
||||||
|
void parse(const std::string &value) override;
|
||||||
|
|
||||||
|
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::pair<int, std::string> value_ = {0, ""};
|
||||||
|
};
|
||||||
@ -43,7 +43,7 @@ void SizeDirective::parse(const std::string &value)
|
|||||||
value_ *= multiplier;
|
value_ *= multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any SizeDirective::getValue() const
|
DirectiveValueType SizeDirective::getValue() const
|
||||||
{
|
{
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
@ -20,7 +20,7 @@ class SizeDirective : public ADirective
|
|||||||
|
|
||||||
void parse(const std::string &value) override;
|
void parse(const std::string &value) override;
|
||||||
|
|
||||||
[[nodiscard]] std::any getValue() const override;
|
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t value_ = 0;
|
size_t value_ = 0;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ void StringDirective::parse(const std::string &value)
|
|||||||
value_ = value;
|
value_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any StringDirective::getValue() const
|
DirectiveValueType StringDirective::getValue() const
|
||||||
{
|
{
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
@ -18,7 +18,7 @@ class StringDirective : public ADirective
|
|||||||
|
|
||||||
void parse(const std::string &value) override;
|
void parse(const std::string &value) override;
|
||||||
|
|
||||||
[[nodiscard]] std::any getValue() const override;
|
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string value_;
|
std::string value_;
|
||||||
|
|||||||
@ -6,10 +6,10 @@
|
|||||||
void VectorDirective::parse(const std::string &value)
|
void VectorDirective::parse(const std::string &value)
|
||||||
{
|
{
|
||||||
std::stringstream ss(value);
|
std::stringstream ss(value);
|
||||||
while(ss.good())
|
while (ss.good())
|
||||||
{
|
{
|
||||||
std::string item;
|
std::string item;
|
||||||
std::getline(ss, item, ' ');// index indx.html
|
std::getline(ss, item, ' '); // index indx.html
|
||||||
if (!item.empty())
|
if (!item.empty())
|
||||||
{
|
{
|
||||||
value_.push_back(item);
|
value_.push_back(item);
|
||||||
@ -17,7 +17,7 @@ void VectorDirective::parse(const std::string &value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any VectorDirective::getValue() const
|
DirectiveValueType VectorDirective::getValue() const
|
||||||
{
|
{
|
||||||
return value_;
|
return value_;
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ class VectorDirective : public ADirective
|
|||||||
|
|
||||||
void parse(const std::string &value) override;
|
void parse(const std::string &value) override;
|
||||||
|
|
||||||
[[nodiscard]] std::any getValue() const override;
|
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::string> value_;
|
std::vector<std::string> value_;
|
||||||
|
|||||||
@ -86,8 +86,10 @@ void Server::setupServerSocket(const ServerConfig &config)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
auto host = config["host"].get<std::string>();
|
||||||
|
auto port = config["listen"].get<int>();
|
||||||
std::unique_ptr<Socket> serverSocket = std::make_unique<Socket>();
|
std::unique_ptr<Socket> serverSocket = std::make_unique<Socket>();
|
||||||
serverSocket->bind(config["host"], config["listen"]);
|
serverSocket->bind(host, port);
|
||||||
serverSocket->listen(SOMAXCONN);
|
serverSocket->listen(SOMAXCONN);
|
||||||
int server_fd = serverSocket->getFd();
|
int server_fd = serverSocket->getFd();
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user