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);
|
||||
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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include <webserv/config/directive/ADirective.hpp> // for ADirective
|
||||
#include <webserv/config/directive/ADirective.hpp>
|
||||
|
||||
DirectiveValue ADirective::get() const
|
||||
{
|
||||
@ -14,3 +14,10 @@ void ADirective::setName(const std::string &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
|
||||
|
||||
#include <any>
|
||||
#include <webserv/config/directive/DirectiveValue.hpp>
|
||||
#include <iostream>
|
||||
#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
|
||||
{
|
||||
@ -26,36 +18,19 @@ class ADirective
|
||||
ADirective(ADirective &&other) noexcept = delete;
|
||||
ADirective &operator=(ADirective &&other) noexcept = delete;
|
||||
|
||||
virtual ~ADirective() {}
|
||||
|
||||
virtual void parse(const std::string &value) = 0;
|
||||
|
||||
[[nodiscard]] virtual std::any getValue() const = 0;
|
||||
|
||||
[[nodiscard]] DirectiveValue get() const;
|
||||
|
||||
[[nodiscard]] std::string getName() const;
|
||||
virtual ~ADirective() = default;
|
||||
|
||||
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:
|
||||
std::string name_; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
|
||||
std::string name_;
|
||||
};
|
||||
|
||||
// Supported directives:
|
||||
|
||||
// - 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}
|
||||
// Non-member stream operator for ADirective
|
||||
std::ostream &operator<<(std::ostream &os, const ADirective &directive);
|
||||
@ -24,7 +24,7 @@ void BoolDirective::parse(const std::string &arg)
|
||||
}
|
||||
}
|
||||
|
||||
std::any BoolDirective::getValue() const
|
||||
DirectiveValueType BoolDirective::getValue() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
@ -20,7 +20,7 @@ class BoolDirective : public ADirective
|
||||
|
||||
void parse(const std::string &value) override;
|
||||
|
||||
[[nodiscard]] std::any getValue() const override;
|
||||
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||
|
||||
private:
|
||||
bool value_ = false;
|
||||
|
||||
@ -3,10 +3,14 @@
|
||||
#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>
|
||||
|
||||
|
||||
|
||||
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); }},
|
||||
{"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); }},
|
||||
{"VectorDirective",
|
||||
[](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 = "root", .type = "StringDirective", .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 = "autoindex", .type = "BoolDirective", .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
|
||||
}
|
||||
|
||||
std::any IntDirective::getValue() const
|
||||
DirectiveValueType IntDirective::getValue() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
@ -20,7 +20,7 @@ class IntDirective : public ADirective
|
||||
|
||||
void parse(const std::string &value) override;
|
||||
|
||||
[[nodiscard]] std::any getValue() const override;
|
||||
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||
|
||||
private:
|
||||
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;
|
||||
}
|
||||
|
||||
std::any SizeDirective::getValue() const
|
||||
DirectiveValueType SizeDirective::getValue() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
@ -20,7 +20,7 @@ class SizeDirective : public ADirective
|
||||
|
||||
void parse(const std::string &value) override;
|
||||
|
||||
[[nodiscard]] std::any getValue() const override;
|
||||
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||
|
||||
private:
|
||||
size_t value_ = 0;
|
||||
|
||||
@ -7,7 +7,7 @@ void StringDirective::parse(const std::string &value)
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
std::any StringDirective::getValue() const
|
||||
DirectiveValueType StringDirective::getValue() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
@ -18,7 +18,7 @@ class StringDirective : public ADirective
|
||||
|
||||
void parse(const std::string &value) override;
|
||||
|
||||
[[nodiscard]] std::any getValue() const override;
|
||||
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||
|
||||
private:
|
||||
std::string value_;
|
||||
|
||||
@ -6,10 +6,10 @@
|
||||
void VectorDirective::parse(const std::string &value)
|
||||
{
|
||||
std::stringstream ss(value);
|
||||
while(ss.good())
|
||||
while (ss.good())
|
||||
{
|
||||
std::string item;
|
||||
std::getline(ss, item, ' ');// index indx.html
|
||||
std::getline(ss, item, ' '); // index indx.html
|
||||
if (!item.empty())
|
||||
{
|
||||
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_;
|
||||
}
|
||||
@ -21,7 +21,7 @@ class VectorDirective : public ADirective
|
||||
|
||||
void parse(const std::string &value) override;
|
||||
|
||||
[[nodiscard]] std::any getValue() const override;
|
||||
[[nodiscard]] DirectiveValueType getValue() const override;
|
||||
|
||||
private:
|
||||
std::vector<std::string> value_;
|
||||
|
||||
@ -86,8 +86,10 @@ void Server::setupServerSocket(const ServerConfig &config)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto host = config["host"].get<std::string>();
|
||||
auto port = config["listen"].get<int>();
|
||||
std::unique_ptr<Socket> serverSocket = std::make_unique<Socket>();
|
||||
serverSocket->bind(config["host"], config["listen"]);
|
||||
serverSocket->bind(host, port);
|
||||
serverSocket->listen(SOMAXCONN);
|
||||
int server_fd = serverSocket->getFd();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user