diff --git a/docs/class/config_class.md b/docs/class/config_class.md index 7528ac9f..78bb1c30 100644 --- a/docs/class/config_class.md +++ b/docs/class/config_class.md @@ -37,7 +37,7 @@ classDiagram -bool autoindex -string index_page -string path - -string redirect_uri + -string redirect_url -set~string~ allow_methods -string alias -string cgi_extension @@ -74,7 +74,7 @@ classDiagram -int client_max_body_size -bool autoindex -string index_page - -string redirect_uri + -string redirect_url -set~string~ allow_methods -string path -string alias diff --git a/docs/class/transaction_class.md b/docs/class/transaction_class.md index 6df6eb7f..0c625419 100644 --- a/docs/class/transaction_class.md +++ b/docs/class/transaction_class.md @@ -58,7 +58,7 @@ class Transaction { throw HTTPException(413); // ステータスコードを設定。 } if (sl.IsRedirect()) { - return ResponseBuilder.BuildRedirect(sl.redirect_uri()); + return ResponseBuilder.BuildRedirect(sl.redirect_url()); } if (sl.IsCGI()) { return CGIExecutor(req, sl); @@ -140,7 +140,7 @@ ResponseBuilder { } return new HTTPResponse(); } - HTTPResponse BuildRedirect(string redirect_uri) { + HTTPResponse BuildRedirect(string redirect_url) { // locationにredirect_urlを設定 // status_codeは302 // TODO: これとerror_pageで302が設定されていた場合 diff --git a/srcs/Config/DefaultValues.cpp b/srcs/Config/DefaultValues.cpp new file mode 100644 index 00000000..bc58289f --- /dev/null +++ b/srcs/Config/DefaultValues.cpp @@ -0,0 +1,15 @@ +#include "DefaultValues.hpp" + +#include + +const std::string DefaultValues::kServerName = ""; // NOLINT +// TODO(iyamada) +// デフォルトのpathはどうするか。正規表現で全部マッチみたいになってそう。 +const std::string DefaultValues::kPath = ""; // NOLINT +const std::string DefaultValues::kIndexPage = ""; // NOLINT +const std::string DefaultValues::kRedirectUrl = ""; // NOLINT +const std::string DefaultValues::kAlias = ""; // NOLINT +const std::string DefaultValues::kCgiExtension = ""; // NOLINT +const int DefaultValues::kPort = 80; +const int DefaultValues::kClientMaxBodySize = 1024; +const bool DefaultValues::kAutoIndex = false; diff --git a/srcs/Config/DefaultValues.hpp b/srcs/Config/DefaultValues.hpp new file mode 100644 index 00000000..db2ab9b8 --- /dev/null +++ b/srcs/Config/DefaultValues.hpp @@ -0,0 +1,22 @@ +#ifndef SRCS_CONFIG_DEFAULTVALUES_HPP_ +#define SRCS_CONFIG_DEFAULTVALUES_HPP_ + +#include + +/* + Store default directive value +*/ +class DefaultValues { + public: + static const std::string kServerName; + static const std::string kPath; + static const std::string kIndexPage; + static const std::string kRedirectUrl; + static const std::string kAlias; + static const std::string kCgiExtension; + static const int kPort; + static const int kClientMaxBodySize; + static const bool kAutoIndex; +}; + +#endif // SRCS_CONFIG_DEFAULTVALUES_HPP_ diff --git a/srcs/Config/InitialValues.cpp b/srcs/Config/InitialValues.cpp new file mode 100644 index 00000000..d2337465 --- /dev/null +++ b/srcs/Config/InitialValues.cpp @@ -0,0 +1,13 @@ +#include "InitialValues.hpp" + +#include + +const std::string InitialValues::kServerName = ""; // NOLINT +const std::string InitialValues::kPath = ""; // NOLINT +const std::string InitialValues::kIndexPage = ""; // NOLINT +const std::string InitialValues::kRedirectUrl = ""; // NOLINT +const std::string InitialValues::kAlias = ""; // NOLINT +const std::string InitialValues::kCgiExtension = ""; // NOLINT +const int InitialValues::kPort = -1; +const int InitialValues::kClientMaxBodySize = -1; +const bool InitialValues::kAutoIndex = false; diff --git a/srcs/Config/InitialValues.hpp b/srcs/Config/InitialValues.hpp new file mode 100644 index 00000000..37a9c4fd --- /dev/null +++ b/srcs/Config/InitialValues.hpp @@ -0,0 +1,22 @@ +#ifndef SRCS_CONFIG_INITIALVALUES_HPP_ +#define SRCS_CONFIG_INITIALVALUES_HPP_ + +#include + +/* + Store initial directive value +*/ +class InitialValues { + public: + static const std::string kServerName; + static const std::string kPath; + static const std::string kIndexPage; + static const std::string kRedirectUrl; + static const std::string kAlias; + static const std::string kCgiExtension; + static const int kPort; + static const int kClientMaxBodySize; + static const bool kAutoIndex; +}; + +#endif // SRCS_CONFIG_INITIALVALUES_HPP_ diff --git a/srcs/Config/LocationContext.cpp b/srcs/Config/LocationContext.cpp index 5d69ef4a..73dc6a0a 100644 --- a/srcs/Config/LocationContext.cpp +++ b/srcs/Config/LocationContext.cpp @@ -14,7 +14,7 @@ LocationContext& LocationContext::operator=(const LocationContext& other) { this->auto_index_ = other.auto_index_; this->index_page_ = other.index_page_; this->path_ = other.path_; - this->redirect_uri_ = other.redirect_uri_; + this->redirect_url_ = other.redirect_url_; this->allow_methods_ = other.allow_methods_; this->alias_ = other.alias_; this->cgi_extension_ = other.cgi_extension_; @@ -33,8 +33,8 @@ int LocationContext::client_max_body_size() const { bool LocationContext::auto_index() const { return this->auto_index_; } std::string LocationContext::index_page() const { return this->index_page_; } std::string LocationContext::path() const { return this->path_; } -std::string LocationContext::redirect_uri() const { - return this->redirect_uri_; +std::string LocationContext::redirect_url() const { + return this->redirect_url_; } std::set LocationContext::allow_methods() const { return this->allow_methods_; @@ -54,8 +54,8 @@ void LocationContext::set_index_page(const std::string& index_page) { this->index_page_ = index_page; } void LocationContext::set_path(const std::string& path) { this->path_ = path; } -void LocationContext::set_redirect_uri(const std::string& redirect_uri) { - this->redirect_uri_ = redirect_uri; +void LocationContext::set_redirect_url(const std::string& redirect_url) { + this->redirect_url_ = redirect_url; } void LocationContext::set_alias(const std::string& alias) { this->alias_ = alias; diff --git a/srcs/Config/LocationContext.hpp b/srcs/Config/LocationContext.hpp index 68f5bd2e..f0b370d3 100644 --- a/srcs/Config/LocationContext.hpp +++ b/srcs/Config/LocationContext.hpp @@ -17,7 +17,7 @@ class LocationContext { bool auto_index() const; std::string index_page() const; std::string path() const; - std::string redirect_uri() const; + std::string redirect_url() const; std::set allow_methods() const; std::string alias() const; std::string cgi_extension() const; @@ -26,7 +26,7 @@ class LocationContext { void set_auto_index(bool auto_index); void set_index_page(const std::string& index_page); void set_path(const std::string& path); - void set_redirect_uri(const std::string& redirect_uri); + void set_redirect_url(const std::string& redirect_url); void set_alias(const std::string& alias); void set_cgi_extension(const std::string& cgi_extension); @@ -39,7 +39,7 @@ class LocationContext { bool auto_index_; std::string index_page_; std::string path_; - std::string redirect_uri_; + std::string redirect_url_; std::set allow_methods_; std::string alias_; std::string cgi_extension_; diff --git a/srcs/Config/ServerContext.cpp b/srcs/Config/ServerContext.cpp index 44a6b7e8..7720a649 100644 --- a/srcs/Config/ServerContext.cpp +++ b/srcs/Config/ServerContext.cpp @@ -2,6 +2,9 @@ #include +#include "InitialValues.hpp" +#include "WebservConfig.hpp" + template static T strtonum(const std::string& s) { std::stringstream ss(s); @@ -11,7 +14,9 @@ static T strtonum(const std::string& s) { } ServerContext::ServerContext() - : client_max_body_size_(1024), auto_index_(false), port_(80) {} + : client_max_body_size_(InitialValues::kClientMaxBodySize), + auto_index_(InitialValues::kAutoIndex), + port_(InitialValues::kPort) {} ServerContext::ServerContext(const ServerContext& other) { *this = other; } diff --git a/srcs/Config/WebservConfig.cpp b/srcs/Config/WebservConfig.cpp index 569f4c9e..f09f467c 100644 --- a/srcs/Config/WebservConfig.cpp +++ b/srcs/Config/WebservConfig.cpp @@ -4,6 +4,17 @@ #include #include "ConfigProcesser.hpp" +#include "DefaultValues.hpp" +#include "InitialValues.hpp" +#include "ServerLocation.hpp" +#include "ServerLocationKey.hpp" + +template +static std::string numtostr(T num) { + std::stringstream ss; + ss << num; + return ss.str(); +} WebservConfig::WebservConfig() : client_max_body_size_(1024), auto_index_(false) {} @@ -65,23 +76,198 @@ WebservConfig WebservConfig::Parse(std::string str) { return conf_proc.Exec(); } -static ServerLocation CreateServerLocation() { - std::map error_pages; - error_pages[404] = "/404.html"; - error_pages[500] = "/50x.html"; - error_pages[501] = "/50x.html"; - error_pages[505] = "/50x.html"; - std::set allow_methods; - allow_methods.insert("GET"); - allow_methods.insert("HEAD"); - allow_methods.insert("POST"); - allow_methods.insert("DELETE"); - return ServerLocation(8081, "webserv1", "/html", error_pages, 1024, false, - "index.html", "", allow_methods, "/var/www", ""); -} - -std::vector *WebservConfig::CreateServerLocations() { - std::vector *vec = new std::vector(); - vec->push_back(CreateServerLocation()); - return vec; +static std::map JoinMap( + std::map map1, + std::map map2) { + for (std::map::iterator itr = + map2.begin(); + itr != map2.end(); ++itr) { + map1[itr->first] = itr->second; + } + return map1; +} + +static std::map JoinMaps( + std::map map1, + std::map map2) { + std::map ret; + + ret = JoinMap(ret, map1); + return JoinMap(ret, map2); +} + +static std::map CreateWithLocationContext( + LocationContext locate, ServerLocation serv_sv) { + std::map ret; + ServerLocation locate_sv; + + /* + locationコンテキストに設定できない値は、serverコンテキストの値が入る + */ + locate_sv.set_port(serv_sv.port()); + locate_sv.set_host(serv_sv.host()); + + /* + locationコンテキストに設定できる値 + */ + // error_pagesは浅いコンテキストのものを先に挿入し、現在のコンテキストを後にするとよい + locate_sv.InsertErrorPages(serv_sv.error_pages()); + locate_sv.InsertErrorPages(locate.error_pages()); + + if (locate.client_max_body_size() == InitialValues::kClientMaxBodySize) { + locate_sv.set_client_max_body_size(serv_sv.client_max_body_size()); + } else { + locate_sv.set_client_max_body_size(locate.client_max_body_size()); + } + + if (locate.alias() == InitialValues::kAlias) { + locate_sv.set_alias(serv_sv.alias()); + } else { + locate_sv.set_alias(locate.alias()); + } + + // allow_methodsが登録されていなかったらtrueになる + if (locate.allow_methods().empty()) { + locate_sv.SetDefaultAllowMethods(); + } else { + locate_sv.set_allow_methods(locate.allow_methods()); + } + + if (locate.auto_index() == InitialValues::kAutoIndex) { + locate_sv.set_auto_index(serv_sv.auto_index()); + } else { + locate_sv.set_auto_index(locate.auto_index()); + } + + if (locate.index_page() == InitialValues::kIndexPage) { + locate_sv.set_index_page(serv_sv.index_page()); + } else { + locate_sv.set_index_page(locate.index_page()); + } + + if (locate.redirect_url() == InitialValues::kRedirectUrl) { + locate_sv.set_redirect_url(serv_sv.redirect_url()); + } else { + locate_sv.set_redirect_url(locate.redirect_url()); + } + + /* + locationコンテキストでしか設定できない値 + */ + if (locate.cgi_extension() == InitialValues::kCgiExtension) { + locate_sv.set_cgi_extension(DefaultValues::kCgiExtension); + } else { + locate_sv.set_cgi_extension(locate.cgi_extension()); + } + + // pathは必ず設定されている + locate_sv.set_path(locate.path()); + + ServerLocationKey svkey(numtostr(locate_sv.port()), locate_sv.host(), + locate_sv.path()); + ret[svkey] = locate_sv; + + return ret; +} + +static std::map CreateWithServerContext( + ServerContext serv, ServerLocation http_sv) { + std::map ret; + + ServerLocation serv_sv; + + /* + serverコンテキストで設定できない値 + */ + // allow_methodsのデフォルト値は'GET', 'POST', 'DELETE'。 + // TODO(iyamada) POSTはどうする? + serv_sv.SetDefaultAllowMethods(); + + // aliasはServerContextにない + serv_sv.set_alias(DefaultValues::kAlias); + + serv_sv.set_cgi_extension(DefaultValues::kCgiExtension); + + // TODO(iyamada) デフォルトのServerLocationのpathはどうするか + serv_sv.set_path(DefaultValues::kPath); + + /* + serverコンテキストで設定できる値 + */ + // 上3つはhttpコンテキストでは設定できないので、必要ならデフォルト値をセット + if (serv.port() == InitialValues::kPort) { + serv_sv.set_port(DefaultValues::kPort); + } else { + serv_sv.set_port(serv.port()); + } + + if (serv.server_name() == InitialValues::kServerName) { + serv_sv.set_host(DefaultValues::kServerName); + } else { + serv_sv.set_host(serv.server_name()); + } + + if (serv.redirect_url() == InitialValues::kRedirectUrl) { + serv_sv.set_redirect_url(DefaultValues::kRedirectUrl); + } else { + serv_sv.set_redirect_url(serv.redirect_url()); + } + + // 以下はhttpコンテキストで設定できるので、必要ならその値をセット + // error_pagesは浅いコンテキストのものを先に挿入し、現在のコンテキストを後にするとよい + serv_sv.InsertErrorPages(http_sv.error_pages()); + serv_sv.InsertErrorPages(serv.error_pages()); + + if (serv.client_max_body_size() == InitialValues::kClientMaxBodySize) { + serv_sv.set_client_max_body_size(http_sv.client_max_body_size()); + } else { + serv_sv.set_client_max_body_size(serv.client_max_body_size()); + } + + if (serv.auto_index() == InitialValues::kAutoIndex) { + serv_sv.set_auto_index(http_sv.auto_index()); + } else { + serv_sv.set_auto_index(serv.auto_index()); + } + + if (serv.index_page() == InitialValues::kIndexPage) { + serv_sv.set_index_page(http_sv.index_page()); + } else { + serv_sv.set_index_page(serv.index_page()); + } + + // 次はlocationコンテキストを見る + std::vector locates = serv.contexts(); + for (std::vector::iterator itr = locates.begin(); + itr != locates.end(); ++itr) { + ret = JoinMaps(ret, CreateWithLocationContext(*itr, serv_sv)); + } + + // serverコンテキストのデフォルトServerLocationを登録 + ServerLocationKey svkey(numtostr(serv_sv.port()), serv_sv.host(), + serv_sv.path()); + ret[svkey] = serv_sv; + + return ret; +} + +std::map +WebservConfig::CreateServerLocations() { + std::map ret; + std::vector servs = this->contexts_; + + // httpコンテキストに値が設定されていたら、ネストされたコンテキストの値を上書きする場合があるので、後で使うために用意 + ServerLocation http_sv; + http_sv.set_error_pages(this->error_pages()); + http_sv.set_client_max_body_size(this->client_max_body_size()); + http_sv.set_auto_index(this->auto_index()); + http_sv.set_index_page(this->index_page()); + + // serverコンテキストがある場合 + for (std::vector::iterator itr = servs.begin(); + itr != servs.end(); ++itr) { + ret = JoinMaps(ret, CreateWithServerContext(*itr, http_sv)); + } + + return ret; } diff --git a/srcs/Config/WebservConfig.hpp b/srcs/Config/WebservConfig.hpp index 56405bbf..d487f058 100644 --- a/srcs/Config/WebservConfig.hpp +++ b/srcs/Config/WebservConfig.hpp @@ -8,6 +8,7 @@ #include "Logging.hpp" #include "ServerContext.hpp" #include "ServerLocation.hpp" +#include "ServerLocationKey.hpp" class WebservConfig { public: @@ -30,8 +31,9 @@ class WebservConfig { void PushErrorPage(int status_code, const std::string& error_page); static WebservConfig Parse(); + + std::map CreateServerLocations(); static WebservConfig Parse(std::string); - std::vector* CreateServerLocations(); private: std::vector contexts_; diff --git a/srcs/Transaction/Transaction.cpp b/srcs/Transaction/Transaction.cpp index abafb5fa..67c9b37a 100644 --- a/srcs/Transaction/Transaction.cpp +++ b/srcs/Transaction/Transaction.cpp @@ -26,7 +26,7 @@ HTTPResponse *Transaction::Exec(HTTPRequest *request, ServerLocation *sl) { throw HTTPException(413); } if (sl->IsRedirect()) { - return ResponseBuilder::BuildRedirect(sl->redirect_uri()); + return ResponseBuilder::BuildRedirect(sl->redirect_url()); } // TODO(takkatao): CGIの処理を実装。 /* diff --git a/srcs/Webserv/ServerLocation.cpp b/srcs/Webserv/ServerLocation.cpp index f581e916..9642d262 100644 --- a/srcs/Webserv/ServerLocation.cpp +++ b/srcs/Webserv/ServerLocation.cpp @@ -7,12 +7,13 @@ ServerLocation::ServerLocation(ServerLocation const &other) { *this = other; } ServerLocation &ServerLocation::operator=(ServerLocation const &other) { if (this != &other) { this->port_ = other.port_; + this->host_ = other.host_; this->path_ = other.path_; this->error_pages_ = other.error_pages_; this->client_max_body_size_ = other.client_max_body_size_; this->auto_index_ = other.auto_index_; this->index_page_ = other.index_page_; - this->redirect_uri_ = other.redirect_uri_; + this->redirect_url_ = other.redirect_url_; this->allow_methods_ = other.allow_methods_; this->alias_ = other.alias_; this->cgi_extension_ = other.cgi_extension_; @@ -31,7 +32,7 @@ bool ServerLocation::IsValidBodySize(int body_size) const { return true; } -bool ServerLocation::IsRedirect() const { return !this->redirect_uri_.empty(); } +bool ServerLocation::IsRedirect() const { return !this->redirect_url_.empty(); } // TODO(ahayashi): 実装する。utilsに移してもいいかもしれない。 static std::string GetExtension(std::string path) { @@ -57,8 +58,8 @@ int ServerLocation::client_max_body_size() const { } bool ServerLocation::auto_index() const { return auto_index_; } const std::string &ServerLocation::index_page() const { return index_page_; } -const std::string &ServerLocation::redirect_uri() const { - return redirect_uri_; +const std::string &ServerLocation::redirect_url() const { + return redirect_url_; } const std::set &ServerLocation::allow_methods() const { return allow_methods_; @@ -67,11 +68,59 @@ const std::string &ServerLocation::alias() const { return alias_; } const std::string &ServerLocation::cgi_extension() const { return cgi_extension_; } + +void ServerLocation::set_port(int port) { this->port_ = port; } +void ServerLocation::set_host(const std::string &host) { this->host_ = host; } +void ServerLocation::set_path(const std::string &path) { this->path_ = path; } +void ServerLocation::set_error_pages( + const std::map &error_pages) { + this->error_pages_ = error_pages; +} +void ServerLocation::set_client_max_body_size(int client_max_body_size) { + this->client_max_body_size_ = client_max_body_size; +} +void ServerLocation::set_auto_index(bool auto_index) { + this->auto_index_ = auto_index; +} +void ServerLocation::set_index_page(const std::string &index_page) { + this->index_page_ = index_page; +} +void ServerLocation::set_redirect_url(const std::string &redirect_url) { + this->redirect_url_ = redirect_url; +} +void ServerLocation::set_allow_methods( + const std::set &allow_methods) { + this->allow_methods_ = allow_methods; +} +void ServerLocation::set_alias(const std::string &alias) { + this->alias_ = alias; +} +void ServerLocation::set_cgi_extension(const std::string &cgi_extension) { + this->cgi_extension_ = cgi_extension; +} + +void ServerLocation::InsertErrorPages( + const std::map &error_pages) { + // std::copy(error_pages.begin(), error_pages.end(), + // std::back_inserter(this->error_pages_)); + for (std::map::const_iterator itr = error_pages.begin(); + itr != error_pages.end(); ++itr) { + this->error_pages_[itr->first] = itr->second; + } +} + +// TODO(iyamada) HEADも追加するかも +void ServerLocation::SetDefaultAllowMethods() { + this->allow_methods_.insert("GET"); + this->allow_methods_.insert("POST"); + this->allow_methods_.insert("DELETE"); +} + ServerLocation::ServerLocation( int port, const std::string &host, const std::string &path, const std::map &error_pages, int client_max_body_size, bool auto_index, const std::string &index_page, - const std::string &redirect_uri, const std::set &allow_methods, + const std::string &redirect_url, const std::set &allow_methods, const std::string &alias, const std::string &cgi_extension) : port_(port), host_(host), @@ -80,7 +129,7 @@ ServerLocation::ServerLocation( client_max_body_size_(client_max_body_size), auto_index_(auto_index), index_page_(index_page), - redirect_uri_(redirect_uri), + redirect_url_(redirect_url), allow_methods_(allow_methods), alias_(alias), cgi_extension_(cgi_extension) {} diff --git a/srcs/Webserv/ServerLocation.hpp b/srcs/Webserv/ServerLocation.hpp index b979823b..cf73a8cf 100644 --- a/srcs/Webserv/ServerLocation.hpp +++ b/srcs/Webserv/ServerLocation.hpp @@ -15,7 +15,7 @@ class ServerLocation { const std::map &error_pages, int client_max_body_size, bool auto_index, const std::string &index_page, - const std::string &redirect_uri, + const std::string &redirect_url, const std::set &allow_methods, const std::string &alias, const std::string &cgi_extension); ServerLocation &operator=(ServerLocation const &other); @@ -28,10 +28,26 @@ class ServerLocation { int client_max_body_size() const; bool auto_index() const; const std::string &index_page() const; - const std::string &redirect_uri() const; + const std::string &redirect_url() const; const std::set &allow_methods() const; const std::string &alias() const; const std::string &cgi_extension() const; + + void set_port(int port); + void set_host(const std::string &host); + void set_path(const std::string &path); + void set_error_pages(const std::map &error_pages); + void set_client_max_body_size(int client_max_body_size); + void set_auto_index(bool auto_index); + void set_index_page(const std::string &index_page); + void set_redirect_url(const std::string &redirect_url); + void set_allow_methods(const std::set &allow_methods); + void set_alias(const std::string &alias); + void set_cgi_extension(const std::string &cgi_extension); + + void InsertErrorPages(const std::map &error_pages); + void SetDefaultAllowMethods(); + bool IsAllowedMethod(std::string) const; bool IsValidBodySize(int) const; bool IsRedirect() const; @@ -46,7 +62,7 @@ class ServerLocation { int client_max_body_size_; bool auto_index_; std::string index_page_; - std::string redirect_uri_; + std::string redirect_url_; std::set allow_methods_; std::string alias_; std::string cgi_extension_; diff --git a/srcs/Webserv/ServerLocationFacade.cpp b/srcs/Webserv/ServerLocationFacade.cpp index 458a5c93..d8a08dd2 100644 --- a/srcs/Webserv/ServerLocationFacade.cpp +++ b/srcs/Webserv/ServerLocationFacade.cpp @@ -1,9 +1,14 @@ #include "ServerLocationFacade.hpp" +#include + +#include "ServerLocationKey.hpp" + ServerLocationFacade::ServerLocationFacade() {} -ServerLocationFacade::ServerLocationFacade(std::vector *vec) - : server_locations_(vec) {} +ServerLocationFacade::ServerLocationFacade( + std::map server_locations) + : server_locations_(server_locations) {} ServerLocationFacade::ServerLocationFacade(ServerLocationFacade const &other) { *this = other; @@ -20,11 +25,13 @@ ServerLocationFacade &ServerLocationFacade::operator=( ServerLocationFacade::~ServerLocationFacade() {} ServerLocation *ServerLocationFacade::Choose(std::string port, std::string host, - std::string path) const { + std::string path) { (void)port; (void)host; (void)path; - return &(this->server_locations_->at(0)); + std::map::iterator itr = + this->server_locations_.begin(); + return &(itr->second); } std::vector ServerLocationFacade::GetPorts() const { diff --git a/srcs/Webserv/ServerLocationFacade.hpp b/srcs/Webserv/ServerLocationFacade.hpp index 30d9b02d..fad58320 100644 --- a/srcs/Webserv/ServerLocationFacade.hpp +++ b/srcs/Webserv/ServerLocationFacade.hpp @@ -1,26 +1,29 @@ #ifndef SRCS_WEBSERV_SERVERLOCATIONFACADE_HPP_ #define SRCS_WEBSERV_SERVERLOCATIONFACADE_HPP_ +#include #include #include #include "Logging.hpp" #include "ServerLocation.hpp" +#include "ServerLocationKey.hpp" class ServerLocationFacade { public: ServerLocationFacade(); ServerLocationFacade(ServerLocationFacade const &other); - explicit ServerLocationFacade(std::vector *); + explicit ServerLocationFacade( + std::map server_locations); ServerLocationFacade &operator=(ServerLocationFacade const &other); ~ServerLocationFacade(); ServerLocation *Choose(std::string port, std::string host, - std::string path) const; + std::string path); std::vector GetPorts() const; private: - std::vector *server_locations_; + std::map server_locations_; }; #endif // SRCS_WEBSERV_SERVERLOCATIONFACADE_HPP_ diff --git a/srcs/Webserv/ServerLocationKey.cpp b/srcs/Webserv/ServerLocationKey.cpp new file mode 100644 index 00000000..4dff35a7 --- /dev/null +++ b/srcs/Webserv/ServerLocationKey.cpp @@ -0,0 +1,14 @@ +#include "ServerLocationKey.hpp" + +#include + +ServerLocationKey::ServerLocationKey(std::string port, std::string host, + std::string path) + : port_(port), host_(host), path_(path) {} + +bool ServerLocationKey::operator<(const ServerLocationKey &rhs) const { + return ((this->port_ < rhs.port_) || + (this->port_ == rhs.port_ && this->host_ < rhs.host_) || + (this->port_ == rhs.port_ && this->host_ == rhs.host_ && + this->path_ < rhs.path_)); +} diff --git a/srcs/Webserv/ServerLocationKey.hpp b/srcs/Webserv/ServerLocationKey.hpp new file mode 100644 index 00000000..9942e5fd --- /dev/null +++ b/srcs/Webserv/ServerLocationKey.hpp @@ -0,0 +1,18 @@ +#ifndef SRCS_WEBSERV_SERVERLOCATIONKEY_HPP_ +#define SRCS_WEBSERV_SERVERLOCATIONKEY_HPP_ + +#include + +class ServerLocationKey { + public: + ServerLocationKey(std::string port, std::string host, std::string path); + + bool operator<(const ServerLocationKey &rhs) const; + + private: + std::string port_; + std::string host_; + std::string path_; +}; + +#endif // SRCS_WEBSERV_SERVERLOCATIONKEY_HPP_ diff --git a/srcs/Webserv/Webserv.cpp b/srcs/Webserv/Webserv.cpp index 56b892fe..89ad741d 100644 --- a/srcs/Webserv/Webserv.cpp +++ b/srcs/Webserv/Webserv.cpp @@ -1,7 +1,7 @@ #include "Webserv.hpp" +#include #include -#include #include "ServerLocation.hpp" #include "ServerLocationFacade.hpp" @@ -22,6 +22,7 @@ Webserv &Webserv::operator=(Webserv const &other) { Webserv::~Webserv() {} void Webserv::Run(int argc, char **argv) { + this->logging_.Debug(argv[0]); WebservConfig config; // TODO(takkatao): 引数の数が多い時のエラー処理を追加。 if (argc == 2) { @@ -31,7 +32,8 @@ void Webserv::Run(int argc, char **argv) { this->logging_.Debug("config : default"); config = WebservConfig::Parse(); } - std::vector *locations = config.CreateServerLocations(); + std::map locations = + config.CreateServerLocations(); ServerLocationFacade facade(locations); SuperVisor sv(facade); sv.Watch(); diff --git a/tests/unit_test/CMakeLists.txt b/tests/unit_test/CMakeLists.txt index aa65befb..dee37d0f 100644 --- a/tests/unit_test/CMakeLists.txt +++ b/tests/unit_test/CMakeLists.txt @@ -19,6 +19,7 @@ add_executable(main utils.cpp HTTP.cpp ConfigParser.cpp + CreateServerLocation.cpp Transaction.cpp ) diff --git a/tests/unit_test/ConfigParser.cpp b/tests/unit_test/ConfigParser.cpp index f689ad8c..de70dcb0 100644 --- a/tests/unit_test/ConfigParser.cpp +++ b/tests/unit_test/ConfigParser.cpp @@ -19,10 +19,6 @@ TEST_F(ConfigParserTest, LocationContextInServerContext) { WebservConfig conf = confproc.Exec(); ASSERT_EQ(conf.contexts().size(), 1); - ASSERT_EQ(conf.error_pages().empty(), true); - ASSERT_EQ(conf.client_max_body_size(), 1024); - ASSERT_EQ(conf.auto_index(), false); - ASSERT_EQ(conf.index_page(), ""); std::vector serv_contexts = conf.contexts(); @@ -31,27 +27,13 @@ TEST_F(ConfigParserTest, LocationContextInServerContext) { ServerContext serv_context = serv_contexts.at(0); ASSERT_EQ(serv_context.contexts().size(), 1); - ASSERT_EQ(serv_context.error_pages().empty(), true); - ASSERT_EQ(serv_context.client_max_body_size(), 1024); - ASSERT_EQ(serv_context.auto_index(), false); - ASSERT_EQ(serv_context.index_page(), ""); - ASSERT_EQ(serv_context.redirect_url(), ""); - ASSERT_EQ(serv_context.server_name(), ""); ASSERT_EQ(serv_context.port(), 80); std::vector locate_contexts = serv_context.contexts(); ASSERT_EQ(locate_contexts.size(), 1); LocationContext locate_context = locate_contexts.at(0); - - ASSERT_EQ(locate_context.error_pages().empty(), true); - ASSERT_EQ(locate_context.client_max_body_size(), 1024); - ASSERT_EQ(locate_context.auto_index(), false); - ASSERT_EQ(locate_context.index_page(), ""); - ASSERT_EQ(locate_context.allow_methods().empty(), true); ASSERT_EQ(locate_context.alias(), "/var/www/html"); - ASSERT_EQ(locate_context.path(), "/"); - ASSERT_EQ(locate_context.redirect_uri(), ""); } TEST_F(ConfigParserTest, autoindex_on_location) { diff --git a/tests/unit_test/CreateServerLocation.cpp b/tests/unit_test/CreateServerLocation.cpp new file mode 100644 index 00000000..5c514e5b --- /dev/null +++ b/tests/unit_test/CreateServerLocation.cpp @@ -0,0 +1,259 @@ +#include +#include + +#include "DefaultValues.hpp" +#include "LocationContext.hpp" +#include "ServerContext.hpp" +#include "ServerLocation.hpp" +#include "ServerLocationKey.hpp" +#include "WebservConfig.hpp" + +class CreateServerLocationTest : public ::testing::Test { + protected: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + virtual void SetUp() {} + virtual void TearDown() {} +}; + +TEST_F(CreateServerLocationTest, single_ServerLocation) { + /* 想定したconfigファイル + server { + listen 8080; + } + */ + WebservConfig conf; + ServerContext serv_contx; + + serv_contx.set_port(8080); + conf.PushServerContext(serv_contx); + + std::map sl_container = + conf.CreateServerLocations(); + + ASSERT_EQ(sl_container.size(), 1); + + std::map::iterator itr = + sl_container.begin(); + + ASSERT_EQ(itr->second.port(), 8080); +} + +TEST_F(CreateServerLocationTest, two_ServerLocations) { + /* 想定したconfigファイル + server { + listen 8080; + location / { + alias /var/www/html; + } + } + */ + WebservConfig conf; + ServerContext serv_contx; + LocationContext locate_contx; + + locate_contx.set_path("/"); + locate_contx.set_alias("/var/www/html"); + + serv_contx.set_port(8080); + serv_contx.PushLocationContext(locate_contx); + + conf.PushServerContext(serv_contx); + + std::map sl_container = + conf.CreateServerLocations(); + + ASSERT_EQ(sl_container.size(), 2); + + // serverコンテキストのServerLocationをチェック + ServerLocationKey serv_key("8080", "", ""); + ServerLocation serv_sl = sl_container[serv_key]; + + ASSERT_EQ(serv_sl.port(), 8080); + + // locationコンテキストのServerLocationをチェック + ServerLocationKey locate_key("8080", "", "/"); + ServerLocation locate_sl = sl_container[locate_key]; + + ASSERT_EQ(locate_sl.port(), 8080); + ASSERT_EQ(locate_sl.path(), "/"); + ASSERT_EQ(locate_sl.alias(), "/var/www/html"); +} + +TEST_F(CreateServerLocationTest, two_server_contexts) { + /* 想定したconfigファイル + server { + listen 8080; + } + server { + listen 8081; + } + */ + WebservConfig conf; + ServerContext serv_contx1; + ServerContext serv_contx2; + + serv_contx1.set_port(8080); + serv_contx2.set_port(8081); + + conf.PushServerContext(serv_contx1); + conf.PushServerContext(serv_contx2); + + std::map sl_container = + conf.CreateServerLocations(); + + ASSERT_EQ(sl_container.size(), 2); + + // serverコンテキストのServerLocationをチェック + ServerLocationKey serv_key("8080", "", ""); + ServerLocation serv_sl = sl_container[serv_key]; + + ASSERT_EQ(serv_sl.port(), 8080); + + // locationコンテキストのServerLocationをチェック + ServerLocationKey locate_key("8081", "", ""); + ServerLocation locate_sl = sl_container[locate_key]; + + ASSERT_EQ(locate_sl.port(), 8081); +} + +TEST_F(CreateServerLocationTest, two_location_contexts) { + /* 想定したconfigファイル + server { + listen 8080; + location / { + alias /var/www/html; + } + location /hoge { + alias /var/www/hoge; + } + } + */ + WebservConfig conf; + ServerContext serv_contx; + LocationContext locate_contx1; + LocationContext locate_contx2; + + locate_contx1.set_path("/"); + locate_contx1.set_alias("/var/www/html"); + locate_contx2.set_path("/hoge"); + locate_contx2.set_alias("/var/www/hoge"); + + serv_contx.set_port(8080); + serv_contx.PushLocationContext(locate_contx1); + serv_contx.PushLocationContext(locate_contx2); + + conf.PushServerContext(serv_contx); + + std::map sl_container = + conf.CreateServerLocations(); + + ASSERT_EQ(sl_container.size(), 3); + + // serverコンテキストのServerLocationをチェック + ServerLocationKey serv_key("8080", "", ""); + ServerLocation serv_sl = sl_container[serv_key]; + + ASSERT_EQ(serv_sl.port(), 8080); + + // locationコンテキストのServerLocationをチェック + ServerLocationKey locate_key1("8080", "", "/"); + ServerLocation locate_sl1 = sl_container[locate_key1]; + + ASSERT_EQ(locate_sl1.port(), 8080); + ASSERT_EQ(locate_sl1.path(), "/"); + ASSERT_EQ(locate_sl1.alias(), "/var/www/html"); + + ServerLocationKey locate_key2("8080", "", "/hoge"); + ServerLocation locate_sl2 = sl_container[locate_key2]; + + ASSERT_EQ(locate_sl2.port(), 8080); + ASSERT_EQ(locate_sl2.path(), "/hoge"); + ASSERT_EQ(locate_sl2.alias(), "/var/www/hoge"); +} + +class DISABLED_CreateServerLocationTest : public ::testing::Test { + protected: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + virtual void SetUp() {} + virtual void TearDown() {} +}; + +/* + autoindexをboolで持っているため、autoindex + offが設定されているか、設定されていないかが判断できない。だから浅いコンテキストの値で上書きされてしまう +*/ +TEST_F(DISABLED_CreateServerLocationTest, complex_test) { + /* 想定したconfigファイル + autoindex on; + server { + listen 8080; + location / { + alias /var/www/html; + } + location /hoge { + alias /var/www/hoge; + } + } + server { + listen 81; + autoindex off; + } + */ + WebservConfig conf; + ServerContext serv_contx1; + ServerContext serv_contx2; + LocationContext locate_contx1; + LocationContext locate_contx2; + + locate_contx1.set_path("/"); + locate_contx1.set_alias("/var/www/html"); + locate_contx2.set_path("/hoge"); + locate_contx2.set_alias("/var/www/hoge"); + + serv_contx1.set_port(8080); + serv_contx1.PushLocationContext(locate_contx1); + serv_contx1.PushLocationContext(locate_contx2); + serv_contx2.set_port(81); + serv_contx2.set_auto_index(false); + + conf.PushServerContext(serv_contx1); + conf.PushServerContext(serv_contx2); + conf.set_auto_index(true); + + std::map sl_container = + conf.CreateServerLocations(); + + ASSERT_EQ(sl_container.size(), 4); + + // serverコンテキストのServerLocationをチェック + ServerLocationKey serv_key1("8080", "", ""); + ServerLocation serv_sl1 = sl_container[serv_key1]; + + ASSERT_EQ(serv_sl1.port(), 8080); + ASSERT_EQ(serv_sl1.auto_index(), true); + + ServerLocationKey serv_key2("81", "", ""); + ServerLocation serv_sl2 = sl_container[serv_key2]; + + ASSERT_EQ(serv_sl2.port(), 81); + ASSERT_EQ(serv_sl2.auto_index(), false); + + // locationコンテキストのServerLocationをチェック + ServerLocationKey locate_key1("8080", "", "/"); + ServerLocation locate_sl1 = sl_container[locate_key1]; + + ASSERT_EQ(locate_sl1.port(), 8080); + ASSERT_EQ(locate_sl1.auto_index(), true); + ASSERT_EQ(locate_sl1.path(), "/"); + ASSERT_EQ(locate_sl1.alias(), "/var/www/html"); + + ServerLocationKey locate_key2("8080", "", "/hoge"); + ServerLocation locate_sl2 = sl_container[locate_key2]; + + ASSERT_EQ(locate_sl2.port(), 8080); + ASSERT_EQ(locate_sl2.auto_index(), true); + ASSERT_EQ(locate_sl2.path(), "/hoge"); + ASSERT_EQ(locate_sl2.alias(), "/var/www/hoge"); +}