From ab82a1a6afdceb915ef549c33b2193adb83fccd8 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Wed, 6 Dec 2023 11:18:12 +0100 Subject: [PATCH 01/34] added TODO --- src/Poll.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Poll.cpp b/src/Poll.cpp index 2262a66..22978d0 100644 --- a/src/Poll.cpp +++ b/src/Poll.cpp @@ -42,9 +42,13 @@ void Poll::pollFDs(void) Logger &logger = Logger::getInstance(); logger.log(INFO, "Polling " + std::to_string(_poll_fds.size()) + " file descriptors"); - int poll_count = poll(_poll_fds.data(), _poll_fds.size(), NO_TIMEOUT); + int poll_count = + poll(_poll_fds.data(), _poll_fds.size(), + NO_TIMEOUT); // TODO: NO_TIMEOUT is an issue. We need to make sure + // Poll will time out certain Clients (e.g. Clients + // won't send anymore bytes after first 10 bytes) if (poll_count == SYSTEM_ERROR || poll_count == 0) - throw SystemException("poll"); // TODO change poll_count 0 handler + throw SystemException("poll"); // TODO: change poll_count 0 handler } std::string Poll::pollEventsToString(short events) const From 6db314b1ab194026aa74e369c3c7cd42b89a17d6 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Fri, 8 Dec 2023 18:57:15 +0100 Subject: [PATCH 02/34] added TODO; minor refactor --- config/default.conf | 16 +++++++++++++++- include/Token.hpp | 1 - src/ConfigParser.cpp | 1 - src/ConfigSyntax.cpp | 1 - src/HTTPServer.cpp | 2 ++ src/Token.cpp | 2 -- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/config/default.conf b/config/default.conf index 9e76bbc..b6d9b7d 100644 --- a/config/default.conf +++ b/config/default.conf @@ -25,7 +25,7 @@ server { location /python/ { alias /cgi/python; # already defined; - cgi .py /bin/python3; # [1 - O] Set a Path to where the CGI can find the Binary; [A-Za-z_/.]* ; Default: [EMPTY] + cgi /bin/python3; # [1 - O] Set a Path to where the CGI can find the Binary; [A-Za-z_/.]* ; Default: [EMPTY] } location /images/ { @@ -43,3 +43,17 @@ server { return localhost; # [1 - O] Reroute a directory to another URL; URL ; Default: [] } } +# +#www.google.com /python/test.py /bin/usr/foo ? +# +# TODO: alias still needs to replace URI; +# TODO: +# +#GET www.google.com/ +# /data/www/index.html +# +#GET www.google.com/python/test.py +# /cgi/python/test.py +# +#GET www.google.com/images/puppy.png +# /data/images/puppy.png diff --git a/include/Token.hpp b/include/Token.hpp index 4be8dec..4d24beb 100644 --- a/include/Token.hpp +++ b/include/Token.hpp @@ -13,7 +13,6 @@ enum class TokenType SEMICOLON, OPEN_BRACKET, CLOSE_BRACKET, - PATH, WORD, }; diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index fe4d1a3..5598117 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -6,7 +6,6 @@ #include #include -#include #include #include #include diff --git a/src/ConfigSyntax.cpp b/src/ConfigSyntax.cpp index 2ddc11e..a00b51c 100644 --- a/src/ConfigSyntax.cpp +++ b/src/ConfigSyntax.cpp @@ -99,7 +99,6 @@ void syntaxLocationBlock(std::vector &tokens, while (it != closing_token) { - syntaxLine(it); it++; } diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index 5aec298..8142106 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -101,6 +101,8 @@ void HTTPServer::handleNewConnection(int fd) std::shared_ptr client = std::make_shared(fd); _active_clients.emplace(client->getFD(), client); _poll.addPollFD(client->getFD(), POLLIN); + // TODO: 1. Serversetting need to be added to client class + // 2. } void HTTPServer::handleExistingConnection(const pollfd &poll_fd) diff --git a/src/Token.cpp b/src/Token.cpp index 4a3419f..67dbc4d 100644 --- a/src/Token.cpp +++ b/src/Token.cpp @@ -110,8 +110,6 @@ std::string Token::typeToString() const return ("OPEN_BRACKET"); case TokenType::CLOSE_BRACKET: return ("CLOSE_BRACKET"); - case TokenType::PATH: - return ("PATH"); case TokenType::WORD: return ("WORD"); } From c865cce1c55d53fbc1c8ee4bd09a5cdd51868b87 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Sun, 10 Dec 2023 17:04:29 +0100 Subject: [PATCH 03/34] minor change --- config/default.conf | 8 +++++--- src/LocationSettings.cpp | 11 ++++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/config/default.conf b/config/default.conf index b6d9b7d..990378a 100644 --- a/config/default.conf +++ b/config/default.conf @@ -29,8 +29,8 @@ server { } location /images/ { - root /data/images; # already defined; - allow_methods GET POST; # already defined; + alias /data/images; # already defined; + allowed_methods GET POST; # already defined; autoindex off; # already defined; } @@ -43,11 +43,13 @@ server { return localhost; # [1 - O] Reroute a directory to another URL; URL ; Default: [] } } + # #www.google.com /python/test.py /bin/usr/foo ? # # TODO: alias still needs to replace URI; -# TODO: +# TODO: autoindex +# TODO: # #GET www.google.com/ # /data/www/index.html diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index 887fa68..db4919f 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -47,7 +47,7 @@ LocationSettings::LocationSettings(std::vector::iterator &token) parseAutoIndex(*token); else if (key.getString() == "allowed_methods") parseAllowedMethods(*token); - else if (key.getString() == "cgi_path") + else if (key.getString() == "cgi") parseCgiPath(*token); else if (key.getString() == "return") parseReturn(*token); @@ -106,8 +106,13 @@ void LocationSettings::parseAllowedMethods(const Token token) void LocationSettings::parseCgiPath(const Token token) { + Logger &logger = Logger::getInstance(); - _cgi_path.append(" " + token.getString()); + if (!_index.empty()) + logger.log(WARNING, + "ConfigParser: redefining index in locationblock: " + + _requesttarget); + _cgi_path = token.getString(); } void LocationSettings::parseReturn(const Token token) @@ -118,7 +123,7 @@ void LocationSettings::parseReturn(const Token token) logger.log(WARNING, "ConfigParser: redefining return in locationblock: " + _requesttarget); - _return.append(" " + token.getString()); + _return = token.getString(); } // Functionality: From acf7559fad79bd492b497c7dbe48a00d98c74c42 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Fri, 15 Dec 2023 16:47:18 +0100 Subject: [PATCH 04/34] working in Listen, reworked resolveLocation --- config/default.conf | 28 ++++++++++++------ config/test.conf | 10 +++++++ include/Client.hpp | 2 ++ include/HTTPRequest.hpp | 2 +- include/LocationSettings.hpp | 9 ++---- include/ServerSettings.hpp | 6 +++- include/Socket.hpp | 4 +++ src/HTTPServer.cpp | 2 +- src/LocationSettings.cpp | 52 +++++++++++++++++++-------------- src/ServerSettings.cpp | 56 ++++++++++++++++++------------------ src/Socket.cpp | 24 +++++++++++++--- 11 files changed, 125 insertions(+), 70 deletions(-) create mode 100644 config/test.conf diff --git a/config/default.conf b/config/default.conf index 990378a..46f3436 100644 --- a/config/default.conf +++ b/config/default.conf @@ -29,14 +29,14 @@ server { } location /images/ { - alias /data/images; # already defined; - allowed_methods GET POST; # already defined; - autoindex off; # already defined; + alias /data/images; + allowed_methods GET POST; + autoindex off; } location /upload/ { - root /data/upload; - allowed_moteds POST DELETE; + alias /data/upload; + allowed_methods POST DELETE; } location /removed_folder/ { @@ -47,9 +47,21 @@ server { # #www.google.com /python/test.py /bin/usr/foo ? # -# TODO: alias still needs to replace URI; -# TODO: autoindex -# TODO: +# TODO: all Settings still need implementation into the Webserver +# [ ] ServerBlock: +# [ ] listen; // +# [ ] server_name; // should go over the Clients/HTTPServers after +# // the request is recieved and see which serverSettings block is relevant to the request; +# [ ] error_dir; // should search this direcotry to find the relevant error file [e.g. 404.html]; +# [ ] client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; +# [ ] Location Block: +# [ ] alias; // should do a fitted preppend on the path in URI; +# [ ] index; // file return of the request just specifies this directory ; +# [ ] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; +# [ ] allowed_methods; // should check if the HTTP Method is allowed in this location; +# [ ] cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; +# [ ] return; // +# # #GET www.google.com/ # /data/www/index.html diff --git a/config/test.conf b/config/test.conf new file mode 100644 index 0000000..416c7a8 --- /dev/null +++ b/config/test.conf @@ -0,0 +1,10 @@ +# Server Configuration + +server { + location / { + alias /data/www; + } +} + + + diff --git a/include/Client.hpp b/include/Client.hpp index fb0e010..e9a862f 100644 --- a/include/Client.hpp +++ b/include/Client.hpp @@ -1,6 +1,7 @@ #ifndef CLIENT_HPP #define CLIENT_HPP +#include "ServerSettings.hpp" #include #include #include @@ -25,6 +26,7 @@ class Client FileManager _file_manager; CGI _cgi; Socket _socket; + ServerSettings _ServerSetting; // TODO: make multiple serverblocks work; ClientState _state; }; diff --git a/include/HTTPRequest.hpp b/include/HTTPRequest.hpp index ca893a7..8c19437 100644 --- a/include/HTTPRequest.hpp +++ b/include/HTTPRequest.hpp @@ -29,7 +29,7 @@ class HTTPRequest public: HTTPRequest(); HTTPRequest(const HTTPRequest &rhs) = delete; - HTTPRequest &operator=(const HTTPRequest &other) = delete; + HTTPRequest &operator=(const HTTPRequest &rhs) = delete; ~HTTPRequest(); void setMethodType(const std::string &method_type); diff --git a/include/LocationSettings.hpp b/include/LocationSettings.hpp index 6f07610..4d71067 100644 --- a/include/LocationSettings.hpp +++ b/include/LocationSettings.hpp @@ -12,25 +12,22 @@ class LocationSettings ~LocationSettings(); LocationSettings(std::vector::iterator &token); LocationSettings(const LocationSettings &rhs); - LocationSettings &operator=(const LocationSettings &rhs) = delete; + LocationSettings &operator=(LocationSettings &rhs); // Functionality: // getters: - const std::string &getRequestTarget() const; + const std::string &getPath() const; const std::string &getAlias() const; const std::string &getIndex() const; const std::string &getAllowedMethods() const; const std::string &getReturn() const; bool getAutoIndex() const; - // setters: - void setDir(const std::string &path); - // Printing: void printLocationSettings() const; private: - std::string _requesttarget; + std::string _path; std::string _alias; std::string _index; diff --git a/include/ServerSettings.hpp b/include/ServerSettings.hpp index 31889a0..8394c2f 100644 --- a/include/ServerSettings.hpp +++ b/include/ServerSettings.hpp @@ -17,7 +17,9 @@ class ServerSettings ServerSettings &operator=(const ServerSettings &rhs) = delete; // Functionality: - const LocationSettings &resolveLocation(const std::string &request_target); + const LocationSettings &resolveLocation(const std::string &URI) const; + bool resolveServerName(const std::string &RequestHost); + const std::string &getListen() const; const std::string &getServerName() const; const std::string &getErrorDir() const; @@ -33,6 +35,8 @@ class ServerSettings std::string _client_max_body_size; std::vector _location_settings; + const LocationSettings &getRootLocationBlock() const; + // Parsing: void addValueToServerSettings(const Token &key, std::vector::iterator &value); diff --git a/include/Socket.hpp b/include/Socket.hpp index 14ca090..3152523 100644 --- a/include/Socket.hpp +++ b/include/Socket.hpp @@ -4,6 +4,10 @@ #include #include +#include +#include +#include + #define MAX_PENDING_CONNECTIONS 10 typedef struct sockaddr_in t_sockaddr_in; diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index 8142106..cc06199 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -102,7 +102,7 @@ void HTTPServer::handleNewConnection(int fd) _active_clients.emplace(client->getFD(), client); _poll.addPollFD(client->getFD(), POLLIN); // TODO: 1. Serversetting need to be added to client class - // 2. + // } void HTTPServer::handleExistingConnection(const pollfd &poll_fd) diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index db4919f..57b0979 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -7,27 +7,44 @@ #include LocationSettings::LocationSettings() - : _requesttarget(), _alias(), _index(), _allowed_methods(), _cgi_path(), + : _path(), _alias(), _index(), _allowed_methods(), _cgi_path(), _auto_index() { } LocationSettings::LocationSettings(const LocationSettings &rhs) - : _requesttarget(rhs._requesttarget), _alias(rhs._alias), - _index(rhs._index), _allowed_methods(rhs._allowed_methods), - _cgi_path(rhs._cgi_path), _auto_index(rhs._auto_index) + : _path(rhs._path), _alias(rhs._alias), _index(rhs._index), + _allowed_methods(rhs._allowed_methods), _cgi_path(rhs._cgi_path), + _auto_index(rhs._auto_index) { } +LocationSettings &LocationSettings::operator=(LocationSettings &rhs) +{ + if (this == &rhs) + return (*this); + + _path = rhs._path; + + _alias = rhs._alias; + _index = rhs._index; + _allowed_methods = rhs._allowed_methods; + _cgi_path = rhs._cgi_path; + _return = rhs._return; + _auto_index = rhs._auto_index; + + return (*this); +} + LocationSettings::~LocationSettings() { } LocationSettings::LocationSettings(std::vector::iterator &token) - : _requesttarget(), _alias(), _index(), _allowed_methods(), _cgi_path(), + : _path(), _alias(), _index(), _allowed_methods(), _cgi_path(), _auto_index() { - _requesttarget = token->getString(); + _path = token->getString(); token += 2; while (token->getType() != TokenType::CLOSE_BRACKET) @@ -67,8 +84,7 @@ void LocationSettings::parseAlias(const Token token) if (!_alias.empty()) logger.log(WARNING, - "ConfigParser: redefining alias in locationblock: " + - _requesttarget); + "ConfigParser: redefining alias in locationblock: " + _path); _alias = token.getString(); } @@ -78,8 +94,7 @@ void LocationSettings::parseIndex(const Token token) if (!_index.empty()) logger.log(WARNING, - "ConfigParser: redefining index in locationblock: " + - _requesttarget); + "ConfigParser: redefining index in locationblock: " + _path); _index = token.getString(); } @@ -110,8 +125,7 @@ void LocationSettings::parseCgiPath(const Token token) if (!_index.empty()) logger.log(WARNING, - "ConfigParser: redefining index in locationblock: " + - _requesttarget); + "ConfigParser: redefining index in locationblock: " + _path); _cgi_path = token.getString(); } @@ -122,15 +136,15 @@ void LocationSettings::parseReturn(const Token token) if (!_return.empty()) logger.log(WARNING, "ConfigParser: redefining return in locationblock: " + - _requesttarget); + _path); _return = token.getString(); } // Functionality: // getters: -const std::string &LocationSettings::getRequestTarget() const +const std::string &LocationSettings::getPath() const { - return (_requesttarget); + return (_path); } const std::string &LocationSettings::getAlias() const @@ -158,11 +172,7 @@ const std::string &LocationSettings::getReturn() const return (_return); } -// setters: -void LocationSettings::setDir(const std::string &requesttarget) -{ - _requesttarget = requesttarget; -} +// // THIS IS PRINTING FUNCTION @@ -170,7 +180,7 @@ void LocationSettings::printLocationSettings() const { Logger &logger = Logger::getInstance(); - logger.log(DEBUG, "\tLocation Prefix:\t" + _requesttarget); + logger.log(DEBUG, "\tLocation Prefix:\t" + _path); logger.log(DEBUG, "\t\tAlias:\t\t\t" + _alias); logger.log(DEBUG, "\t\tIndex:\t\t\t" + _index); logger.log(DEBUG, "\t\tAllowed_methods:\t" + _allowed_methods); diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index 7eab019..c8423f4 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -73,8 +73,12 @@ void validateListen(const std::string &str) void ServerSettings::parseListen(const Token value) { + Logger &logger = Logger::getInstance(); validateListen(value.getString()); - _listen.append(" " + value.getString()); + + if (!_listen.empty()) + logger.log(WARNING, "ConfigParser: redefining listen"); + _listen = value.getString(); } void ServerSettings::parseServerName(const Token value) @@ -123,22 +127,6 @@ void ServerSettings::addValueToServerSettings( } // Functionality: -const std::string -methodToString(HTTPMethod method) // TODO: change data_types in function -{ - switch (method) - { - case (HTTPMethod::GET): - return ("GET"); - case (HTTPMethod::POST): - return ("POST"); - case (HTTPMethod::DELETE): - return ("DELETE"); - default: - throw std::runtime_error("Unknown HTTPMethod"); - } -} - // getters: const std::string &ServerSettings::getListen() const { @@ -179,24 +167,24 @@ const std::string &ServerSettings::getClientMaxBodySize() const // /png/images/ => / // -const LocationSettings &ServerSettings::resolveLocation(const std::string &URI) +const LocationSettings & +ServerSettings::resolveLocation(const std::string &RequestTarget) const { - LocationSettings *ret = nullptr; - const std::string requesttarget = URI.substr(0, URI.find_last_of("/") + 1); + const LocationSettings *ret = nullptr; + std::string searched = RequestTarget.substr(0, RequestTarget.find("?")); - for (auto &instance : _location_settings) + for (const auto &instance : _location_settings) { - const size_t pos = requesttarget.find(instance.getRequestTarget()); + const size_t pos = RequestTarget.find(instance.getPath()); - if (pos != 0) + if (pos == std::string::npos) continue; - if (ret != nullptr) + if (ret == nullptr) { - if (instance.getRequestTarget().length() > - ret->getRequestTarget().length()) - ret = &instance; + ret = &instance; + continue; } - else + if (instance.getPath().length() > ret->getPath().length()) ret = &instance; } if (ret == nullptr) @@ -205,6 +193,18 @@ const LocationSettings &ServerSettings::resolveLocation(const std::string &URI) return (*ret); } +/* TODO: move to relevant class, i think it should be HTTPRequest + +bool ServerSettings::resolveServerName(const std::string &RequestHost) +{ + std::stringstream ss(getServerName()); + std::string option; + + for (; std::getline(ss, option, ' ');) + { + } +} +*/ // Printing: void ServerSettings::printServerSettings() const diff --git a/src/Socket.cpp b/src/Socket.cpp index 630f26b..e52dd76 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -46,16 +47,31 @@ Socket::~Socket() assert(close(getFD()) != SYSTEM_ERROR); } -void Socket::initSockaddrIn(t_sockaddr_in &addr, const std::string &_port) +void Socket::initSockaddrIn(t_sockaddr_in &addr, const std::string &_listen) { + Logger &logger = Logger::getInstance(); + + size_t pos = _listen.find(":"); + std::string host = _listen.substr(0, pos); + std::string port; + if (pos == std::string::npos) + port = "80"; + else + port = _listen.substr(pos + 1); + logger.log(DEBUG, + "listen: " + _listen + "\nhost: " + host + "\nport: " + port); + + if (getaddrinfo(host.c_str(), port) != 0) + throw SystemException("getaddrinfo failed"); + bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(std::stoi(_port)); + addr.sin_port = htons(std::stoi()); std::fill_n(addr.sin_zero, sizeof(addr.sin_zero), '\0'); } -void Socket::setupServer(const std::string &port) +void Socket::setupServer(const std::string &Listen) { int option = 1; if (fcntl(getFD(), F_SETFL, O_NONBLOCK) == SYSTEM_ERROR) @@ -63,7 +79,7 @@ void Socket::setupServer(const std::string &port) if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) == SYSTEM_ERROR) throw SystemException("setsockopt failed"); - initSockaddrIn(_addr, port); + initSockaddrIn(_addr, Listen); if (bind(getFD(), (t_sockaddr *)&_addr, sizeof(t_sockaddr_in)) == SYSTEM_ERROR) throw SystemException("Bind"); From aed2e3c038f79a1a3ace0e73655953432e20595c Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Sun, 17 Dec 2023 02:19:00 +0100 Subject: [PATCH 05/34] restructured data --- data/errors/404.html | 4 +++- data/errors/500.html | 12 ++++++++++++ data/{ => images}/nose_monkey.webp | Bin {cgi-bin => data/python}/print.py | 0 data/www/index.html | 4 +++- 5 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 data/errors/500.html rename data/{ => images}/nose_monkey.webp (100%) rename {cgi-bin => data/python}/print.py (100%) diff --git a/data/errors/404.html b/data/errors/404.html index 2056402..5559d33 100644 --- a/data/errors/404.html +++ b/data/errors/404.html @@ -5,6 +5,8 @@

404 Not Found

-

The requested page could not be found.

+

The requested page could not be found. +
+
File: /data/error/404.html

diff --git a/data/errors/500.html b/data/errors/500.html new file mode 100644 index 0000000..a60a156 --- /dev/null +++ b/data/errors/500.html @@ -0,0 +1,12 @@ + + + + 500 Not Found + + +

500 Not Found

+

The server has encountered an internal error. +
+
File: /data/error/500.html

+ + diff --git a/data/nose_monkey.webp b/data/images/nose_monkey.webp similarity index 100% rename from data/nose_monkey.webp rename to data/images/nose_monkey.webp diff --git a/cgi-bin/print.py b/data/python/print.py similarity index 100% rename from cgi-bin/print.py rename to data/python/print.py diff --git a/data/www/index.html b/data/www/index.html index 4b3e145..6ee9982 100644 --- a/data/www/index.html +++ b/data/www/index.html @@ -22,7 +22,9 @@

Do not go gentle into that good night

- + This is the nose_monkey.webp test via HTTP-request + This is the nose_monkey.webp test directory +

hallo

From e4e2d0bcf2f4523c0808643df49f5daeccbd9d19 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Sun, 17 Dec 2023 02:23:07 +0100 Subject: [PATCH 06/34] webserver runs again. Gives 500, due to it trying to open a directory --- include/Client.hpp | 2 +- include/HTTPServer.hpp | 2 +- include/Server.hpp | 1 + src/Client.cpp | 7 ++++++- src/HTTPServer.cpp | 29 ++++++++++------------------- src/Server.cpp | 5 +++++ src/Socket.cpp | 11 ++++------- 7 files changed, 28 insertions(+), 29 deletions(-) diff --git a/include/Client.hpp b/include/Client.hpp index e9a862f..a7c0242 100644 --- a/include/Client.hpp +++ b/include/Client.hpp @@ -11,7 +11,7 @@ class Client { public: - Client(const int &server_fd); + Client(const int &server_fd, const ServerSettings &serversettings); Client() = delete; Client(const Client &other) = delete; const Client &operator=(const Client &other) = delete; diff --git a/include/HTTPServer.hpp b/include/HTTPServer.hpp index e1d7e18..8d0c76e 100644 --- a/include/HTTPServer.hpp +++ b/include/HTTPServer.hpp @@ -28,7 +28,7 @@ class HTTPServer void setupServers(void); void handleActivePollFDs(); - void handleNewConnection(int fd); + void handleNewConnection(int fd, const ServerSettings &ServerBlock); void handleExistingConnection(const pollfd &poll_fd); }; diff --git a/include/Server.hpp b/include/Server.hpp index 853bfd4..1ae0f32 100644 --- a/include/Server.hpp +++ b/include/Server.hpp @@ -14,6 +14,7 @@ class Server Server &operator=(const Server &rhs) = delete; ~Server(); int getFD(void) const; + const ServerSettings &getServerSettings(void) const; private: const ServerSettings &_server_settings; diff --git a/src/Client.cpp b/src/Client.cpp index 1911c29..55b6f6e 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -1,10 +1,13 @@ +#include "Server.hpp" +#include "ServerSettings.hpp" #include #include #include #include -Client::Client(const int &server_fd) : _socket(server_fd) +Client::Client(const int &server_fd, const ServerSettings &serversettings) + : _socket(server_fd), _ServerSetting(serversettings) { _socket.setupClient(); } @@ -32,6 +35,8 @@ ClientState Client::handleConnection(short events) } else if (events & POLLOUT && _state == ClientState::Loading) { + // Does the loading event only happen once? + _state = _file_manager.manage( _request.getMethodType(), "./data/www" + _request.getRequestTarget(), diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index cc06199..12538a0 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -26,26 +26,15 @@ int HTTPServer::run() _parser.ParseConfig(); setupServers(); logger.log(INFO, "Server started"); + while (true) + handleActivePollFDs(); } catch (const std::runtime_error &e) { logger.log(FATAL, e.what()); return (EXIT_FAILURE); } - return (EXIT_SUCCESS); - - while (true) - { - try - { - handleActivePollFDs(); - } - catch (const std::runtime_error &e) - { - logger.log(FATAL, e.what()); - return (EXIT_FAILURE); - } - } + // return (EXIT_SUCCESS); } void HTTPServer::setupServers(void) @@ -88,7 +77,9 @@ void HTTPServer::handleActivePollFDs() " revents: " + _poll.pollEventsToString(poll_fd.revents)); if (_active_servers.find(poll_fd.fd) != _active_servers.end()) - handleNewConnection(poll_fd.fd); + handleNewConnection( + poll_fd.fd, + _active_servers.find(poll_fd.fd)->second->getServerSettings()); else if (_active_clients.find(poll_fd.fd) != _active_clients.end()) handleExistingConnection(poll_fd); else @@ -96,13 +87,13 @@ void HTTPServer::handleActivePollFDs() } } -void HTTPServer::handleNewConnection(int fd) +void HTTPServer::handleNewConnection(int fd, + const ServerSettings &ServerSettings) { - std::shared_ptr client = std::make_shared(fd); + std::shared_ptr client = + std::make_shared(fd, ServerSettings); _active_clients.emplace(client->getFD(), client); _poll.addPollFD(client->getFD(), POLLIN); - // TODO: 1. Serversetting need to be added to client class - // } void HTTPServer::handleExistingConnection(const pollfd &poll_fd) diff --git a/src/Server.cpp b/src/Server.cpp index a856e04..80b4351 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -19,6 +19,11 @@ Server::~Server() { } +const ServerSettings &Server::getServerSettings(void) const +{ + return (_server_settings); +} + int Server::getFD(void) const { return (_socket.getFD()); diff --git a/src/Socket.cpp b/src/Socket.cpp index e52dd76..dad1ed4 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -49,7 +49,7 @@ Socket::~Socket() void Socket::initSockaddrIn(t_sockaddr_in &addr, const std::string &_listen) { - Logger &logger = Logger::getInstance(); + // Logger &logger = Logger::getInstance(); size_t pos = _listen.find(":"); std::string host = _listen.substr(0, pos); @@ -58,16 +58,13 @@ void Socket::initSockaddrIn(t_sockaddr_in &addr, const std::string &_listen) port = "80"; else port = _listen.substr(pos + 1); - logger.log(DEBUG, - "listen: " + _listen + "\nhost: " + host + "\nport: " + port); - - if (getaddrinfo(host.c_str(), port) != 0) - throw SystemException("getaddrinfo failed"); + // logger.log(DEBUG, + // "listen: " + _listen + "\nhost: " + host + "\nport: " + port); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(std::stoi()); + addr.sin_port = htons(std::stoi(port)); std::fill_n(addr.sin_zero, sizeof(addr.sin_zero), '\0'); } From 89d43125666b702152d2d7f8f688af7d48d5b682 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Sun, 17 Dec 2023 02:29:50 +0100 Subject: [PATCH 07/34] cleanup --- config/default.conf | 32 +++++++--- in.txt | 2 - out.txt | 2 - saveData.cpp | 145 -------------------------------------------- 4 files changed, 25 insertions(+), 156 deletions(-) delete mode 100644 in.txt delete mode 100644 out.txt delete mode 100644 saveData.cpp diff --git a/config/default.conf b/config/default.conf index 46f3436..b609f59 100644 --- a/config/default.conf +++ b/config/default.conf @@ -49,18 +49,36 @@ server { # # TODO: all Settings still need implementation into the Webserver # [ ] ServerBlock: -# [ ] listen; // -# [ ] server_name; // should go over the Clients/HTTPServers after +# [ ]- listen; // +# [ ]- server_name; // should go over the Clients/HTTPServers after # // the request is recieved and see which serverSettings block is relevant to the request; -# [ ] error_dir; // should search this direcotry to find the relevant error file [e.g. 404.html]; -# [ ] client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; +# [ ]- error_dir; // should search this direcotry to find the relevant error file [e.g. 404.html]; +# [ ]- client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; # [ ] Location Block: # [ ] alias; // should do a fitted preppend on the path in URI; # [ ] index; // file return of the request just specifies this directory ; # [ ] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; -# [ ] allowed_methods; // should check if the HTTP Method is allowed in this location; -# [ ] cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; -# [ ] return; // +# [ ]- allowed_methods; // should check if the HTTP Method is allowed in this location; +# [ ]- cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; +# [ ]- return; // +# +# TODO: Move list to plan +# +#plan: +# +# The location block needs to be added to the client. +# - before we enter the file manager we'll find the serverblock +# +# alias +# if found, fitted preppend on requesttarget +# if none, use requesttarget as is +# +# if the requesttarget is a directory, search LocationBlock for index +# if found, append index to requesttarget +# if none, seach LocationBlock for autoindex +# if found, genrate autoindex and write to _response +# if none, return 404. +# # # #GET www.google.com/ diff --git a/in.txt b/in.txt deleted file mode 100644 index d151800..0000000 --- a/in.txt +++ /dev/null @@ -1,2 +0,0 @@ -hello world! -goodbye world! diff --git a/out.txt b/out.txt deleted file mode 100644 index 40f3220..0000000 --- a/out.txt +++ /dev/null @@ -1,2 +0,0 @@ -['hello world!\n', 'goodbye world!\n'] -Content-type: text/html diff --git a/saveData.cpp b/saveData.cpp deleted file mode 100644 index 02c8e47..0000000 --- a/saveData.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include - -int post_image(const std::string filename, const std::string post_data) -{ - std::ifstream inputFile(filename); - std::ofstream outputFile("temp.txt"); - std::ifstream image("data/images/" + post_data); - const std::string check_point = " "; - std::string converted_post_data = " "; - std::string line; - std::vector lines; - int currentLine = 0; - while (std::getline(inputFile, line)) { - currentLine++; - if (line == check_point && done) { - lines.push_back(line); - lines.push_back(converted_post_data); - done = false; - continue ; - } - lines.push_back(line); - } - for (const std::string& storedLine : lines) { - outputFile << storedLine << '\n'; - } - inputFile.close(); - outputFile.close(); - if (std::rename("temp.txt", filename.c_str()) != 0) { - std::cerr << "Error renaming the file." << std::endl; - return 1; - } - std::cout << "Image inserted successfully." << std::endl; - return 0; -} - - -int post_text(const std::string filename, const std::string content) -{ - std::ifstream inputFile(filename); - std::ofstream outputFile("temp.txt"); - const std::string check_point = " "; - std::string converted_post_data = "

"; - bool done = true; - - if (!inputFile || !outputFile) { - std::cerr << "Error opening files." << std::endl; - return 1; - } - if (content == "") - return 204; - converted_post_data += content + "

"; - std::string line; - std::vector lines; - int currentLine = 0; - while (std::getline(inputFile, line)) { - currentLine++; - if (line == check_point && done) { - lines.push_back(line); - lines.push_back(converted_post_data); - done = false; - continue ; - } - lines.push_back(line); - } - - for (const std::string& storedLine : lines) { - outputFile << storedLine << '\n'; - } - - inputFile.close(); - outputFile.close(); - - if (std::rename("temp.txt", filename.c_str()) != 0) { - std::cerr << "Error renaming the file." << std::endl; - return 1; - } - - std::cout << "Text inserted successfully." << std::endl; - return 0; -} - -// when implementing save_image it can be simplified by replacing -// function body with: - // std::ofstream new_image("data/" + post_message); - // new_image << conent; -bool save_data(const std::string post_message, const std::string content, - const std::string content_type) -{ - std::ifstream image_content(content); - std::string line; - - if (!image_content) - { - std::cerr << "Error opening files." << std::endl; - return (false); - } - // std::cout << "data/" + content_type + "/" + post_message + "\n"; - std::ofstream new_image("data/" + content_type + "/" + post_message); - while (std::getline(image_content, line)) { - new_image << line << '\n'; - } - return (true); -} - -int main(int argc, char **argv) -{ - if (argc != 4) - { - std::cout << "Invalid number of parameters.\n"; - return 0; - } - // const std::string filename = "data/www/index.html"; - const std::string post_message = argv[2]; - const std::string content_type = argv[1]; - if (save_data(post_message, argv[3], content_type) == false) { - std::cout << "400 BAD REQUEST\n"; - return (400); - } - - // post functionality is optional I guess - // if (content_type == "images") { - // if (post_image(filename, post_message) == 204) { - // std::cout << "204 NO CONTENT\n"; - // return (204); - // } - // } else if (content_type == "text") { - // if (post_text(filename, post_message) == 204) { - // std::cout << "204 NO CONTENT\n"; - // return (204); - // } - // } - return 0; -} \ No newline at end of file From 377d472c1ba513783e716c78d5a95273c373cdc3 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Sat, 23 Dec 2023 20:47:36 +0100 Subject: [PATCH 08/34] MaxC:wlientBodySize is implemented and working. --- config/default.conf | 3 ++- include/HTTPRequest.hpp | 4 ++++ include/StatusCode.hpp | 2 +- src/Client.cpp | 4 ++-- src/FileManager.cpp | 1 + src/HTTPRequest.cpp | 32 ++++++++++++++++++++++++++++++-- src/HTTPStatus.cpp | 8 ++++---- src/ServerSettings.cpp | 22 +++++++++++++++++++--- 8 files changed, 63 insertions(+), 13 deletions(-) diff --git a/config/default.conf b/config/default.conf index b609f59..30c047b 100644 --- a/config/default.conf +++ b/config/default.conf @@ -53,7 +53,7 @@ server { # [ ]- server_name; // should go over the Clients/HTTPServers after # // the request is recieved and see which serverSettings block is relevant to the request; # [ ]- error_dir; // should search this direcotry to find the relevant error file [e.g. 404.html]; -# [ ]- client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; +# [x] client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; # [ ] Location Block: # [ ] alias; // should do a fitted preppend on the path in URI; # [ ] index; // file return of the request just specifies this directory ; @@ -61,6 +61,7 @@ server { # [ ]- allowed_methods; // should check if the HTTP Method is allowed in this location; # [ ]- cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; # [ ]- return; // +# [ ] HTTPerrorpagegenerator // method that can generate a simple ERROR page to the _response. # # TODO: Move list to plan # diff --git a/include/HTTPRequest.hpp b/include/HTTPRequest.hpp index 8c19437..2be730a 100644 --- a/include/HTTPRequest.hpp +++ b/include/HTTPRequest.hpp @@ -38,6 +38,9 @@ class HTTPRequest void setRequestTarget(const std::string &request_target); const std::string &getRequestTarget(void) const; + void setMaxBodySize(std::string inp); + ssize_t getMaxBodySize(void) const; + void setHTTPVersion(const std::string &http_version); const std::string &getHTTPVersion(void) const; @@ -50,6 +53,7 @@ class HTTPRequest private: ssize_t _bytes_read; size_t _content_length; + ssize_t _max_body_size; HTTPMethod _methodType; std::string _http_request; std::string _request_target; diff --git a/include/StatusCode.hpp b/include/StatusCode.hpp index 17e63b8..f0fa59a 100644 --- a/include/StatusCode.hpp +++ b/include/StatusCode.hpp @@ -16,7 +16,7 @@ enum class StatusCode MethodNotAllowed = 405, RequestTimeout = 408, LenghtRequired = 411, - PayloadToLarge = 413, + RequestBodyTooLarge = 413, URIToLong = 414, UnsupportedMediaType = 415, InternalServerError = 500, diff --git a/src/Client.cpp b/src/Client.cpp index 55b6f6e..57d552c 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -10,6 +10,8 @@ Client::Client(const int &server_fd, const ServerSettings &serversettings) : _socket(server_fd), _ServerSetting(serversettings) { _socket.setupClient(); + // TODO: if more settings need to be added make separate constructor; + _request.setMaxBodySize(serversettings.getClientMaxBodySize()); } Client::~Client() @@ -35,8 +37,6 @@ ClientState Client::handleConnection(short events) } else if (events & POLLOUT && _state == ClientState::Loading) { - // Does the loading event only happen once? - _state = _file_manager.manage( _request.getMethodType(), "./data/www" + _request.getRequestTarget(), diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 03328bf..ca24244 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -68,6 +68,7 @@ ClientState FileManager::loadErrorPage(void) { HTTPStatus status(StatusCode::InternalServerError); _response = status.getStatusLine("HTTP/1.1") + status.getHTMLStatus(); + // TODO: shouldn't there be a return here? } _response += std::string(buffer); if (_request_target.eof()) diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index 25c80e4..db753ab 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -1,14 +1,18 @@ +#include "ClientException.hpp" +#include "StatusCode.hpp" #include #include #include +#include #include #include HTTPRequest::HTTPRequest() - : _bytes_read(0), _content_length(0), _methodType(HTTPMethod::UNKNOWN), - _http_request(), _request_target(), _http_version(), _body(), _headers() + : _bytes_read(0), _content_length(0), _max_body_size(), + _methodType(HTTPMethod::UNKNOWN), _http_request(), _request_target(), + _http_version(), _body(), _headers() { } @@ -33,6 +37,28 @@ HTTPMethod HTTPRequest::getMethodType(void) const return (_methodType); } +void HTTPRequest::setMaxBodySize(std::string inp) +{ + size_t pos = inp.find_first_of("KM"); + std::string nbr = inp.substr(0, pos); + std::string mag; + if (pos != std::string::npos) + { + mag = inp.substr(pos); + if (mag == "K") + nbr += "000"; + else // (mag == "M") + nbr += "000000"; + } + + _max_body_size = std::stoull(nbr); +} + +ssize_t HTTPRequest::getMaxBodySize(void) const +{ + return (_max_body_size); +} + void HTTPRequest::setHeader(const std::string &key, const std::string &header) { _headers.emplace(key, header); @@ -121,6 +147,8 @@ ClientState HTTPRequest::receive(int client_fd) if (_content_length != 0) { _body += std::string(buffer, _bytes_read); + if (_body.size() >= _max_body_size) + throw ClientException(StatusCode::RequestEntityTooLarge); if (_body.size() >= _content_length) { logger.log(DEBUG, "Body: " + _body); diff --git a/src/HTTPStatus.cpp b/src/HTTPStatus.cpp index 52d7ad0..2c6e93c 100644 --- a/src/HTTPStatus.cpp +++ b/src/HTTPStatus.cpp @@ -15,7 +15,7 @@ std::unordered_map HTTPStatus::_message = { {StatusCode::MethodNotAllowed, "Method Not Allowed"}, {StatusCode::RequestTimeout, "Request Timeout"}, {StatusCode::LenghtRequired, "Length Required"}, - {StatusCode::PayloadToLarge, "Payload Too Large"}, + {StatusCode::RequestBodyTooLarge, "Request Body Too Large"}, {StatusCode::URIToLong, "URI Too Long"}, {StatusCode::UnsupportedMediaType, "Unsupported Media Type"}, {StatusCode::InternalServerError, "Internal Server Error"}, @@ -41,10 +41,10 @@ std::string HTTPStatus::getStatusLine(const std::string &version) const std::string HTTPStatus::getHTMLStatus(void) const { - return ("

" + - std::to_string(static_cast(_status_code)) + " " + + return ("

ERROR: " + + std::to_string(static_cast(_status_code)) + "

(" + _message.at(_status_code)) + - "

"; + ")

"; } StatusCode HTTPStatus::getStatusCode() const diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index c8423f4..8daa20f 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -6,11 +6,12 @@ #include #include +#include #include #include ServerSettings::ServerSettings() - : _listen(), _server_name(), _error_dir(), _client_max_body_size(), + : _listen(), _server_name(), _error_dir(), _client_max_body_size("3M"), _location_settings() { } @@ -32,7 +33,7 @@ ServerSettings::~ServerSettings() // assigned values will fill in the ServerSettings. ServerSettings::ServerSettings(std::vector::iterator &token) - : _listen(), _server_name(), _error_dir(), _client_max_body_size(), + : _listen(), _server_name(), _error_dir(), _client_max_body_size("3M"), _location_settings() { token += 2; @@ -99,9 +100,24 @@ void ServerSettings::parseClientMaxBodySize(const Token value) { Logger &logger = Logger::getInstance(); + const std::regex rgx_pat = std::regex("^\\d{1,3}[KM]?$"); + + std::sregex_iterator it(value.getString().begin(), value.getString().end(), + rgx_pat); + std::sregex_iterator end; + + if (std::distance(it, end) == 0) + { + logger.log(FATAL, "ConfigParser: clientmaxbodysize inpropperly " + "formated: \"d{1,3}[MK]?\""); + throw std::runtime_error( + "ConfigParser: invalid value for clientmaxbodysize"); + } + if (!_client_max_body_size.empty()) logger.log(WARNING, "ConfigParser: redefining clientmaxbodysize"); - _client_max_body_size = value.getString(); + + _client_max_body_size = it->str(); } void ServerSettings::addValueToServerSettings( From 7f9929e7cfd1b8c4b89320ce76105d2d84db5495 Mon Sep 17 00:00:00 2001 From: tentanus Date: Tue, 26 Dec 2023 15:29:43 +0100 Subject: [PATCH 09/34] Errordirectory is implemented. resolveAlias now works propperly. still needs to be implemented --- config/default.conf | 28 +++++++++++++++------- data/www/index.html | 5 ++-- include/Client.hpp | 4 ++-- include/HTTPRequest.hpp | 6 ++++- include/LocationSettings.hpp | 3 +++ include/ServerSettings.hpp | 5 ++-- src/Client.cpp | 8 +++---- src/FileManager.cpp | 2 +- src/HTTPRequest.cpp | 16 ++++++++----- src/LocationSettings.cpp | 45 ++++++++++++++++++++++++++++++------ 10 files changed, 87 insertions(+), 35 deletions(-) diff --git a/config/default.conf b/config/default.conf index 30c047b..9e89657 100644 --- a/config/default.conf +++ b/config/default.conf @@ -13,29 +13,41 @@ server { listen localhost:8080; # [M - O] choose a Host:Port combination ; IPv4:{1 - 16bit} ; default: INADDR_ANY:8080 server_name localhost; # [M - O] Setup the server_names ; [A-Za-z_]* ; default: [EMPTY] - error_dir /error; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] + error_dir /data/errors; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] client_max_body_size 3M; # [1 - O] Limit client body size ; [\d]{1,3}[KkMm]? ; Default: 1 mB location / { # [1 - O] Request Target is the Target of the HTTP request; starts with a / - alias /data/www; # [1 - O] links the stated Direcotry as the RequestTarget Location ; [/]{1}[A-Za-z_/:w]* ; Default: /data/www + alias /data/www/; # [1 - O] links the stated Direcotry as the RequestTarget Location ; [/]{1}[A-Za-z_/:w]* ; Default: /data/www index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html allowed_methods GET; # [M - O] Define a list of accepted HTTP methods for the route; GET/POST/DELETE ; Default: GET autoindex on; # [B - O] Turn on or off directory listing; on; Default: off } location /python/ { - alias /cgi/python; # already defined; + alias /cgi/python/; # already defined; cgi /bin/python3; # [1 - O] Set a Path to where the CGI can find the Binary; [A-Za-z_/.]* ; Default: [EMPTY] } location /images/ { - alias /data/images; + alias /data/images/; + allowed_methods GET POST; + autoindex off; + } + + location /png/ { + alias /data/images/png/; + allowed_methods GET POST; + autoindex off; + } + + location /images/jpg/ { + alias /data/upload/images/jpg/; allowed_methods GET POST; autoindex off; } location /upload/ { - alias /data/upload; + alias /data/upload/; allowed_methods POST DELETE; } @@ -52,16 +64,16 @@ server { # [ ]- listen; // # [ ]- server_name; // should go over the Clients/HTTPServers after # // the request is recieved and see which serverSettings block is relevant to the request; -# [ ]- error_dir; // should search this direcotry to find the relevant error file [e.g. 404.html]; +# [x] error_dir; // should search this direcotry to find the relevant error file [e.g. 404.html]; # [x] client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; # [ ] Location Block: -# [ ] alias; // should do a fitted preppend on the path in URI; +# [X] alias; (miss imp) // should do a fitted preppend on the path in URI; # [ ] index; // file return of the request just specifies this directory ; # [ ] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; # [ ]- allowed_methods; // should check if the HTTP Method is allowed in this location; # [ ]- cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; # [ ]- return; // -# [ ] HTTPerrorpagegenerator // method that can generate a simple ERROR page to the _response. +# [x] HTTPerrorpagegenerator // method that can generate a simple ERROR page to the _response. # # TODO: Move list to plan # diff --git a/data/www/index.html b/data/www/index.html index 6ee9982..1fe2bc9 100644 --- a/data/www/index.html +++ b/data/www/index.html @@ -22,8 +22,9 @@

Do not go gentle into that good night

- This is the nose_monkey.webp test via HTTP-request - This is the nose_monkey.webp test directory + nose_monkey.webp test via HTTP-request +
+ nose_monkey.webp test via directory diff --git a/include/Client.hpp b/include/Client.hpp index a7c0242..daf12d9 100644 --- a/include/Client.hpp +++ b/include/Client.hpp @@ -1,7 +1,7 @@ #ifndef CLIENT_HPP #define CLIENT_HPP -#include "ServerSettings.hpp" +#include #include #include #include @@ -26,7 +26,7 @@ class Client FileManager _file_manager; CGI _cgi; Socket _socket; - ServerSettings _ServerSetting; // TODO: make multiple serverblocks work; + ServerSettings _serversetting; // TODO: make multiple serverblocks work; ClientState _state; }; diff --git a/include/HTTPRequest.hpp b/include/HTTPRequest.hpp index 2be730a..b142a57 100644 --- a/include/HTTPRequest.hpp +++ b/include/HTTPRequest.hpp @@ -2,6 +2,8 @@ #define HTTP_REQUEST_HPP #include +#include +#include #include #include @@ -28,6 +30,7 @@ class HTTPRequest { public: HTTPRequest(); + HTTPRequest(const ServerSettings &serversetting); HTTPRequest(const HTTPRequest &rhs) = delete; HTTPRequest &operator=(const HTTPRequest &rhs) = delete; ~HTTPRequest(); @@ -53,12 +56,13 @@ class HTTPRequest private: ssize_t _bytes_read; size_t _content_length; - ssize_t _max_body_size; + size_t _max_body_size; HTTPMethod _methodType; std::string _http_request; std::string _request_target; std::string _http_version; std::string _body; + ServerSettings _serversetting; std::unordered_map _headers; size_t parseStartLine(size_t &i); diff --git a/include/LocationSettings.hpp b/include/LocationSettings.hpp index 4d71067..37a2d86 100644 --- a/include/LocationSettings.hpp +++ b/include/LocationSettings.hpp @@ -23,6 +23,9 @@ class LocationSettings const std::string &getReturn() const; bool getAutoIndex() const; + // resolves: + const std::string resolveAlias(const std::string request_target) const; + // Printing: void printLocationSettings() const; diff --git a/include/ServerSettings.hpp b/include/ServerSettings.hpp index 8394c2f..1a14900 100644 --- a/include/ServerSettings.hpp +++ b/include/ServerSettings.hpp @@ -1,7 +1,6 @@ #ifndef SERVERSETTING_HPP #define SERVERSETTING_HPP -#include #include #include @@ -17,8 +16,8 @@ class ServerSettings ServerSettings &operator=(const ServerSettings &rhs) = delete; // Functionality: - const LocationSettings &resolveLocation(const std::string &URI) const; - bool resolveServerName(const std::string &RequestHost); + const LocationSettings &resolveLocation(const std::string &request_target) const; +// bool resolveServerName(const std::string &RequestHost); const std::string &getListen() const; const std::string &getServerName() const; diff --git a/src/Client.cpp b/src/Client.cpp index 57d552c..5dda2e8 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -6,12 +6,10 @@ #include -Client::Client(const int &server_fd, const ServerSettings &serversettings) - : _socket(server_fd), _ServerSetting(serversettings) +Client::Client(const int &server_fd, const ServerSettings &serversetting) + : _request(serversetting), _socket(server_fd), _serversetting(serversetting) { _socket.setupClient(); - // TODO: if more settings need to be added make separate constructor; - _request.setMaxBodySize(serversettings.getClientMaxBodySize()); } Client::~Client() @@ -61,7 +59,7 @@ ClientState Client::handleConnection(short events) _response.clear(); _response.append(e.what()); _state = _file_manager.openErrorPage( - "./data/errors", e.getStatusCode()); // TODO: resolve location + _serversetting.getErrorDir(), e.getStatusCode()); return (_state); } return (ClientState::Unkown); diff --git a/src/FileManager.cpp b/src/FileManager.cpp index ca24244..7beab62 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -68,7 +68,7 @@ ClientState FileManager::loadErrorPage(void) { HTTPStatus status(StatusCode::InternalServerError); _response = status.getStatusLine("HTTP/1.1") + status.getHTMLStatus(); - // TODO: shouldn't there be a return here? + // TODO: @saladuit: shouldn't there be a return here? -> return(ClientState::Sending) } _response += std::string(buffer); if (_request_target.eof()) diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index db753ab..a83e5a4 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -9,11 +9,12 @@ #include -HTTPRequest::HTTPRequest() - : _bytes_read(0), _content_length(0), _max_body_size(), +HTTPRequest::HTTPRequest(const ServerSettings &serversetting) + : _bytes_read(0), _content_length(0), _max_body_size(), _methodType(HTTPMethod::UNKNOWN), _http_request(), _request_target(), - _http_version(), _body(), _headers() + _http_version(), _body(), _serversetting(serversetting), _headers() { + setMaxBodySize(_serversetting.getClientMaxBodySize()); } HTTPRequest::~HTTPRequest() @@ -103,7 +104,10 @@ size_t HTTPRequest::parseStartLine(size_t &i) setMethodType(_http_request.substr(i, pos - i)); i = pos + 1; pos = _http_request.find(' ', i); - setRequestTarget(_http_request.substr(i, pos - i)); + + std::string prelim = _http_request.substr(i, pos - i); + setRequestTarget(_serversetting.resolveLocation(prelim).resolveAlias(prelim)); + i = pos + 1; pos = _http_request.find("\r\n", i); setHTTPVersion(_http_request.substr(i, pos - i)); @@ -147,13 +151,13 @@ ClientState HTTPRequest::receive(int client_fd) if (_content_length != 0) { _body += std::string(buffer, _bytes_read); - if (_body.size() >= _max_body_size) - throw ClientException(StatusCode::RequestEntityTooLarge); if (_body.size() >= _content_length) { logger.log(DEBUG, "Body: " + _body); return (ClientState::Loading); } + if (_body.size() >= _max_body_size) // @saladuit not sure if this should be before the previous ifstatement + throw ClientException(StatusCode::RequestBodyTooLarge); return (ClientState::Receiving); } _http_request += std::string(buffer, _bytes_read); diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index 57b0979..5028b28 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -7,8 +7,6 @@ #include LocationSettings::LocationSettings() - : _path(), _alias(), _index(), _allowed_methods(), _cgi_path(), - _auto_index() { } @@ -41,8 +39,6 @@ LocationSettings::~LocationSettings() } LocationSettings::LocationSettings(std::vector::iterator &token) - : _path(), _alias(), _index(), _allowed_methods(), _cgi_path(), - _auto_index() { _path = token->getString(); token += 2; @@ -69,9 +65,11 @@ LocationSettings::LocationSettings(std::vector::iterator &token) else if (key.getString() == "return") parseReturn(*token); else + { logger.log(WARNING, "LocationSettings: unknown KEY token: " + key.getString()); - + break ; + } token++; } token++; @@ -125,7 +123,7 @@ void LocationSettings::parseCgiPath(const Token token) if (!_index.empty()) logger.log(WARNING, - "ConfigParser: redefining index in locationblock: " + _path); + "ConfigParser: redefining cgi_path in locationblock: " + _path); _cgi_path = token.getString(); } @@ -172,7 +170,40 @@ const std::string &LocationSettings::getReturn() const return (_return); } -// +// + +const std::string LocationSettings::resolveAlias(const std::string inp) const +{ +// Logger &logger = Logger::getInstance(); + +// logger.log(DEBUG, "input: " + getPath()); +// logger.log(DEBUG, " 01234567890123456789"); +// logger.log(DEBUG, "alias: " + getAlias() + "\n"); + + std::string alias = getAlias(); + if (alias.empty()) + return (inp); + if (_path.length() == 1) + return (alias + inp.substr(1, inp.length() - 1)); + + size_t pos_begin = alias.length() - 1; + size_t pos_end; + while (pos_end != 0) + { + pos_end = pos_begin; + pos_begin = alias.find_last_of("/", pos_end - 1); + std::string hit = alias.substr(pos_begin, pos_end - pos_begin + 1); +// logger.log(DEBUG, "end: " + std::to_string(pos_end)); +// logger.log(DEBUG, "begin: " + std::to_string(pos_begin)); +// logger.log(DEBUG, "part: " + hit); + if (inp.find(hit) == std::string::npos) // aka not found in inp. + break; + } + std::string request_target = alias.substr(0, pos_end) + inp; +// logger.log(DEBUG, "Found: " + request_target + "\n"); + + return (request_target); +} // THIS IS PRINTING FUNCTION From c695bcf58149d363cfecdf863087d904a2bb5b87 Mon Sep 17 00:00:00 2001 From: tentanus Date: Wed, 27 Dec 2023 21:38:58 +0100 Subject: [PATCH 10/34] added resolveAlias and ResolveMethod --- config/default.conf | 8 +++--- include/LocationSettings.hpp | 3 +++ src/HTTPRequest.cpp | 6 ++++- src/LocationSettings.cpp | 52 +++++++++++++++++++++++++++--------- src/ServerSettings.cpp | 14 +++++----- 5 files changed, 60 insertions(+), 23 deletions(-) diff --git a/config/default.conf b/config/default.conf index 9e89657..7b54fe8 100644 --- a/config/default.conf +++ b/config/default.conf @@ -13,7 +13,7 @@ server { listen localhost:8080; # [M - O] choose a Host:Port combination ; IPv4:{1 - 16bit} ; default: INADDR_ANY:8080 server_name localhost; # [M - O] Setup the server_names ; [A-Za-z_]* ; default: [EMPTY] - error_dir /data/errors; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] + error_dir /data/errors; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] client_max_body_size 3M; # [1 - O] Limit client body size ; [\d]{1,3}[KkMm]? ; Default: 1 mB location / { # [1 - O] Request Target is the Target of the HTTP request; starts with a / @@ -61,16 +61,16 @@ server { # # TODO: all Settings still need implementation into the Webserver # [ ] ServerBlock: -# [ ]- listen; // +# [ ]- listen; // # [ ]- server_name; // should go over the Clients/HTTPServers after # // the request is recieved and see which serverSettings block is relevant to the request; # [x] error_dir; // should search this direcotry to find the relevant error file [e.g. 404.html]; # [x] client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; # [ ] Location Block: -# [X] alias; (miss imp) // should do a fitted preppend on the path in URI; +# [x] alias; // should do a fitted preppend on the path in URI; # [ ] index; // file return of the request just specifies this directory ; # [ ] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; -# [ ]- allowed_methods; // should check if the HTTP Method is allowed in this location; +# [x] allowed_methods; // should check if the HTTP Method is allowed in this location; # [ ]- cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; # [ ]- return; // # [x] HTTPerrorpagegenerator // method that can generate a simple ERROR page to the _response. diff --git a/include/LocationSettings.hpp b/include/LocationSettings.hpp index 37a2d86..946a0dc 100644 --- a/include/LocationSettings.hpp +++ b/include/LocationSettings.hpp @@ -16,6 +16,7 @@ class LocationSettings // Functionality: // getters: + const std::string &getPath() const; const std::string &getAlias() const; const std::string &getIndex() const; @@ -24,7 +25,9 @@ class LocationSettings bool getAutoIndex() const; // resolves: + const std::string resolveAlias(const std::string request_target) const; + bool resolveMethod(HTTPMethod method) const; // Printing: void printLocationSettings() const; diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index a83e5a4..efb6984 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -106,7 +106,11 @@ size_t HTTPRequest::parseStartLine(size_t &i) pos = _http_request.find(' ', i); std::string prelim = _http_request.substr(i, pos - i); - setRequestTarget(_serversetting.resolveLocation(prelim).resolveAlias(prelim)); + const LocationSettings &loc = _serversetting.resolveLocation(prelim); + + setRequestTarget(loc.resolveAlias(prelim)); + if (loc.resolveMethod(_methodType)) + throw ClientException(StatusCode::Forbidden); i = pos + 1; pos = _http_request.find("\r\n", i); diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index 5028b28..b71bea6 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -1,6 +1,7 @@ -#include #include +#include +#include #include #include @@ -170,17 +171,48 @@ const std::string &LocationSettings::getReturn() const return (_return); } -// +const std::string MethodToString(HTTPMethod num) +{ + switch (num) + { + case (HTTPMethod::GET): + return ("GET"); + case (HTTPMethod::POST): + return ("POST"); + case (HTTPMethod::DELETE): + return ("DELETE"); + } -const std::string LocationSettings::resolveAlias(const std::string inp) const + Logger &logger = Logger::getInstance(); + logger.log(WARNING, "LocationSettings MethodToString: unknown Method"); + return ("UNKOWNSTRING"); +} + +// resolveMethod +bool LocationSettings::resolveMethod(HTTPMethod method) const { -// Logger &logger = Logger::getInstance(); + Logger &logger = Logger::getInstance(); + + if (getAllowedMethods().empty()) + logger.log(WARNING, "ResolveMethod: No HTTPMethod specified in Locationblock: " + getPath()); + std::stringstream ss(getAllowedMethods()); + std::string option; + for (; std::getline(ss, option, ' ') ;) + { + if (option == MethodToString(method)) + return (true); + } + return (false); +} -// logger.log(DEBUG, "input: " + getPath()); -// logger.log(DEBUG, " 01234567890123456789"); -// logger.log(DEBUG, "alias: " + getAlias() + "\n"); +// resolveAlias + +const std::string LocationSettings::resolveAlias(const std::string inp) const +{ + Logger &logger = Logger::getInstance(); std::string alias = getAlias(); + logger.log(DEBUG, "resolveAlias: received: " + inp + "\tAlias: " + alias); if (alias.empty()) return (inp); if (_path.length() == 1) @@ -193,14 +225,10 @@ const std::string LocationSettings::resolveAlias(const std::string inp) const pos_end = pos_begin; pos_begin = alias.find_last_of("/", pos_end - 1); std::string hit = alias.substr(pos_begin, pos_end - pos_begin + 1); -// logger.log(DEBUG, "end: " + std::to_string(pos_end)); -// logger.log(DEBUG, "begin: " + std::to_string(pos_begin)); -// logger.log(DEBUG, "part: " + hit); - if (inp.find(hit) == std::string::npos) // aka not found in inp. + if (inp.find(hit) == std::string::npos) // aka hit not found in inp. break; } std::string request_target = alias.substr(0, pos_end) + inp; -// logger.log(DEBUG, "Found: " + request_target + "\n"); return (request_target); } diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index 8daa20f..9d98092 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -164,9 +164,11 @@ const std::string &ServerSettings::getClientMaxBodySize() const return (_client_max_body_size); } -// Funcion: find the longest possible locationblock form the URI. -// URI will be stripped from it's trailing file. (line 3) -// and expects LocationBlock requesttarget to always start with a '/' +// Funcion: find the longest possible locationblock that fits the request_target. +// request_target will be stripped from it's trailing input. (line 3) +// and expects LocationBlock requesttarget to always start and end with a '/' +// +// EXAMPLES: // // server { // location / {} @@ -184,14 +186,14 @@ const std::string &ServerSettings::getClientMaxBodySize() const // const LocationSettings & -ServerSettings::resolveLocation(const std::string &RequestTarget) const +ServerSettings::resolveLocation(const std::string &request_target) const { const LocationSettings *ret = nullptr; - std::string searched = RequestTarget.substr(0, RequestTarget.find("?")); + std::string searched = request_target.substr(0, request_target.find("?")); for (const auto &instance : _location_settings) { - const size_t pos = RequestTarget.find(instance.getPath()); + const size_t pos = request_target.find(instance.getPath()); if (pos == std::string::npos) continue; From a7c3fb45a4eb15bca10b923eb37dd558e7c37d72 Mon Sep 17 00:00:00 2001 From: tentanus Date: Thu, 28 Dec 2023 00:23:43 +0100 Subject: [PATCH 11/34] minor changes --- config/default.conf | 2 +- data/www/index.html | 4 ++-- include/HTTPRequest.hpp | 7 +++++-- include/LocationSettings.hpp | 14 +++++++++++++- src/Client.cpp | 4 ++-- src/HTTPRequest.cpp | 10 ++++++---- src/LocationSettings.cpp | 14 ++++++++------ src/ServerSettings.cpp | 4 ++-- 8 files changed, 39 insertions(+), 20 deletions(-) diff --git a/config/default.conf b/config/default.conf index 7b54fe8..aac3868 100644 --- a/config/default.conf +++ b/config/default.conf @@ -13,7 +13,7 @@ server { listen localhost:8080; # [M - O] choose a Host:Port combination ; IPv4:{1 - 16bit} ; default: INADDR_ANY:8080 server_name localhost; # [M - O] Setup the server_names ; [A-Za-z_]* ; default: [EMPTY] - error_dir /data/errors; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] + error_dir /data/errors/; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] client_max_body_size 3M; # [1 - O] Limit client body size ; [\d]{1,3}[KkMm]? ; Default: 1 mB location / { # [1 - O] Request Target is the Target of the HTTP request; starts with a / diff --git a/data/www/index.html b/data/www/index.html index 1fe2bc9..8e3d599 100644 --- a/data/www/index.html +++ b/data/www/index.html @@ -22,10 +22,10 @@

Do not go gentle into that good night

- nose_monkey.webp test via HTTP-request +

hallo

diff --git a/include/HTTPRequest.hpp b/include/HTTPRequest.hpp index b142a57..e2e7a17 100644 --- a/include/HTTPRequest.hpp +++ b/include/HTTPRequest.hpp @@ -2,8 +2,6 @@ #define HTTP_REQUEST_HPP #include -#include -#include #include #include @@ -17,6 +15,8 @@ #endif // ENUM +#ifndef HTTP_METHOD_ENUM +#define HTTP_METHOD_ENUM enum class HTTPMethod { GET, @@ -24,6 +24,9 @@ enum class HTTPMethod DELETE, UNKNOWN, }; +#endif + +#include // CLASS class HTTPRequest diff --git a/include/LocationSettings.hpp b/include/LocationSettings.hpp index 946a0dc..27b4f66 100644 --- a/include/LocationSettings.hpp +++ b/include/LocationSettings.hpp @@ -5,6 +5,18 @@ #include +// ENUM +#ifndef HTTP_METHOD_ENUM +#define HTTP_METHOD_ENUM +enum class HTTPMethod +{ + GET, + POST, + DELETE, + UNKNOWN, +}; +#endif + class LocationSettings { public: @@ -27,7 +39,7 @@ class LocationSettings // resolves: const std::string resolveAlias(const std::string request_target) const; - bool resolveMethod(HTTPMethod method) const; + bool resolveMethod(const HTTPMethod method) const; // Printing: void printLocationSettings() const; diff --git a/src/Client.cpp b/src/Client.cpp index 5dda2e8..edbb655 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -1,5 +1,5 @@ -#include "Server.hpp" -#include "ServerSettings.hpp" +#include +#include #include #include #include diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index efb6984..c9dc087 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -1,5 +1,5 @@ -#include "ClientException.hpp" -#include "StatusCode.hpp" +#include +#include #include #include #include @@ -107,9 +107,11 @@ size_t HTTPRequest::parseStartLine(size_t &i) std::string prelim = _http_request.substr(i, pos - i); const LocationSettings &loc = _serversetting.resolveLocation(prelim); - + if (prelim.find_last_of('/') == prelim.length() - 1) + logger.log(WARNING, "prelim end with /\t" + prelim); + setRequestTarget(loc.resolveAlias(prelim)); - if (loc.resolveMethod(_methodType)) + if (loc.resolveMethod(_methodType) == false) throw ClientException(StatusCode::Forbidden); i = pos + 1; diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index b71bea6..44249f1 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -181,19 +181,21 @@ const std::string MethodToString(HTTPMethod num) return ("POST"); case (HTTPMethod::DELETE): return ("DELETE"); + default: + { + Logger &logger = Logger::getInstance(); + logger.log(WARNING, "LocationSettings MethodToString: unknown Method"); + return ("UNKOWNSTRING"); + } } - - Logger &logger = Logger::getInstance(); - logger.log(WARNING, "LocationSettings MethodToString: unknown Method"); - return ("UNKOWNSTRING"); } // resolveMethod -bool LocationSettings::resolveMethod(HTTPMethod method) const +bool LocationSettings::resolveMethod(const HTTPMethod method) const { Logger &logger = Logger::getInstance(); - if (getAllowedMethods().empty()) + if (getAllowedMethods().empty()) logger.log(WARNING, "ResolveMethod: No HTTPMethod specified in Locationblock: " + getPath()); std::stringstream ss(getAllowedMethods()); std::string option; diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index 9d98092..fd09b18 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -11,7 +11,7 @@ #include ServerSettings::ServerSettings() - : _listen(), _server_name(), _error_dir(), _client_max_body_size("3M"), + : _listen(), _server_name(), _error_dir(), _client_max_body_size(), _location_settings() { } @@ -33,7 +33,7 @@ ServerSettings::~ServerSettings() // assigned values will fill in the ServerSettings. ServerSettings::ServerSettings(std::vector::iterator &token) - : _listen(), _server_name(), _error_dir(), _client_max_body_size("3M"), + : _listen(), _server_name(), _error_dir(), _client_max_body_size(), _location_settings() { token += 2; From 1251bb322d677c14faa1aa9f2e5426a8bae7101d Mon Sep 17 00:00:00 2001 From: tentanus Date: Thu, 28 Dec 2023 00:37:12 +0100 Subject: [PATCH 12/34] added comment --- src/FileManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 7beab62..4e8b802 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -47,7 +47,9 @@ void FileManager::openPostFile(const std::string &request_target_path) ClientState FileManager::openErrorPage(const std::string &error_pages_path, const StatusCode &status_code) -{ +{ Logger &logger = Logger::getInstance(); + + logger.log(DEBUG, "openErrorPage method is called"); _request_target.open(error_pages_path + std::to_string(static_cast(status_code)) + ".html"); @@ -60,6 +62,9 @@ ClientState FileManager::openErrorPage(const std::string &error_pages_path, return (ClientState::Error); } +// still need some elaboration for this part. it seems odd to append the buffer +// to the respons even after it goes into the if(_request_target.bad()). and if +// you don't go in it you've missed your statusline for the response. ClientState FileManager::loadErrorPage(void) { char buffer[BUFFER_SIZE]; From f0605e4db00e0ffe1a8cc8184c58c1e07d29bc1c Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Fri, 29 Dec 2023 20:06:30 +0100 Subject: [PATCH 13/34] webserver returns files, some formatting --- config/default.conf | 35 ++++----------------------------- data/images/coffee-resized.jpg | Bin 0 -> 12260 bytes src/Client.cpp | 11 +++++------ src/FileManager.cpp | 10 +++++----- src/HTTPRequest.cpp | 13 ++++++------ src/LocationSettings.cpp | 19 ++++++++++-------- 6 files changed, 32 insertions(+), 56 deletions(-) create mode 100644 data/images/coffee-resized.jpg diff --git a/config/default.conf b/config/default.conf index aac3868..1ae26aa 100644 --- a/config/default.conf +++ b/config/default.conf @@ -61,8 +61,8 @@ server { # # TODO: all Settings still need implementation into the Webserver # [ ] ServerBlock: -# [ ]- listen; // -# [ ]- server_name; // should go over the Clients/HTTPServers after +# [ ] listen; // +# [ ] server_name; // should go over the Clients/HTTPServers after # // the request is recieved and see which serverSettings block is relevant to the request; # [x] error_dir; // should search this direcotry to find the relevant error file [e.g. 404.html]; # [x] client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; @@ -71,34 +71,7 @@ server { # [ ] index; // file return of the request just specifies this directory ; # [ ] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; # [x] allowed_methods; // should check if the HTTP Method is allowed in this location; -# [ ]- cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; -# [ ]- return; // +# [ ] cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; +# [ ] return; // # [x] HTTPerrorpagegenerator // method that can generate a simple ERROR page to the _response. # -# TODO: Move list to plan -# -#plan: -# -# The location block needs to be added to the client. -# - before we enter the file manager we'll find the serverblock -# -# alias -# if found, fitted preppend on requesttarget -# if none, use requesttarget as is -# -# if the requesttarget is a directory, search LocationBlock for index -# if found, append index to requesttarget -# if none, seach LocationBlock for autoindex -# if found, genrate autoindex and write to _response -# if none, return 404. -# -# -# -#GET www.google.com/ -# /data/www/index.html -# -#GET www.google.com/python/test.py -# /cgi/python/test.py -# -#GET www.google.com/images/puppy.png -# /data/images/puppy.png diff --git a/data/images/coffee-resized.jpg b/data/images/coffee-resized.jpg new file mode 100644 index 0000000000000000000000000000000000000000..799bdb5679822d875d72a67fa0047f913fcd5bd8 GIT binary patch literal 12260 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 M -#include #include #include #include +#include +#include #include @@ -36,8 +36,7 @@ ClientState Client::handleConnection(short events) else if (events & POLLOUT && _state == ClientState::Loading) { _state = _file_manager.manage( - _request.getMethodType(), - "./data/www" + _request.getRequestTarget(), + _request.getMethodType(), _request.getRequestTarget(), _request.getBody()); // TODO: resolve location return (_state); } @@ -58,8 +57,8 @@ ClientState Client::handleConnection(short events) logger.log(ERROR, "Client exception: " + std::string(e.what())); _response.clear(); _response.append(e.what()); - _state = _file_manager.openErrorPage( - _serversetting.getErrorDir(), e.getStatusCode()); + _state = _file_manager.openErrorPage(_serversetting.getErrorDir(), + e.getStatusCode()); return (_state); } return (ClientState::Unkown); diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 4e8b802..62a9d25 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -2,8 +2,8 @@ #include #include -#include #include +#include FileManager::FileManager() : _response(), _request_target() { @@ -15,9 +15,9 @@ FileManager::~FileManager() void FileManager::openGetFile(const std::string &request_target_path) { - if (!std::filesystem::exists(request_target_path)) + if (!std::filesystem::exists(request_target_path.substr(1))) throw ClientException(StatusCode::NotFound); - _request_target.open(request_target_path, std::ios::in); + _request_target.open(request_target_path.substr(1), std::ios::in); if (!_request_target.is_open()) throw ClientException(StatusCode::NotFound); HTTPStatus status(StatusCode::OK); @@ -47,7 +47,8 @@ void FileManager::openPostFile(const std::string &request_target_path) ClientState FileManager::openErrorPage(const std::string &error_pages_path, const StatusCode &status_code) -{ Logger &logger = Logger::getInstance(); +{ + Logger &logger = Logger::getInstance(); logger.log(DEBUG, "openErrorPage method is called"); _request_target.open(error_pages_path + @@ -73,7 +74,6 @@ ClientState FileManager::loadErrorPage(void) { HTTPStatus status(StatusCode::InternalServerError); _response = status.getStatusLine("HTTP/1.1") + status.getHTMLStatus(); - // TODO: @saladuit: shouldn't there be a return here? -> return(ClientState::Sending) } _response += std::string(buffer); if (_request_target.eof()) diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index c9dc087..4f95e6e 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -1,16 +1,15 @@ #include -#include #include #include +#include #include -#include #include #include HTTPRequest::HTTPRequest(const ServerSettings &serversetting) - : _bytes_read(0), _content_length(0), _max_body_size(), + : _bytes_read(0), _content_length(0), _max_body_size(), _methodType(HTTPMethod::UNKNOWN), _http_request(), _request_target(), _http_version(), _body(), _serversetting(serversetting), _headers() { @@ -108,12 +107,12 @@ size_t HTTPRequest::parseStartLine(size_t &i) std::string prelim = _http_request.substr(i, pos - i); const LocationSettings &loc = _serversetting.resolveLocation(prelim); if (prelim.find_last_of('/') == prelim.length() - 1) - logger.log(WARNING, "prelim end with /\t" + prelim); + logger.log(WARNING, "prelim is a Directory:\t" + prelim); setRequestTarget(loc.resolveAlias(prelim)); if (loc.resolveMethod(_methodType) == false) throw ClientException(StatusCode::Forbidden); - + i = pos + 1; pos = _http_request.find("\r\n", i); setHTTPVersion(_http_request.substr(i, pos - i)); @@ -162,7 +161,9 @@ ClientState HTTPRequest::receive(int client_fd) logger.log(DEBUG, "Body: " + _body); return (ClientState::Loading); } - if (_body.size() >= _max_body_size) // @saladuit not sure if this should be before the previous ifstatement + if (_body.size() >= + _max_body_size) // @saladuit not sure if this should be before the + // previous ifstatement throw ClientException(StatusCode::RequestBodyTooLarge); return (ClientState::Receiving); } diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index 44249f1..5b549bd 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -1,7 +1,7 @@ -#include -#include #include +#include +#include #include #include @@ -69,7 +69,7 @@ LocationSettings::LocationSettings(std::vector::iterator &token) { logger.log(WARNING, "LocationSettings: unknown KEY token: " + key.getString()); - break ; + break; } token++; } @@ -124,7 +124,8 @@ void LocationSettings::parseCgiPath(const Token token) if (!_index.empty()) logger.log(WARNING, - "ConfigParser: redefining cgi_path in locationblock: " + _path); + "ConfigParser: redefining cgi_path in locationblock: " + + _path); _cgi_path = token.getString(); } @@ -195,11 +196,13 @@ bool LocationSettings::resolveMethod(const HTTPMethod method) const { Logger &logger = Logger::getInstance(); - if (getAllowedMethods().empty()) - logger.log(WARNING, "ResolveMethod: No HTTPMethod specified in Locationblock: " + getPath()); + if (getAllowedMethods().empty()) + logger.log(WARNING, + "ResolveMethod: No HTTPMethod specified in Locationblock: " + + getPath()); std::stringstream ss(getAllowedMethods()); std::string option; - for (; std::getline(ss, option, ' ') ;) + for (; std::getline(ss, option, ' ');) { if (option == MethodToString(method)) return (true); @@ -219,7 +222,7 @@ const std::string LocationSettings::resolveAlias(const std::string inp) const return (inp); if (_path.length() == 1) return (alias + inp.substr(1, inp.length() - 1)); - + size_t pos_begin = alias.length() - 1; size_t pos_end; while (pos_end != 0) From 56f2bec073bf0627e020caf17c0c162780e8a509 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Sat, 30 Dec 2023 15:33:58 +0100 Subject: [PATCH 14/34] Logger segfaults when moving image, images still don't transport propperly --- config/default.conf | 1 + .../{coffee-resized.jpg => coffee-resized.jpeg} | Bin makerc/options.mk | 2 +- src/Client.cpp | 6 +++--- src/FileManager.cpp | 12 ++++++++---- src/HTTPResponse.cpp | 8 +++++--- src/LocationSettings.cpp | 2 +- 7 files changed, 19 insertions(+), 12 deletions(-) rename data/images/{coffee-resized.jpg => coffee-resized.jpeg} (100%) diff --git a/config/default.conf b/config/default.conf index 1ae26aa..afde938 100644 --- a/config/default.conf +++ b/config/default.conf @@ -60,6 +60,7 @@ server { #www.google.com /python/test.py /bin/usr/foo ? # # TODO: all Settings still need implementation into the Webserver +# [ ] SetDefaultValues for configfile. # [ ] ServerBlock: # [ ] listen; // # [ ] server_name; // should go over the Clients/HTTPServers after diff --git a/data/images/coffee-resized.jpg b/data/images/coffee-resized.jpeg similarity index 100% rename from data/images/coffee-resized.jpg rename to data/images/coffee-resized.jpeg diff --git a/makerc/options.mk b/makerc/options.mk index 80f38ba..2a8ac9e 100644 --- a/makerc/options.mk +++ b/makerc/options.mk @@ -1,6 +1,6 @@ # Flags ifdef DEBUG - CFLAGS +=-g -fstandalone-debug + CFLAGS +=-g #-fstandalone-debug endif diff --git a/src/Client.cpp b/src/Client.cpp index f926e77..18b4af5 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -35,9 +35,9 @@ ClientState Client::handleConnection(short events) } else if (events & POLLOUT && _state == ClientState::Loading) { - _state = _file_manager.manage( - _request.getMethodType(), _request.getRequestTarget(), - _request.getBody()); // TODO: resolve location + _state = _file_manager.manage(_request.getMethodType(), + _request.getRequestTarget(), + _request.getBody()); return (_state); } else if (events & POLLOUT && _state == ClientState::Error) diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 62a9d25..1cf3c80 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -51,7 +51,7 @@ ClientState FileManager::openErrorPage(const std::string &error_pages_path, Logger &logger = Logger::getInstance(); logger.log(DEBUG, "openErrorPage method is called"); - _request_target.open(error_pages_path + + _request_target.open(error_pages_path.substr(1) + std::to_string(static_cast(status_code)) + ".html"); if (!_request_target.is_open()) @@ -64,7 +64,7 @@ ClientState FileManager::openErrorPage(const std::string &error_pages_path, } // still need some elaboration for this part. it seems odd to append the buffer -// to the respons even after it goes into the if(_request_target.bad()). and if +// to the respons even after it goes into the if(_request_target.bad()). and if // you don't go in it you've missed your statusline for the response. ClientState FileManager::loadErrorPage(void) { @@ -86,11 +86,10 @@ ClientState FileManager::manageGet(void) Logger &logger = Logger::getInstance(); char buffer[BUFFER_SIZE + 1]; - logger.log(DEBUG, "manageGet method is called"); + logger.log(DEBUG, "manageGet method is called: "); _request_target.read(buffer, BUFFER_SIZE); if (_request_target.bad()) throw ClientException(StatusCode::InternalServerError); - logger.log(DEBUG, "get buffer: " + std::string(buffer)); buffer[_request_target.gcount()] = '\0'; _response += std::string(buffer); if (_request_target.eof()) @@ -129,6 +128,11 @@ ClientState FileManager::manage(HTTPMethod method, const std::string &request_target_path, const std::string &body) { + Logger &logger = Logger::getInstance(); + + logger.log(DEBUG, "FileManager::manage: " + + std::to_string(static_cast(method)) + " " + + request_target_path + " " + body); if (method == HTTPMethod::DELETE) return (manageDelete(request_target_path)); if (method == HTTPMethod::GET) diff --git a/src/HTTPResponse.cpp b/src/HTTPResponse.cpp index 4770c28..24d3de4 100644 --- a/src/HTTPResponse.cpp +++ b/src/HTTPResponse.cpp @@ -1,8 +1,9 @@ -#include "HTTPRequest.hpp" +#include #include #include #include +#include #include HTTPResponse::HTTPResponse() : _bytes_sent(0), _response("") @@ -34,7 +35,8 @@ ClientState HTTPResponse::send(int client_fd, const std::string &response) _response = response; logger.log(INFO, "Sending response to client on fd: " + std::to_string(client_fd)); - logger.log(DEBUG, "response: " + _response); + // logger.log(DEBUG, "response: " + _response); // this logger line gives a + // segfault when transporting /data/images/conffee-resized.jpeg if (_response.length() - _bytes_sent < BUFFER_SIZE) bytes_to_send = _response.length() - _bytes_sent; else @@ -43,7 +45,7 @@ ClientState HTTPResponse::send(int client_fd, const std::string &response) write(client_fd, _response.substr(_bytes_sent).c_str(), bytes_to_send); if (w_size == -1) throw SystemException("Error: write failed on: " + - std::to_string(client_fd)); // TODO handle error + std::to_string(client_fd)); // TODO: handle error _bytes_sent += w_size; if (_bytes_sent == _response.length()) { diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index 5b549bd..788d2e7 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -224,7 +224,7 @@ const std::string LocationSettings::resolveAlias(const std::string inp) const return (alias + inp.substr(1, inp.length() - 1)); size_t pos_begin = alias.length() - 1; - size_t pos_end; + size_t pos_end = pos_begin; while (pos_end != 0) { pos_end = pos_begin; From 09dc0d3ce68280a0dd73c89e65a36b76eafb33fc Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Thu, 4 Jan 2024 13:15:06 +0100 Subject: [PATCH 15/34] filemanager now is capable of sending binary data --- src/FileManager.cpp | 7 ++++--- src/HTTPResponse.cpp | 2 +- src/ServerSettings.cpp | 11 ++++++----- tests/GET_local.sh | 6 ++++-- tests/get_request.sh | 6 +++--- tests/request/get.txt | 2 +- 6 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 1cf3c80..9c43b10 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -17,7 +17,8 @@ void FileManager::openGetFile(const std::string &request_target_path) { if (!std::filesystem::exists(request_target_path.substr(1))) throw ClientException(StatusCode::NotFound); - _request_target.open(request_target_path.substr(1), std::ios::in); + _request_target.open(request_target_path.substr(1), + std::ios::in | std::ios::binary); if (!_request_target.is_open()) throw ClientException(StatusCode::NotFound); HTTPStatus status(StatusCode::OK); @@ -86,12 +87,12 @@ ClientState FileManager::manageGet(void) Logger &logger = Logger::getInstance(); char buffer[BUFFER_SIZE + 1]; - logger.log(DEBUG, "manageGet method is called: "); + logger.log(DEBUG, "manageGet method is called:"); _request_target.read(buffer, BUFFER_SIZE); if (_request_target.bad()) throw ClientException(StatusCode::InternalServerError); buffer[_request_target.gcount()] = '\0'; - _response += std::string(buffer); + _response += std::string(buffer, _request_target.gcount()); if (_request_target.eof()) return (ClientState::Sending); return (ClientState::Loading); diff --git a/src/HTTPResponse.cpp b/src/HTTPResponse.cpp index 24d3de4..fa7dd9e 100644 --- a/src/HTTPResponse.cpp +++ b/src/HTTPResponse.cpp @@ -35,7 +35,7 @@ ClientState HTTPResponse::send(int client_fd, const std::string &response) _response = response; logger.log(INFO, "Sending response to client on fd: " + std::to_string(client_fd)); - // logger.log(DEBUG, "response: " + _response); // this logger line gives a + // logger.log(DEBUG, "response: " + _response); // this logger line gives a // segfault when transporting /data/images/conffee-resized.jpeg if (_response.length() - _bytes_sent < BUFFER_SIZE) bytes_to_send = _response.length() - _bytes_sent; diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index fd09b18..f7253cc 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -164,10 +164,11 @@ const std::string &ServerSettings::getClientMaxBodySize() const return (_client_max_body_size); } -// Funcion: find the longest possible locationblock that fits the request_target. -// request_target will be stripped from it's trailing input. (line 3) -// and expects LocationBlock requesttarget to always start and end with a '/' -// +// Funcion: find the longest possible locationblock that fits the +// request_target. request_target will be stripped from it's trailing input. +// (line 3) and expects LocationBlock requesttarget to always start and end with +// a '/' +// // EXAMPLES: // // server { @@ -195,7 +196,7 @@ ServerSettings::resolveLocation(const std::string &request_target) const { const size_t pos = request_target.find(instance.getPath()); - if (pos == std::string::npos) + if (pos != 0) continue; if (ret == nullptr) { diff --git a/tests/GET_local.sh b/tests/GET_local.sh index ba99459..1a2a114 100755 --- a/tests/GET_local.sh +++ b/tests/GET_local.sh @@ -1,16 +1,18 @@ #!/bin/bash if [[ -z $1 ]]; then - SERVER_PORT="9696" + SERVER_PORT="8080" else SERVER_PORT=$1 fi -HTTP_VERSION="http1.1" +HTTP_VERSION="HTTP/1.1" SERVER_HOST="localhost" SERVER_LOG_DIR=../build/log/ +HTTP_REQUEST="./request/get.txt" + echo "GET REQUEST on localhost at port $SERVER_PORT" echo "" diff --git a/tests/get_request.sh b/tests/get_request.sh index 8923074..30d03d3 100755 --- a/tests/get_request.sh +++ b/tests/get_request.sh @@ -2,10 +2,10 @@ # Server configuration SERVER_HOST="localhost" -SERVER_PORT="9696" +SERVER_PORT="8080" # Request file -REQUEST_FILE="tests/request/delete.txt" +REQUEST_FILE="tests/request/get.txt" # Use netcat to send the contents of the request file to the server -nc "${SERVER_HOST}" "${SERVER_PORT}" < "${REQUEST_FILE}" +nc "${SERVER_HOST}" "${SERVER_PORT}" <"${REQUEST_FILE}" diff --git a/tests/request/get.txt b/tests/request/get.txt index b5de54c..0135c00 100755 --- a/tests/request/get.txt +++ b/tests/request/get.txt @@ -1,4 +1,4 @@ -GET /index.html HTTP/1.1 +GET /images/coffee-resized.jpeg HTTP/1.1 User-Agent: custom-client Host: weebserv Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5 From 86e947fd9340385139a0cc8311cd20d0ac50ba29 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Thu, 4 Jan 2024 17:53:45 +0100 Subject: [PATCH 16/34] Filemanager contains the Serversetting instead of HTTPRequest; Found bug in Error pages; --- config/default.conf | 2 +- include/FileManager.hpp | 8 ++++++ include/HTTPRequest.hpp | 6 ++--- src/Client.cpp | 11 ++++++--- src/FileManager.cpp | 55 +++++++++++++++++++++++++++++++++-------- src/HTTPRequest.cpp | 18 ++++---------- src/HTTPResponse.cpp | 4 +++ src/ServerSettings.cpp | 3 ++- tests/request/get.txt | 2 +- 9 files changed, 76 insertions(+), 33 deletions(-) diff --git a/config/default.conf b/config/default.conf index afde938..70b0949 100644 --- a/config/default.conf +++ b/config/default.conf @@ -69,7 +69,7 @@ server { # [x] client_max_body_size; // limits the size of the client Request, returning 413 when it exceeds this value; # [ ] Location Block: # [x] alias; // should do a fitted preppend on the path in URI; -# [ ] index; // file return of the request just specifies this directory ; +# [x] index; // file return of the request just specifies this directory ; # [ ] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; # [x] allowed_methods; // should check if the HTTP Method is allowed in this location; # [ ] cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; diff --git a/include/FileManager.hpp b/include/FileManager.hpp index 8f08a4c..dec88e4 100644 --- a/include/FileManager.hpp +++ b/include/FileManager.hpp @@ -3,6 +3,9 @@ #include #include +#include +#include + #include #include @@ -11,9 +14,14 @@ class FileManager private: std::string _response; std::fstream _request_target; + const ServerSettings &_serversetting; + + std::string applyLocationSettings(const std::string &request_target, + HTTPMethod method); public: FileManager(); + FileManager(const ServerSettings &ServerSettings); FileManager(const FileManager &other) = delete; void operator=(const FileManager &other) = delete; ~FileManager(); diff --git a/include/HTTPRequest.hpp b/include/HTTPRequest.hpp index e2e7a17..0ae06df 100644 --- a/include/HTTPRequest.hpp +++ b/include/HTTPRequest.hpp @@ -2,6 +2,7 @@ #define HTTP_REQUEST_HPP #include +#include #include #include @@ -26,14 +27,11 @@ enum class HTTPMethod }; #endif -#include - // CLASS class HTTPRequest { public: HTTPRequest(); - HTTPRequest(const ServerSettings &serversetting); HTTPRequest(const HTTPRequest &rhs) = delete; HTTPRequest &operator=(const HTTPRequest &rhs) = delete; ~HTTPRequest(); @@ -65,11 +63,11 @@ class HTTPRequest std::string _request_target; std::string _http_version; std::string _body; - ServerSettings _serversetting; std::unordered_map _headers; size_t parseStartLine(size_t &i); size_t parseHeaders(size_t &i); + void setLocationdependancies(std::string request_target); }; #endif diff --git a/src/Client.cpp b/src/Client.cpp index 18b4af5..6689d97 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -7,9 +7,11 @@ #include Client::Client(const int &server_fd, const ServerSettings &serversetting) - : _request(serversetting), _socket(server_fd), _serversetting(serversetting) + : _request(), _file_manager(serversetting), _socket(server_fd), + _serversetting(serversetting) { _socket.setupClient(); + _request.setMaxBodySize(_serversetting.getClientMaxBodySize()); } Client::~Client() @@ -57,8 +59,11 @@ ClientState Client::handleConnection(short events) logger.log(ERROR, "Client exception: " + std::string(e.what())); _response.clear(); _response.append(e.what()); - _state = _file_manager.openErrorPage(_serversetting.getErrorDir(), - e.getStatusCode()); + _state = _file_manager.openErrorPage( + _serversetting.getErrorDir().substr(1), e.getStatusCode()); + // TODO: Fix Error page: + // Error status is put in Client::_response + // Error page loaded is put into FileManager::_response return (_state); } return (ClientState::Unkown); diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 9c43b10..1771142 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -5,7 +5,8 @@ #include #include -FileManager::FileManager() : _response(), _request_target() +FileManager::FileManager(const ServerSettings &ServerSettings) + : _response(), _request_target(), _serversetting(ServerSettings) { } @@ -13,12 +14,39 @@ FileManager::~FileManager() { } +std::string +FileManager::applyLocationSettings(const std::string &request_target, + HTTPMethod method) +{ + Logger &logger = Logger::getInstance(); + + const LocationSettings &loc = + _serversetting.resolveLocation(request_target); + + if (loc.resolveMethod(method) == false) + throw ClientException(StatusCode::MethodNotAllowed); + + if (request_target.find_last_of('/') == request_target.length() - 1) + { + logger.log(WARNING, + "request_target is a Directory:\t" + request_target); + if (loc.getAutoIndex()) + return (loc.resolveAlias(request_target).substr(1)); + return (loc.resolveAlias(request_target).substr(1) + loc.getIndex()); + } + + return (loc.resolveAlias(request_target).substr(1)); + // substr is required to remove starting '/' ^ +} + void FileManager::openGetFile(const std::string &request_target_path) { - if (!std::filesystem::exists(request_target_path.substr(1))) + const std::string resolved_target = + applyLocationSettings(request_target_path, HTTPMethod::GET); + + if (!std::filesystem::exists(resolved_target)) throw ClientException(StatusCode::NotFound); - _request_target.open(request_target_path.substr(1), - std::ios::in | std::ios::binary); + _request_target.open(resolved_target, std::ios::in); if (!_request_target.is_open()) throw ClientException(StatusCode::NotFound); HTTPStatus status(StatusCode::OK); @@ -51,10 +79,13 @@ ClientState FileManager::openErrorPage(const std::string &error_pages_path, { Logger &logger = Logger::getInstance(); - logger.log(DEBUG, "openErrorPage method is called"); - _request_target.open(error_pages_path.substr(1) + - std::to_string(static_cast(status_code)) + - ".html"); + logger.log(DEBUG, "openErrorPage method is called. (" + error_pages_path + + std::to_string(static_cast(status_code)) + + ".html)"); + _request_target.open(error_pages_path + + std::to_string(static_cast(status_code)) + + ".html", + std::ios::in); if (!_request_target.is_open()) { HTTPStatus status(status_code); @@ -76,10 +107,14 @@ ClientState FileManager::loadErrorPage(void) HTTPStatus status(StatusCode::InternalServerError); _response = status.getStatusLine("HTTP/1.1") + status.getHTMLStatus(); } - _response += std::string(buffer); + buffer[_request_target.gcount()] = '\0'; + _response += std::string(buffer, _request_target.gcount()); if (_request_target.eof()) + { return (ClientState::Sending); - return (ClientState::Loading); + } + return (ClientState::Error); // @saladuit changed this to Error since the + // file needs to keep reading this fstream } ClientState FileManager::manageGet(void) diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index 4f95e6e..9984367 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -8,12 +8,11 @@ #include -HTTPRequest::HTTPRequest(const ServerSettings &serversetting) +HTTPRequest::HTTPRequest() : _bytes_read(0), _content_length(0), _max_body_size(), _methodType(HTTPMethod::UNKNOWN), _http_request(), _request_target(), - _http_version(), _body(), _serversetting(serversetting), _headers() + _http_version(), _body(), _headers() { - setMaxBodySize(_serversetting.getClientMaxBodySize()); } HTTPRequest::~HTTPRequest() @@ -101,17 +100,10 @@ size_t HTTPRequest::parseStartLine(size_t &i) pos = _http_request.find(' ', i); setMethodType(_http_request.substr(i, pos - i)); + i = pos + 1; pos = _http_request.find(' ', i); - - std::string prelim = _http_request.substr(i, pos - i); - const LocationSettings &loc = _serversetting.resolveLocation(prelim); - if (prelim.find_last_of('/') == prelim.length() - 1) - logger.log(WARNING, "prelim is a Directory:\t" + prelim); - - setRequestTarget(loc.resolveAlias(prelim)); - if (loc.resolveMethod(_methodType) == false) - throw ClientException(StatusCode::Forbidden); + setRequestTarget(_http_request.substr(i, pos - i)); i = pos + 1; pos = _http_request.find("\r\n", i); @@ -163,7 +155,7 @@ ClientState HTTPRequest::receive(int client_fd) } if (_body.size() >= _max_body_size) // @saladuit not sure if this should be before the - // previous ifstatement + // previous ifstatement throw ClientException(StatusCode::RequestBodyTooLarge); return (ClientState::Receiving); } diff --git a/src/HTTPResponse.cpp b/src/HTTPResponse.cpp index fa7dd9e..ae6da4e 100644 --- a/src/HTTPResponse.cpp +++ b/src/HTTPResponse.cpp @@ -31,8 +31,12 @@ ClientState HTTPResponse::send(int client_fd, const std::string &response) ssize_t bytes_to_send; ssize_t w_size; + // logger.log(DEBUG, "_response: " + _response); + // logger.log(DEBUG, "response: " + response); if (_response.empty()) + { _response = response; + } logger.log(INFO, "Sending response to client on fd: " + std::to_string(client_fd)); // logger.log(DEBUG, "response: " + _response); // this logger line gives a diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index f7253cc..4c2ecdd 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -212,7 +212,8 @@ ServerSettings::resolveLocation(const std::string &request_target) const return (*ret); } -/* TODO: move to relevant class, i think it should be HTTPRequest +/* TODO: move this method to relevant class, i think it should be Client or + Filemanager bool ServerSettings::resolveServerName(const std::string &RequestHost) { diff --git a/tests/request/get.txt b/tests/request/get.txt index 0135c00..d112b5f 100755 --- a/tests/request/get.txt +++ b/tests/request/get.txt @@ -1,4 +1,4 @@ -GET /images/coffee-resized.jpeg HTTP/1.1 +GET /test/errors HTTP/1.1 User-Agent: custom-client Host: weebserv Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5 From 6ab65058660dfc31e19bb42dd364d6c9047dd176 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Fri, 5 Jan 2024 18:13:32 +0100 Subject: [PATCH 17/34] adding start AutoIndexGenerator; --- config/default.conf | 2 +- include/AutoIndexGenerator.hpp | 15 ++++++++++ include/Client.hpp | 2 +- include/FileManager.hpp | 1 + src/AutoIndexGenerator.cpp | 50 ++++++++++++++++++++++++++++++++++ src/Client.cpp | 3 +- src/FileManager.cpp | 29 ++++++++++++-------- src/LocationSettings.cpp | 2 ++ 8 files changed, 90 insertions(+), 14 deletions(-) create mode 100644 include/AutoIndexGenerator.hpp create mode 100644 src/AutoIndexGenerator.cpp diff --git a/config/default.conf b/config/default.conf index 70b0949..806c5aa 100644 --- a/config/default.conf +++ b/config/default.conf @@ -18,7 +18,7 @@ server { location / { # [1 - O] Request Target is the Target of the HTTP request; starts with a / alias /data/www/; # [1 - O] links the stated Direcotry as the RequestTarget Location ; [/]{1}[A-Za-z_/:w]* ; Default: /data/www - index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html +# index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html allowed_methods GET; # [M - O] Define a list of accepted HTTP methods for the route; GET/POST/DELETE ; Default: GET autoindex on; # [B - O] Turn on or off directory listing; on; Default: off } diff --git a/include/AutoIndexGenerator.hpp b/include/AutoIndexGenerator.hpp new file mode 100644 index 0000000..6292cd4 --- /dev/null +++ b/include/AutoIndexGenerator.hpp @@ -0,0 +1,15 @@ +#ifndef AUTOINDEXGENERATOR_HPP +#define AUTOINDEXGENERATOR_HPP + +#include + +#include +#include + +namespace AutoIndexGenerator +{ +std::fstream OpenAutoIndex(std::string directory, const std::string uri); +std::string AutoIndexGenerator(const std::string dir); +} // namespace AutoIndexGenerator + +#endif // !AUTOINDEXGENERATOR_HPP diff --git a/include/Client.hpp b/include/Client.hpp index daf12d9..97906ec 100644 --- a/include/Client.hpp +++ b/include/Client.hpp @@ -1,11 +1,11 @@ #ifndef CLIENT_HPP #define CLIENT_HPP -#include #include #include #include #include +#include #include class Client diff --git a/include/FileManager.hpp b/include/FileManager.hpp index dec88e4..66528f6 100644 --- a/include/FileManager.hpp +++ b/include/FileManager.hpp @@ -15,6 +15,7 @@ class FileManager std::string _response; std::fstream _request_target; const ServerSettings &_serversetting; + bool _autoindex; std::string applyLocationSettings(const std::string &request_target, HTTPMethod method); diff --git a/src/AutoIndexGenerator.cpp b/src/AutoIndexGenerator.cpp new file mode 100644 index 0000000..039eaaf --- /dev/null +++ b/src/AutoIndexGenerator.cpp @@ -0,0 +1,50 @@ + +#include "Logger.hpp" +#include + +#include +#include + +std::string excludeSpecialCharacters(std::string str) +{ + std::string result; + + for (std::string::iterator it = str.begin(); it != str.end(); ++it) + { + if (*it == '/') + result += "_"; + else + result += *it; + } + return (result); +} + +std::string AutoIndexGenerator::AutoIndexGenerator(const std::string dir) +{ + return (dir); +} + +std::fstream AutoIndexGenerator::OpenAutoIndex(std::string directory, + const std::string uri) +{ + (void)uri; + Logger &logger = Logger::getInstance(); + + logger.log(DEBUG, "OpenAutoIndex method is called:"); + directory = excludeSpecialCharacters(directory); + + const std::string filename = "/tmp/" + directory + ".autoindex"; + + std::fstream autoindex_fstream(filename.c_str(), std::fstream::out); + if (!autoindex_fstream.is_open()) + logger.log(DEBUG, filename + " isn't opened."); + + logger.log(DEBUG, AutoIndexGenerator(directory)); + autoindex_fstream.close(); + + exit(1); + std::fstream return_fstream(filename, std::ios::in); + std::remove(filename.c_str()); + + return (return_fstream); +} diff --git a/src/Client.cpp b/src/Client.cpp index 6689d97..f326861 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -63,7 +63,8 @@ ClientState Client::handleConnection(short events) _serversetting.getErrorDir().substr(1), e.getStatusCode()); // TODO: Fix Error page: // Error status is put in Client::_response - // Error page loaded is put into FileManager::_response + // Errorpage fsteam is put into FileManager::_response + // in HTTPResponse::send this clashes in the first if statement return (_state); } return (ClientState::Unkown); diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 1771142..35d90c0 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -1,3 +1,5 @@ +#include "StatusCode.hpp" +#include #include #include #include @@ -6,7 +8,8 @@ #include FileManager::FileManager(const ServerSettings &ServerSettings) - : _response(), _request_target(), _serversetting(ServerSettings) + : _response(), _request_target(), _serversetting(ServerSettings), + _autoindex(false) { } @@ -18,8 +21,6 @@ std::string FileManager::applyLocationSettings(const std::string &request_target, HTTPMethod method) { - Logger &logger = Logger::getInstance(); - const LocationSettings &loc = _serversetting.resolveLocation(request_target); @@ -28,13 +29,16 @@ FileManager::applyLocationSettings(const std::string &request_target, if (request_target.find_last_of('/') == request_target.length() - 1) { - logger.log(WARNING, - "request_target is a Directory:\t" + request_target); - if (loc.getAutoIndex()) - return (loc.resolveAlias(request_target).substr(1)); - return (loc.resolveAlias(request_target).substr(1) + loc.getIndex()); + if (!loc.getIndex().empty()) + return (loc.resolveAlias(request_target).substr(1) + + loc.getIndex()); + else if (loc.getAutoIndex() == false) + return (loc.resolveAlias(request_target).substr(1) + + "index.html"); // default value; + _request_target = AutoIndexGenerator::OpenAutoIndex( + loc.resolveAlias(request_target).substr(1), request_target); + _autoindex = true; } - return (loc.resolveAlias(request_target).substr(1)); // substr is required to remove starting '/' ^ } @@ -43,10 +47,12 @@ void FileManager::openGetFile(const std::string &request_target_path) { const std::string resolved_target = applyLocationSettings(request_target_path, HTTPMethod::GET); + if (_autoindex == true) + return; if (!std::filesystem::exists(resolved_target)) throw ClientException(StatusCode::NotFound); - _request_target.open(resolved_target, std::ios::in); + _request_target.open(resolved_target, std::ios::in | std::ios::binary); if (!_request_target.is_open()) throw ClientException(StatusCode::NotFound); HTTPStatus status(StatusCode::OK); @@ -114,7 +120,8 @@ ClientState FileManager::loadErrorPage(void) return (ClientState::Sending); } return (ClientState::Error); // @saladuit changed this to Error since the - // file needs to keep reading this fstream + // file needs to keep reading this and + // loadErrorPage } ClientState FileManager::manageGet(void) diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index 788d2e7..a150f77 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -8,6 +8,8 @@ #include LocationSettings::LocationSettings() + : _path(), _alias(), _index(), _allowed_methods(), _cgi_path(), + _auto_index(false) { } From beb4374db0c8b3b3bfd9253c3d755a865604661b Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Fri, 5 Jan 2024 18:18:22 +0100 Subject: [PATCH 18/34] changing includes --- include/AutoIndexGenerator.hpp | 3 ++- include/Client.hpp | 12 ++++++------ include/FileManager.hpp | 8 ++++---- src/AutoIndexGenerator.cpp | 2 +- src/FileManager.cpp | 8 ++++---- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/include/AutoIndexGenerator.hpp b/include/AutoIndexGenerator.hpp index 6292cd4..8743385 100644 --- a/include/AutoIndexGenerator.hpp +++ b/include/AutoIndexGenerator.hpp @@ -1,8 +1,9 @@ #ifndef AUTOINDEXGENERATOR_HPP #define AUTOINDEXGENERATOR_HPP -#include +#include "Logger.hpp" +#include #include #include diff --git a/include/Client.hpp b/include/Client.hpp index 97906ec..507c8bd 100644 --- a/include/Client.hpp +++ b/include/Client.hpp @@ -1,12 +1,12 @@ #ifndef CLIENT_HPP #define CLIENT_HPP -#include -#include -#include -#include -#include -#include +#include "CGI.hpp" +#include "FileManager.hpp" +#include "HTTPRequest.hpp" +#include "HTTPResponse.hpp" +#include "ServerSettings.hpp" +#include "Socket.hpp" class Client { diff --git a/include/FileManager.hpp b/include/FileManager.hpp index 66528f6..8c5a890 100644 --- a/include/FileManager.hpp +++ b/include/FileManager.hpp @@ -1,10 +1,10 @@ #ifndef FILE_MANAGER_HPP #define FILE_MANAGER_HPP -#include -#include -#include -#include +#include "HTTPRequest.hpp" +#include "HTTPStatus.hpp" +#include "LocationSettings.hpp" +#include "ServerSettings.hpp" #include #include diff --git a/src/AutoIndexGenerator.cpp b/src/AutoIndexGenerator.cpp index 039eaaf..26c43bc 100644 --- a/src/AutoIndexGenerator.cpp +++ b/src/AutoIndexGenerator.cpp @@ -1,6 +1,6 @@ +#include "AutoIndexGenerator.hpp" #include "Logger.hpp" -#include #include #include diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 35d90c0..95af5d5 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -1,8 +1,8 @@ +#include "FileManager.hpp" +#include "AutoIndexGenerator.hpp" +#include "ClientException.hpp" +#include "Logger.hpp" #include "StatusCode.hpp" -#include -#include -#include -#include #include #include From 48e39e2df949fd63ba69f145d6e5224b911829bc Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Sun, 7 Jan 2024 15:36:39 +0100 Subject: [PATCH 19/34] just added a parameter, that's it --- include/AutoIndexGenerator.hpp | 3 ++- src/AutoIndexGenerator.cpp | 35 ++++++++++++++++++++++++++++++---- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/include/AutoIndexGenerator.hpp b/include/AutoIndexGenerator.hpp index 8743385..cd401cc 100644 --- a/include/AutoIndexGenerator.hpp +++ b/include/AutoIndexGenerator.hpp @@ -10,7 +10,8 @@ namespace AutoIndexGenerator { std::fstream OpenAutoIndex(std::string directory, const std::string uri); -std::string AutoIndexGenerator(const std::string dir); +std::string AutoIndexGenerator(const std::string dir, const std::string uri); + } // namespace AutoIndexGenerator #endif // !AUTOINDEXGENERATOR_HPP diff --git a/src/AutoIndexGenerator.cpp b/src/AutoIndexGenerator.cpp index 26c43bc..932dc31 100644 --- a/src/AutoIndexGenerator.cpp +++ b/src/AutoIndexGenerator.cpp @@ -2,6 +2,7 @@ #include "AutoIndexGenerator.hpp" #include "Logger.hpp" +#include #include #include @@ -19,15 +20,41 @@ std::string excludeSpecialCharacters(std::string str) return (result); } -std::string AutoIndexGenerator::AutoIndexGenerator(const std::string dir) +std::string AutoIndexGenerator::AutoIndexGenerator(const std::string dir, + const std::string uri) { - return (dir); + std::string response; + + (void)dir; + (void)uri; + /* + + + Index of DIR</ title> + </ head> + <body> + <h1> Index of DIR</ h1> + <table style = "width:80%;font-size:15px"> + <tbody> + <tr> + <th style = "text-align:left"> File Name</ th> + <th style = "text-align:left"> Last Modification</ th> + <th style = "text-align:left"> File Size</ th> + </ tr><tr> + <th style = "text-align:left">.</ th> + < th style ="text-align:left" > 07 Jan</ th> + < th style ="text-align:left" > 253 B</ th> + </ tr> + </ tbody> + </ table> + </ body> + */ + return (response); } std::fstream AutoIndexGenerator::OpenAutoIndex(std::string directory, const std::string uri) { - (void)uri; Logger &logger = Logger::getInstance(); logger.log(DEBUG, "OpenAutoIndex method is called:"); @@ -39,7 +66,7 @@ std::fstream AutoIndexGenerator::OpenAutoIndex(std::string directory, if (!autoindex_fstream.is_open()) logger.log(DEBUG, filename + " isn't opened."); - logger.log(DEBUG, AutoIndexGenerator(directory)); + logger.log(DEBUG, AutoIndexGenerator(directory, uri)); autoindex_fstream.close(); exit(1); From 13c89996aa6c3291c86bb867e182b5dd318ff501 Mon Sep 17 00:00:00 2001 From: Martijn Weverling <mweverli@student.codam.nl> Date: Wed, 10 Jan 2024 18:15:19 +0100 Subject: [PATCH 20/34] AutoIndexGenerator almost finished --- src/AutoIndexGenerator.cpp | 106 +++++++++++++++++++++++++++---------- tests/request/get.txt | 2 +- 2 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/AutoIndexGenerator.cpp b/src/AutoIndexGenerator.cpp index 932dc31..8405cac 100644 --- a/src/AutoIndexGenerator.cpp +++ b/src/AutoIndexGenerator.cpp @@ -3,6 +3,10 @@ #include "Logger.hpp" #include <dirent.h> +#include <sys/stat.h> +#include <time.h> + +#include <filesystem> #include <fstream> #include <string> @@ -20,35 +24,83 @@ std::string excludeSpecialCharacters(std::string str) return (result); } +const std::string getStatSize(struct stat &filestat) +{ + std::string str; + char buf[100]; + time_t date = filestat.st_mtime; + struct tm *time = localtime(&date); + + strftime(buf, sizeof(buf), "%d %m %y", time); + str = std::string(buf); + + return (str); +} + +const std::string getStatDateLastModified(struct stat &filestat) +{ + std::string str = std::to_string((intmax_t)filestat.st_size); + return (str); +} + +void getTableLines(std::string &response, const std::string dir) +{ + // clang-format off + DIR *dirptr = opendir(dir.c_str()); + struct dirent *direnty; + + std::filesystem::path pwd = std::filesystem::current_path(); + short statreturn; + std::string filepath; + struct stat filestat; + + for (size_t i = 0 ; i < 2 ; i++) + direnty = readdir(dirptr); + while ((direnty = readdir(dirptr)) != NULL) + { + filepath = pwd.string() + "/" + dir + direnty->d_name; + statreturn = stat(filepath.c_str(), &filestat); + response += "\t\t<tr>\n\ + \t\t\t<th style =\"text-align:left\" >" + std::string(direnty->d_name) + "</th>\n\ + \t\t\t<th style =\"text-align:left\" >" + ((statreturn != -1) ? getStatDateLastModified(filestat) : "UNKOWN") + "</th>\n\ + \t\t\t<th style =\"text-align:left\" >" + ((statreturn != -1) ? getStatSize(filestat) : "UNKNOWN") + "</th>\n\ + \t\t</tr>"; + } + // clang-format on +} + std::string AutoIndexGenerator::AutoIndexGenerator(const std::string dir, const std::string uri) { std::string response; - (void)dir; - (void)uri; - /* - <html> - <head> - <title> Index of DIR</ title> - </ head> - <body> - <h1> Index of DIR</ h1> - <table style = "width:80%;font-size:15px"> - <tbody> - <tr> - <th style = "text-align:left"> File Name</ th> - <th style = "text-align:left"> Last Modification</ th> - <th style = "text-align:left"> File Size</ th> - </ tr><tr> - <th style = "text-align:left">.</ th> - < th style ="text-align:left" > 07 Jan</ th> - < th style ="text-align:left" > 253 B</ th> - </ tr> - </ tbody> - </ table> - </ body> - */ + // clang-format off + response = "<!DOCTYPE html>\n\ + <html>\n\ + \t<head>\n\ + \t\t<title> Index of "; + response += uri; + response += "\n\ + \t\n\ + \t\n\ + \t\t

Index of "; + response += uri; + response += "

\n\ + \t\t\n\ + \t\t\n\ + \t\t\n\ + \t\t\t\n\ + \t\t\t\n\ + \t\t\t\n\ + \t\t\n"; + + getTableLines(response, dir); + + response += "\ + \t\t\n\ + \t\t
File Name File Size Last Modification
\n\ + \t\n"; + // clang-format on return (response); } @@ -58,15 +110,15 @@ std::fstream AutoIndexGenerator::OpenAutoIndex(std::string directory, Logger &logger = Logger::getInstance(); logger.log(DEBUG, "OpenAutoIndex method is called:"); - directory = excludeSpecialCharacters(directory); + const std::string escapeddir = excludeSpecialCharacters(directory); - const std::string filename = "/tmp/" + directory + ".autoindex"; + const std::string filename = "/tmp/" + escapeddir + ".autoindex"; std::fstream autoindex_fstream(filename.c_str(), std::fstream::out); if (!autoindex_fstream.is_open()) logger.log(DEBUG, filename + " isn't opened."); - logger.log(DEBUG, AutoIndexGenerator(directory, uri)); + autoindex_fstream << AutoIndexGenerator(directory, uri); autoindex_fstream.close(); exit(1); diff --git a/tests/request/get.txt b/tests/request/get.txt index d112b5f..ca02290 100755 --- a/tests/request/get.txt +++ b/tests/request/get.txt @@ -1,4 +1,4 @@ -GET /test/errors HTTP/1.1 +GET / HTTP/1.1 User-Agent: custom-client Host: weebserv Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5 From b7a52806f0da0de7d5cc20d1ca9b5f3216ae9721 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Thu, 11 Jan 2024 18:08:38 +0100 Subject: [PATCH 21/34] AutoIndexGenerator working --- config/default.conf | 4 ++-- src/AutoIndexGenerator.cpp | 20 ++++++++++---------- src/FileManager.cpp | 10 ++++++---- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/config/default.conf b/config/default.conf index 806c5aa..8b2cffc 100644 --- a/config/default.conf +++ b/config/default.conf @@ -59,7 +59,7 @@ server { # #www.google.com /python/test.py /bin/usr/foo ? # -# TODO: all Settings still need implementation into the Webserver +#TODO: all Settings still need implementation into the Webserver # [ ] SetDefaultValues for configfile. # [ ] ServerBlock: # [ ] listen; // @@ -70,7 +70,7 @@ server { # [ ] Location Block: # [x] alias; // should do a fitted preppend on the path in URI; # [x] index; // file return of the request just specifies this directory ; -# [ ] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; +# [x] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; # [x] allowed_methods; // should check if the HTTP Method is allowed in this location; # [ ] cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; # [ ] return; // diff --git a/src/AutoIndexGenerator.cpp b/src/AutoIndexGenerator.cpp index 8405cac..b1ffbe3 100644 --- a/src/AutoIndexGenerator.cpp +++ b/src/AutoIndexGenerator.cpp @@ -14,7 +14,7 @@ std::string excludeSpecialCharacters(std::string str) { std::string result; - for (std::string::iterator it = str.begin(); it != str.end(); ++it) + for (std::string::iterator it = str.begin(); it != str.end() - 1; ++it) { if (*it == '/') result += "_"; @@ -75,18 +75,19 @@ std::string AutoIndexGenerator::AutoIndexGenerator(const std::string dir, std::string response; // clang-format off - response = "\n\ - \n\ - \t\n\ - \t\t Index of "; + response = "\ +<!DOCTYPE html>\n\ + <html>\n\ + <head>\n\ + \t<title> Index of "; response += uri; response += "\n\ - \t\n\ - \t\n\ - \t\t

Index of "; + \n\ + \n\ +

Index of "; response += uri; response += "

\n\ - \t\t\n\ + \t
\n\ \t\t\n\ \t\t\n\ \t\t\t\n\ @@ -121,7 +122,6 @@ std::fstream AutoIndexGenerator::OpenAutoIndex(std::string directory, autoindex_fstream << AutoIndexGenerator(directory, uri); autoindex_fstream.close(); - exit(1); std::fstream return_fstream(filename, std::ios::in); std::remove(filename.c_str()); diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 95af5d5..6dfc678 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -21,6 +21,7 @@ std::string FileManager::applyLocationSettings(const std::string &request_target, HTTPMethod method) { + // substr is required to remove starting '/' const LocationSettings &loc = _serversetting.resolveLocation(request_target); @@ -40,7 +41,6 @@ FileManager::applyLocationSettings(const std::string &request_target, _autoindex = true; } return (loc.resolveAlias(request_target).substr(1)); - // substr is required to remove starting '/' ^ } void FileManager::openGetFile(const std::string &request_target_path) @@ -48,7 +48,11 @@ void FileManager::openGetFile(const std::string &request_target_path) const std::string resolved_target = applyLocationSettings(request_target_path, HTTPMethod::GET); if (_autoindex == true) + { + HTTPStatus status(StatusCode::OK); + _response += status.getStatusLine("HTTP/1.1"); return; + } if (!std::filesystem::exists(resolved_target)) throw ClientException(StatusCode::NotFound); @@ -173,9 +177,7 @@ ClientState FileManager::manage(HTTPMethod method, { Logger &logger = Logger::getInstance(); - logger.log(DEBUG, "FileManager::manage: " + - std::to_string(static_cast(method)) + " " + - request_target_path + " " + body); + logger.log(DEBUG, "FileManager::manage: "); if (method == HTTPMethod::DELETE) return (manageDelete(request_target_path)); if (method == HTTPMethod::GET) From 51a5c0cf26197bb4adabbf2d6ff3af68a03cce4c Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Fri, 12 Jan 2024 11:34:55 +0100 Subject: [PATCH 22/34] formatting on AutoIndexGenerator --- include/FileManager.hpp | 1 - src/AutoIndexGenerator.cpp | 31 ++++++++++++++++--------------- src/FileManager.cpp | 2 +- tests/request/get.txt | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/include/FileManager.hpp b/include/FileManager.hpp index 8c5a890..59e67fd 100644 --- a/include/FileManager.hpp +++ b/include/FileManager.hpp @@ -31,7 +31,6 @@ class FileManager void openPostFile(const std::string &request_target_path); ClientState openErrorPage(const std::string &error_pages_path, const StatusCode &status_code); - ClientState setErrorResponse(const StatusCode &status_code); ClientState loadErrorPage(void); ClientState manage(HTTPMethod method, const std::string &filename, const std::string &body); diff --git a/src/AutoIndexGenerator.cpp b/src/AutoIndexGenerator.cpp index b1ffbe3..a148c13 100644 --- a/src/AutoIndexGenerator.cpp +++ b/src/AutoIndexGenerator.cpp @@ -61,10 +61,10 @@ void getTableLines(std::string &response, const std::string dir) filepath = pwd.string() + "/" + dir + direnty->d_name; statreturn = stat(filepath.c_str(), &filestat); response += "\t\t\n\ - \t\t\t\n\ - \t\t\t\n\ - \t\t\t\n\ - \t\t"; + \n\ + \n\ + \n\ + \n"; } // clang-format on } @@ -77,7 +77,7 @@ std::string AutoIndexGenerator::AutoIndexGenerator(const std::string dir, // clang-format off response = "\ \n\ - \n\ +\n\ \n\ \t Index of "; response += uri; @@ -87,20 +87,21 @@ std::string AutoIndexGenerator::AutoIndexGenerator(const std::string dir, <h1> Index of "; response += uri; response += "</h1>\n\ - \t<table style = \"width:80%;font-size:15px\">\n\ - \t\t<tbody>\n\ - \t\t<tr>\n\ - \t\t\t<th style = \"text-align:left\"> File Name</th>\n\ - \t\t\t<th style = \"text-align:left\"> File Size</th>\n\ - \t\t\t<th style = \"text-align:left\"> Last Modification</th>\n\ - \t\t</tr>\n"; + <hr>\n\ + <table style = \"width:80%;font-size:15px\">\n\ + <tbody>\n\ + <tr>\n\ + \t<th style = \"text-align:left\"> File Name</th>\n\ + \t<th style = \"text-align:left\"> File Size</th>\n\ + \t<th style = \"text-align:left\"> Last Modification</th>\n\ + </tr>\n"; getTableLines(response, dir); response += "\ - \t\t</tbody>\n\ - \t\t</table>\n\ - \t</body>\n"; + </tbody>\n\ + </table>\n\ + </body>\n"; // clang-format on return (response); } diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 6dfc678..48db1ca 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -124,7 +124,7 @@ ClientState FileManager::loadErrorPage(void) return (ClientState::Sending); } return (ClientState::Error); // @saladuit changed this to Error since the - // file needs to keep reading this and + // file needs to keep reading this fstream and // loadErrorPage } diff --git a/tests/request/get.txt b/tests/request/get.txt index ca02290..6543118 100755 --- a/tests/request/get.txt +++ b/tests/request/get.txt @@ -1,4 +1,4 @@ -GET / HTTP/1.1 +GET /this/wont/work HTTP/1.1 User-Agent: custom-client Host: weebserv Accept-Language: fr-CH, fr;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5 From 1c8e074fcd10d44a9ce44fac867801fbf39c5665 Mon Sep 17 00:00:00 2001 From: Martijn Weverling <mweverli@student.codam.nl> Date: Fri, 12 Jan 2024 12:08:53 +0100 Subject: [PATCH 23/34] implemented and fixed error_dir --- config/default.conf | 2 +- data/errors/404.html | 3 ++- include/FileManager.hpp | 1 + src/Client.cpp | 3 ++- src/FileManager.cpp | 5 +++++ 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/config/default.conf b/config/default.conf index 8b2cffc..d8fda5b 100644 --- a/config/default.conf +++ b/config/default.conf @@ -12,7 +12,7 @@ server { listen localhost:8080; # [M - O] choose a Host:Port combination ; IPv4:{1 - 16bit} ; default: INADDR_ANY:8080 - server_name localhost; # [M - O] Setup the server_names ; [A-Za-z_]* ; default: [EMPTY] + server_name localhost; # [M - O] retup the server_names ; [A-Za-z_]* ; default: [EMPTY] error_dir /data/errors/; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] client_max_body_size 3M; # [1 - O] Limit client body size ; [\d]{1,3}[KkMm]? ; Default: 1 mB diff --git a/data/errors/404.html b/data/errors/404.html index 5559d33..9a2acb3 100644 --- a/data/errors/404.html +++ b/data/errors/404.html @@ -5,8 +5,9 @@ </head> <body> <h1>404 Not Found</h1> + <hr> <p>The requested page could not be found. <br> - <br>File: /data/error/404.html</p> + <br>This was loaded using our error_dir</p> </body> </html> diff --git a/include/FileManager.hpp b/include/FileManager.hpp index 59e67fd..2e8370b 100644 --- a/include/FileManager.hpp +++ b/include/FileManager.hpp @@ -39,6 +39,7 @@ class FileManager ClientState manageDelete(const std::string &reqest_target_path); const std::string &getResponse(void) const; + void setResponse(const std::string str); }; #endif diff --git a/src/Client.cpp b/src/Client.cpp index f326861..2dc6cd3 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -58,13 +58,14 @@ ClientState Client::handleConnection(short events) { logger.log(ERROR, "Client exception: " + std::string(e.what())); _response.clear(); - _response.append(e.what()); + _file_manager.setResponse(e.what()); _state = _file_manager.openErrorPage( _serversetting.getErrorDir().substr(1), e.getStatusCode()); // TODO: Fix Error page: // Error status is put in Client::_response // Errorpage fsteam is put into FileManager::_response // in HTTPResponse::send this clashes in the first if statement + // FIXED return (_state); } return (ClientState::Unkown); diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 48db1ca..6959841 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -199,3 +199,8 @@ const std::string &FileManager::getResponse(void) const { return (_response); } + +void FileManager::setResponse(const std::string str) +{ + _response = str; +} From 01a3629bdc6949b6eb0907a5ad666611b83bb17b Mon Sep 17 00:00:00 2001 From: Martijn Weverling <mweverli@student.codam.nl> Date: Mon, 19 Feb 2024 14:05:13 +0100 Subject: [PATCH 24/34] added files for autoindexgenerator testing --- config/default.conf | 2 +- data/www/autoindexresult.html | 29 +++++++++++++++++++++++++++++ data/www/test.file | 0 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 data/www/autoindexresult.html create mode 100644 data/www/test.file diff --git a/config/default.conf b/config/default.conf index d8fda5b..604449a 100644 --- a/config/default.conf +++ b/config/default.conf @@ -18,7 +18,7 @@ server { location / { # [1 - O] Request Target is the Target of the HTTP request; starts with a / alias /data/www/; # [1 - O] links the stated Direcotry as the RequestTarget Location ; [/]{1}[A-Za-z_/:w]* ; Default: /data/www -# index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html + #index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html allowed_methods GET; # [M - O] Define a list of accepted HTTP methods for the route; GET/POST/DELETE ; Default: GET autoindex on; # [B - O] Turn on or off directory listing; on; Default: off } diff --git a/data/www/autoindexresult.html b/data/www/autoindexresult.html new file mode 100644 index 0000000..affc527 --- /dev/null +++ b/data/www/autoindexresult.html @@ -0,0 +1,29 @@ +<!DOCTYPE html> + <html> + <head> + <title> Index of / + + +

Index of /

+
File Name
" + std::string(direnty->d_name) + "" + ((statreturn != -1) ? getStatDateLastModified(filestat) : "UNKOWN") + "" + ((statreturn != -1) ? getStatSize(filestat) : "UNKNOWN") + "
" + std::string(direnty->d_name) + "" + ((statreturn != -1) ? getStatDateLastModified(filestat) : "UNKOWN") + "" + ((statreturn != -1) ? getStatSize(filestat) : "UNKNOWN") + "
+ + + + + + + + + + + + + + + + + + + +
File Name File Size Last Modification
index.html389903 01 24
test.file010 01 24
test.txt010 01 24
+ diff --git a/data/www/test.file b/data/www/test.file new file mode 100644 index 0000000..e69de29 From 1e88041ddb8573b6315c20f3e421b430d30f6b56 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Mon, 19 Feb 2024 14:09:35 +0100 Subject: [PATCH 25/34] ReturnException: If Location contains a Return, Filemanager will throw ReturnException. WIP: still need to edit Client Class and generate correct response --- config/default.conf | 7 +++---- include/FileManager.hpp | 1 + include/LocationSettings.hpp | 4 ++-- include/ReturnException.hpp | 24 ++++++++++++++++++++++++ include/StatusCode.hpp | 1 + src/Client.cpp | 12 ++++++++++++ src/ConfigParser.cpp | 11 +---------- src/FileManager.cpp | 22 ++++++++++++++++++---- src/HTTPStatus.cpp | 1 + src/LocationSettings.cpp | 18 +++++++++--------- 10 files changed, 72 insertions(+), 29 deletions(-) create mode 100644 include/ReturnException.hpp diff --git a/config/default.conf b/config/default.conf index 604449a..9c2827f 100644 --- a/config/default.conf +++ b/config/default.conf @@ -52,13 +52,12 @@ server { } location /removed_folder/ { - return localhost; # [1 - O] Reroute a directory to another URL; URL ; Default: [] + alias /data/www/; + allowed_methods GET; + return localhost:8080/images/coffee-resized.jpeg; # [1 - O] Reroute a directory to another URL; URL ; Default: [] } } -# -#www.google.com /python/test.py /bin/usr/foo ? -# #TODO: all Settings still need implementation into the Webserver # [ ] SetDefaultValues for configfile. # [ ] ServerBlock: diff --git a/include/FileManager.hpp b/include/FileManager.hpp index 2e8370b..3648e68 100644 --- a/include/FileManager.hpp +++ b/include/FileManager.hpp @@ -39,6 +39,7 @@ class FileManager ClientState manageDelete(const std::string &reqest_target_path); const std::string &getResponse(void) const; + void addToResponse(const std::string str); void setResponse(const std::string str); }; diff --git a/include/LocationSettings.hpp b/include/LocationSettings.hpp index 27b4f66..7d742fc 100644 --- a/include/LocationSettings.hpp +++ b/include/LocationSettings.hpp @@ -33,7 +33,7 @@ class LocationSettings const std::string &getAlias() const; const std::string &getIndex() const; const std::string &getAllowedMethods() const; - const std::string &getReturn() const; + const std::string &getRedirect() const; bool getAutoIndex() const; // resolves: @@ -51,7 +51,7 @@ class LocationSettings std::string _index; std::string _allowed_methods; std::string _cgi_path; - std::string _return; + std::string _redirect; bool _auto_index; void parseAlias(const Token token); diff --git a/include/ReturnException.hpp b/include/ReturnException.hpp new file mode 100644 index 0000000..85dd81a --- /dev/null +++ b/include/ReturnException.hpp @@ -0,0 +1,24 @@ +#ifndef RETURN_EXCEPTION_HPP +#define RETURN_EXCEPTION_HPP + +#include "LocationSettings.hpp" +#include +#include + +class ReturnException : public HTTPStatus, public std::runtime_error +{ + private: + const std::string _redireciton; + + public: + ReturnException(StatusCode status, const LocationSettings &locationBlock) + : HTTPStatus(status), std::runtime_error(getStatusLine("HTTP/1.1")), + _redireciton(locationBlock.getRedirect()){}; + + const std::string &getRedirection(void) + { + return (_redireciton); + } +}; + +#endif diff --git a/include/StatusCode.hpp b/include/StatusCode.hpp index f0fa59a..72614db 100644 --- a/include/StatusCode.hpp +++ b/include/StatusCode.hpp @@ -7,6 +7,7 @@ enum class StatusCode Created = 201, Accepted = 202, NoContent = 204, + MovedPermanently = 301, Found = 302, NotModified = 304, BadRequest = 400, diff --git a/src/Client.cpp b/src/Client.cpp index 2dc6cd3..c9761b6 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -1,3 +1,5 @@ +#include "ClientState.hpp" +#include "ReturnException.hpp" #include #include #include @@ -68,5 +70,15 @@ ClientState Client::handleConnection(short events) // FIXED return (_state); } + catch (ReturnException &e) + { + logger.log(ERROR, "Return exception: " + std::string(e.what())); + _response.clear(); + _file_manager.setResponse(e.what()); + _file_manager.addToResponse("Location:" + e.getRedirection() + + "\r\n\r\n"); + _state = ClientState::Sending; + return (_state); + } return (ClientState::Unkown); } diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 5598117..06702e5 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -49,20 +49,11 @@ void ConfigParser::ParseConfig() tokenizeStream(OpenFile(), tokenlist); syntax(tokenlist); - logger.log(INFO, "Syntax of " + _config_file_path + " finished"); + logger.log(INFO, "Passed Syntax " + _config_file_path); for (std::vector::iterator it = tokenlist.begin(); it != tokenlist.end(); it++) _server_settings.emplace_back(ServerSettings(it)); - // { - // const LocationSettings &loc = it.resolveLocation("/t/"); - // - // logger.log(DEBUG, "LocationSettings.getRequestTarget: " + - // loc.getRequestTarget() + - // "\tcheck: " + loc.getIndex()); - // } - // - // logger.log(INFO, "Parsed configfile: " + _config_file_path); } diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 6959841..d964adf 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -2,6 +2,7 @@ #include "AutoIndexGenerator.hpp" #include "ClientException.hpp" #include "Logger.hpp" +#include "ReturnException.hpp" #include "StatusCode.hpp" #include @@ -27,6 +28,8 @@ FileManager::applyLocationSettings(const std::string &request_target, if (loc.resolveMethod(method) == false) throw ClientException(StatusCode::MethodNotAllowed); + if (!loc.getRedirect().empty()) + throw ReturnException(StatusCode::MovedPermanently, loc); if (request_target.find_last_of('/') == request_target.length() - 1) { @@ -35,11 +38,14 @@ FileManager::applyLocationSettings(const std::string &request_target, loc.getIndex()); else if (loc.getAutoIndex() == false) return (loc.resolveAlias(request_target).substr(1) + - "index.html"); // default value; + "index.html"); /* default value, potential + TODO: set Default values in default + assigner; */ _request_target = AutoIndexGenerator::OpenAutoIndex( loc.resolveAlias(request_target).substr(1), request_target); _autoindex = true; } + return (loc.resolveAlias(request_target).substr(1)); } @@ -65,9 +71,12 @@ void FileManager::openGetFile(const std::string &request_target_path) void FileManager::openPostFile(const std::string &request_target_path) { - if (!std::filesystem::exists(request_target_path)) + const std::string resolved_target = + applyLocationSettings(request_target_path, HTTPMethod::GET); + + if (!std::filesystem::exists(resolved_target)) { - _request_target.open(request_target_path, std::ios::out); + _request_target.open(resolved_target, std::ios::out); if (!_request_target.is_open()) throw ClientException(StatusCode::InternalServerError); HTTPStatus status(StatusCode::Created); @@ -106,7 +115,7 @@ ClientState FileManager::openErrorPage(const std::string &error_pages_path, } // still need some elaboration for this part. it seems odd to append the buffer -// to the respons even after it goes into the if(_request_target.bad()). and if +// to the response even after it goes into the if(_request_target.bad()). and if // you don't go in it you've missed your statusline for the response. ClientState FileManager::loadErrorPage(void) { @@ -200,6 +209,11 @@ const std::string &FileManager::getResponse(void) const return (_response); } +void FileManager::addToResponse(const std::string str) +{ + _response += str; +} + void FileManager::setResponse(const std::string str) { _response = str; diff --git a/src/HTTPStatus.cpp b/src/HTTPStatus.cpp index 2c6e93c..b4d882f 100644 --- a/src/HTTPStatus.cpp +++ b/src/HTTPStatus.cpp @@ -6,6 +6,7 @@ std::unordered_map HTTPStatus::_message = { {StatusCode::Created, "Created"}, {StatusCode::Accepted, "Accepted"}, {StatusCode::NoContent, "No Content"}, + {StatusCode::MovedPermanently, "Moved Permanently"}, {StatusCode::Found, "Found"}, {StatusCode::NotModified, "Not Modified"}, {StatusCode::BadRequest, "Bad Request"}, diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index a150f77..c346180 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -8,7 +8,7 @@ #include LocationSettings::LocationSettings() - : _path(), _alias(), _index(), _allowed_methods(), _cgi_path(), + : _path(), _alias(), _index(), _allowed_methods(), _cgi_path(), _redirect(), _auto_index(false) { } @@ -16,7 +16,7 @@ LocationSettings::LocationSettings() LocationSettings::LocationSettings(const LocationSettings &rhs) : _path(rhs._path), _alias(rhs._alias), _index(rhs._index), _allowed_methods(rhs._allowed_methods), _cgi_path(rhs._cgi_path), - _auto_index(rhs._auto_index) + _redirect(rhs._redirect), _auto_index(rhs._auto_index) { } @@ -31,7 +31,7 @@ LocationSettings &LocationSettings::operator=(LocationSettings &rhs) _index = rhs._index; _allowed_methods = rhs._allowed_methods; _cgi_path = rhs._cgi_path; - _return = rhs._return; + _redirect = rhs._redirect; _auto_index = rhs._auto_index; return (*this); @@ -135,11 +135,11 @@ void LocationSettings::parseReturn(const Token token) { Logger &logger = Logger::getInstance(); - if (!_return.empty()) + if (!_redirect.empty()) logger.log(WARNING, "ConfigParser: redefining return in locationblock: " + _path); - _return = token.getString(); + _redirect = token.getString(); } // Functionality: @@ -169,9 +169,9 @@ bool LocationSettings::getAutoIndex() const return (_auto_index); } -const std::string &LocationSettings::getReturn() const +const std::string &LocationSettings::getRedirect() const { - return (_return); + return (_redirect); } const std::string MethodToString(HTTPMethod num) @@ -201,7 +201,7 @@ bool LocationSettings::resolveMethod(const HTTPMethod method) const if (getAllowedMethods().empty()) logger.log(WARNING, "ResolveMethod: No HTTPMethod specified in Locationblock: " + - getPath()); + getPath()); // TODO: Should throw exception? std::stringstream ss(getAllowedMethods()); std::string option; for (; std::getline(ss, option, ' ');) @@ -251,7 +251,7 @@ void LocationSettings::printLocationSettings() const logger.log(DEBUG, "\t\tIndex:\t\t\t" + _index); logger.log(DEBUG, "\t\tAllowed_methods:\t" + _allowed_methods); logger.log(DEBUG, "\t\tCGI Path:\t\t" + _cgi_path); - logger.log(DEBUG, "\t\tReturn:\t\t" + _return); + logger.log(DEBUG, "\t\tRedirect:\t\t" + _redirect); logger.log(DEBUG, "\t\tAutoIndex:\t\t" + (_auto_index ? std::string(" ON") : std::string(" OFF"))); From 308881167e7246d0fd3e59b55c64e2f35fda9020 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Wed, 28 Feb 2024 15:12:20 +0100 Subject: [PATCH 26/34] redirection is working --- config/default.conf | 4 ++-- include/HTTPStatus.hpp | 1 + include/ReturnException.hpp | 2 +- src/Client.cpp | 2 +- src/HTTPStatus.cpp | 7 +++++++ 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/config/default.conf b/config/default.conf index 9c2827f..cf05c4c 100644 --- a/config/default.conf +++ b/config/default.conf @@ -54,7 +54,7 @@ server { location /removed_folder/ { alias /data/www/; allowed_methods GET; - return localhost:8080/images/coffee-resized.jpeg; # [1 - O] Reroute a directory to another URL; URL ; Default: [] + return /images/coffee-resized.jpeg ; # [1 - O] Reroute a directory to another URL; URL ; Default: [] } } @@ -72,6 +72,6 @@ server { # [x] autoindex; // Automaticly should create a Index file that shows an overview of the direcotry; # [x] allowed_methods; // should check if the HTTP Method is allowed in this location; # [ ] cgi; // is a boolean that shows if the directory is a CGI and the value is the path to the executable; -# [ ] return; // +# [x] return; // # [x] HTTPerrorpagegenerator // method that can generate a simple ERROR page to the _response. # diff --git a/include/HTTPStatus.hpp b/include/HTTPStatus.hpp index 135d784..6897c4d 100644 --- a/include/HTTPStatus.hpp +++ b/include/HTTPStatus.hpp @@ -20,6 +20,7 @@ class HTTPStatus ~HTTPStatus(); std::string getStatusLine(const std::string &version) const; + std::string getStatusLineCRLF(const std::string &version) const; std::string getHTMLStatus(void) const; StatusCode getStatusCode() const; }; diff --git a/include/ReturnException.hpp b/include/ReturnException.hpp index 85dd81a..45fe6d4 100644 --- a/include/ReturnException.hpp +++ b/include/ReturnException.hpp @@ -12,7 +12,7 @@ class ReturnException : public HTTPStatus, public std::runtime_error public: ReturnException(StatusCode status, const LocationSettings &locationBlock) - : HTTPStatus(status), std::runtime_error(getStatusLine("HTTP/1.1")), + : HTTPStatus(status), std::runtime_error(getStatusLineCRLF("HTTP/1.1")), _redireciton(locationBlock.getRedirect()){}; const std::string &getRedirection(void) diff --git a/src/Client.cpp b/src/Client.cpp index c9761b6..96d3998 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -75,7 +75,7 @@ ClientState Client::handleConnection(short events) logger.log(ERROR, "Return exception: " + std::string(e.what())); _response.clear(); _file_manager.setResponse(e.what()); - _file_manager.addToResponse("Location:" + e.getRedirection() + + _file_manager.addToResponse("Location: " + e.getRedirection() + "\r\n\r\n"); _state = ClientState::Sending; return (_state); diff --git a/src/HTTPStatus.cpp b/src/HTTPStatus.cpp index b4d882f..a5be2a4 100644 --- a/src/HTTPStatus.cpp +++ b/src/HTTPStatus.cpp @@ -33,6 +33,13 @@ HTTPStatus::~HTTPStatus() { } +std::string HTTPStatus::getStatusLineCRLF(const std::string &version) const +{ + return (version + " " + std::to_string(static_cast(_status_code)) + + " " + _message.at(_status_code)) + + "\r\n"; +} + std::string HTTPStatus::getStatusLine(const std::string &version) const { return (version + " " + std::to_string(static_cast(_status_code)) + From 19ccaec2662b94b9f439b2dbef82d3ccca95b739 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Thu, 28 Mar 2024 14:52:38 +0100 Subject: [PATCH 27/34] changed Statuscode 301 -> 302 --- src/FileManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FileManager.cpp b/src/FileManager.cpp index d964adf..5bb4a41 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -29,7 +29,7 @@ FileManager::applyLocationSettings(const std::string &request_target, if (loc.resolveMethod(method) == false) throw ClientException(StatusCode::MethodNotAllowed); if (!loc.getRedirect().empty()) - throw ReturnException(StatusCode::MovedPermanently, loc); + throw ReturnException(StatusCode::Found, loc); if (request_target.find_last_of('/') == request_target.length() - 1) { From 45099599c0e45a74c2527984739d11517004f402 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Mon, 1 Apr 2024 17:16:00 +0200 Subject: [PATCH 28/34] requested changes for pull request #42 --- include/Socket.hpp | 4 ---- src/Client.cpp | 5 ----- src/FileManager.cpp | 7 +------ src/HTTPRequest.cpp | 6 ++---- src/HTTPResponse.cpp | 4 ---- src/HTTPServer.cpp | 2 +- src/Poll.cpp | 6 +----- src/Socket.cpp | 2 +- 8 files changed, 6 insertions(+), 30 deletions(-) diff --git a/include/Socket.hpp b/include/Socket.hpp index 3152523..14ca090 100644 --- a/include/Socket.hpp +++ b/include/Socket.hpp @@ -4,10 +4,6 @@ #include #include -#include -#include -#include - #define MAX_PENDING_CONNECTIONS 10 typedef struct sockaddr_in t_sockaddr_in; diff --git a/src/Client.cpp b/src/Client.cpp index 96d3998..2d2f046 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -63,11 +63,6 @@ ClientState Client::handleConnection(short events) _file_manager.setResponse(e.what()); _state = _file_manager.openErrorPage( _serversetting.getErrorDir().substr(1), e.getStatusCode()); - // TODO: Fix Error page: - // Error status is put in Client::_response - // Errorpage fsteam is put into FileManager::_response - // in HTTPResponse::send this clashes in the first if statement - // FIXED return (_state); } catch (ReturnException &e) diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 5bb4a41..ec57f1f 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -114,9 +114,6 @@ ClientState FileManager::openErrorPage(const std::string &error_pages_path, return (ClientState::Error); } -// still need some elaboration for this part. it seems odd to append the buffer -// to the response even after it goes into the if(_request_target.bad()). and if -// you don't go in it you've missed your statusline for the response. ClientState FileManager::loadErrorPage(void) { char buffer[BUFFER_SIZE]; @@ -132,9 +129,7 @@ ClientState FileManager::loadErrorPage(void) { return (ClientState::Sending); } - return (ClientState::Error); // @saladuit changed this to Error since the - // file needs to keep reading this fstream and - // loadErrorPage + return (ClientState::Error); } ClientState FileManager::manageGet(void) diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index 9984367..543e3d0 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -148,15 +148,13 @@ ClientState HTTPRequest::receive(int client_fd) if (_content_length != 0) { _body += std::string(buffer, _bytes_read); + if (_body.size() >= _max_body_size) + throw ClientException(StatusCode::RequestBodyTooLarge); if (_body.size() >= _content_length) { logger.log(DEBUG, "Body: " + _body); return (ClientState::Loading); } - if (_body.size() >= - _max_body_size) // @saladuit not sure if this should be before the - // previous ifstatement - throw ClientException(StatusCode::RequestBodyTooLarge); return (ClientState::Receiving); } _http_request += std::string(buffer, _bytes_read); diff --git a/src/HTTPResponse.cpp b/src/HTTPResponse.cpp index ae6da4e..3e8c801 100644 --- a/src/HTTPResponse.cpp +++ b/src/HTTPResponse.cpp @@ -31,16 +31,12 @@ ClientState HTTPResponse::send(int client_fd, const std::string &response) ssize_t bytes_to_send; ssize_t w_size; - // logger.log(DEBUG, "_response: " + _response); - // logger.log(DEBUG, "response: " + response); if (_response.empty()) { _response = response; } logger.log(INFO, "Sending response to client on fd: " + std::to_string(client_fd)); - // logger.log(DEBUG, "response: " + _response); // this logger line gives a - // segfault when transporting /data/images/conffee-resized.jpeg if (_response.length() - _bytes_sent < BUFFER_SIZE) bytes_to_send = _response.length() - _bytes_sent; else diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index 12538a0..5e91057 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -34,7 +34,7 @@ int HTTPServer::run() logger.log(FATAL, e.what()); return (EXIT_FAILURE); } - // return (EXIT_SUCCESS); + return (EXIT_SUCCESS); } void HTTPServer::setupServers(void) diff --git a/src/Poll.cpp b/src/Poll.cpp index 22978d0..67c4fae 100644 --- a/src/Poll.cpp +++ b/src/Poll.cpp @@ -42,11 +42,7 @@ void Poll::pollFDs(void) Logger &logger = Logger::getInstance(); logger.log(INFO, "Polling " + std::to_string(_poll_fds.size()) + " file descriptors"); - int poll_count = - poll(_poll_fds.data(), _poll_fds.size(), - NO_TIMEOUT); // TODO: NO_TIMEOUT is an issue. We need to make sure - // Poll will time out certain Clients (e.g. Clients - // won't send anymore bytes after first 10 bytes) + int poll_count = poll(_poll_fds.data(), _poll_fds.size(), NO_TIMEOUT); if (poll_count == SYSTEM_ERROR || poll_count == 0) throw SystemException("poll"); // TODO: change poll_count 0 handler } diff --git a/src/Socket.cpp b/src/Socket.cpp index dad1ed4..3048522 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -63,7 +63,7 @@ void Socket::initSockaddrIn(t_sockaddr_in &addr, const std::string &_listen) bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_addr.s_addr = htonl(INADDR_ANY); // TODO: implement getaddrinfo addr.sin_port = htons(std::stoi(port)); std::fill_n(addr.sin_zero, sizeof(addr.sin_zero), '\0'); } From e491e83505f640fcef4b85c229a2cdc091d20e4f Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Thu, 18 Apr 2024 21:45:05 +0200 Subject: [PATCH 29/34] start of Listen implementation --- include/ConfigParser.hpp | 1 + include/Server.hpp | 1 + include/ServerSettings.hpp | 7 ++----- src/ConfigParser.cpp | 13 +++++++++++++ src/FileManager.cpp | 1 + src/HTTPServer.cpp | 6 +++--- src/LocationSettings.cpp | 2 +- src/Server.cpp | 2 +- src/Socket.cpp | 8 ++++---- 9 files changed, 27 insertions(+), 14 deletions(-) diff --git a/include/ConfigParser.hpp b/include/ConfigParser.hpp index d242cde..8119622 100644 --- a/include/ConfigParser.hpp +++ b/include/ConfigParser.hpp @@ -29,6 +29,7 @@ class ConfigParser void ParseConfig(); const std::vector &getServerSettings(); + const std::vector> sortServerSettings(); }; void tokenizeStream(std::stringstream sstream, diff --git a/include/Server.hpp b/include/Server.hpp index 1ae0f32..92fa401 100644 --- a/include/Server.hpp +++ b/include/Server.hpp @@ -13,6 +13,7 @@ class Server Server(const Server &rhs) = delete; Server &operator=(const Server &rhs) = delete; ~Server(); + int getFD(void) const; const ServerSettings &getServerSettings(void) const; diff --git a/include/ServerSettings.hpp b/include/ServerSettings.hpp index 1a14900..ba6829b 100644 --- a/include/ServerSettings.hpp +++ b/include/ServerSettings.hpp @@ -16,8 +16,8 @@ class ServerSettings ServerSettings &operator=(const ServerSettings &rhs) = delete; // Functionality: - const LocationSettings &resolveLocation(const std::string &request_target) const; -// bool resolveServerName(const std::string &RequestHost); + const LocationSettings & + resolveLocation(const std::string &request_target) const; const std::string &getListen() const; const std::string &getServerName() const; @@ -43,9 +43,6 @@ class ServerSettings void parseServerName(const Token value); void parseErrorDir(const Token value); void parseClientMaxBodySize(const Token value); - - // TODO: methods fucntion that can resolve if a read/write/delete can be - // done on a certain location in the LocationSettings }; #endif diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 06702e5..12a604f 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -19,6 +19,19 @@ ConfigParser::~ConfigParser() { } +const std::vector> +ConfigParser::sortServerSettings() +{ + std::vector> vec; + Logger &logger = Logger::getInstance(); + logger.log(INFO, "sortServerSettings"); + + for (const ServerSettings &block : _server_settings) + { + } + return (vec); +} + const std::vector &ConfigParser::getServerSettings() { return (_server_settings); diff --git a/src/FileManager.cpp b/src/FileManager.cpp index ec57f1f..adf9d53 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -22,6 +22,7 @@ std::string FileManager::applyLocationSettings(const std::string &request_target, HTTPMethod method) { + // substr is required to remove starting '/' const LocationSettings &loc = _serversetting.resolveLocation(request_target); diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index 5e91057..f1923f9 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -42,10 +42,10 @@ void HTTPServer::setupServers(void) Logger &logger = Logger::getInstance(); logger.log(INFO, "Setting up server sockets"); - const std::vector &server_settings = - _parser.getServerSettings(); + const std::vector> list = + _parser.sortServerSettings(); - for (const auto &server_setting : server_settings) + for (const auto &server_setting : list) { std::shared_ptr server = std::make_shared(server_setting); diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index c346180..45a9a47 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -188,7 +188,7 @@ const std::string MethodToString(HTTPMethod num) { Logger &logger = Logger::getInstance(); logger.log(WARNING, "LocationSettings MethodToString: unknown Method"); - return ("UNKOWNSTRING"); + return ("UNKOWNMETHOD"); } } } diff --git a/src/Server.cpp b/src/Server.cpp index 80b4351..627de4e 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -9,7 +9,7 @@ Server::Server(const ServerSettings &server_settings) _socket.setupServer( _server_settings.getListen()); // TODO: make sure setupServer is capable - // of having getListen as an input. + // of having getListen as an input. logger.log(DEBUG, "Created Server on host:port " + _server_settings.getListen() + " on fd: " + std::to_string(_socket.getFD())); diff --git a/src/Socket.cpp b/src/Socket.cpp index 3048522..d0e21f4 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -49,17 +49,17 @@ Socket::~Socket() void Socket::initSockaddrIn(t_sockaddr_in &addr, const std::string &_listen) { - // Logger &logger = Logger::getInstance(); + Logger &logger = Logger::getInstance(); size_t pos = _listen.find(":"); std::string host = _listen.substr(0, pos); std::string port; if (pos == std::string::npos) - port = "80"; + port = "80"; // DEFUALT 80 else port = _listen.substr(pos + 1); - // logger.log(DEBUG, - // "listen: " + _listen + "\nhost: " + host + "\nport: " + port); + logger.log(DEBUG, + "listen: " + _listen + "\nhost: " + host + "\nport: " + port); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; From 637755d955680be293caa5be7845cfe55a592ae4 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Thu, 25 Apr 2024 19:59:08 +0200 Subject: [PATCH 30/34] converting HOST in config file & sorting ServerSetting blocks --- config/default.conf | 21 ++++++++++++--- config/simple.conf | 56 ++++++++++++++++++++++++++++++++++++++-- include/ConfigParser.hpp | 2 +- src/ConfigParser.cpp | 32 +++++++++++++++++++---- src/HTTPServer.cpp | 6 ++--- src/ServerSettings.cpp | 38 ++++++++++++++++++++++----- 6 files changed, 135 insertions(+), 20 deletions(-) diff --git a/config/default.conf b/config/default.conf index cf05c4c..b532ee7 100644 --- a/config/default.conf +++ b/config/default.conf @@ -11,21 +11,36 @@ # Server Configuration server { - listen localhost:8080; # [M - O] choose a Host:Port combination ; IPv4:{1 - 16bit} ; default: INADDR_ANY:8080 + listen 127.4.4.4:8081; server_name localhost; # [M - O] retup the server_names ; [A-Za-z_]* ; default: [EMPTY] error_dir /data/errors/; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] client_max_body_size 3M; # [1 - O] Limit client body size ; [\d]{1,3}[KkMm]? ; Default: 1 mB location / { # [1 - O] Request Target is the Target of the HTTP request; starts with a / alias /data/www/; # [1 - O] links the stated Direcotry as the RequestTarget Location ; [/]{1}[A-Za-z_/:w]* ; Default: /data/www - #index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html + index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html + allowed_methods GET; # [M - O] Define a list of accepted HTTP methods for the route; GET/POST/DELETE ; Default: GET + autoindex on; # [B - O] Turn on or off directory listing; on; Default: off + } + +} + +server { + listen 127.0.0.1:8080; # [M - O] choose a Host:Port combination ; IPv4:{1 - 16bit} ; default: INADDR_ANY:8080 + server_name localhost; # [M - O] retup the server_names ; [A-Za-z_]* ; default: [EMPTY] + error_dir /data/errors/; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] + client_max_body_size 3M; # [1 - O] Limit client body size ; [\d]{1,3}[KkMm]? ; Default: 1 mB + + location / { # [1 - O] Request Target is the Target of the HTTP request; starts with a / + alias /data/www/; # [1 - O] links the stated Direcotry as the RequestTarget Location ; [/]{1}[A-Za-z_/:w]* ; Default: /data/www + index index.html; # [1 - O] Set a default file to answer if the request is a directory ; [A-Za-z_/.]* ; Default: index.html allowed_methods GET; # [M - O] Define a list of accepted HTTP methods for the route; GET/POST/DELETE ; Default: GET autoindex on; # [B - O] Turn on or off directory listing; on; Default: off } location /python/ { alias /cgi/python/; # already defined; - cgi /bin/python3; # [1 - O] Set a Path to where the CGI can find the Binary; [A-Za-z_/.]* ; Default: [EMPTY] + cgi on; # [1 - O] Set a Path to where the CGI can find the Binary; [A-Za-z_/.]* ; Default: [EMPTY] } location /images/ { diff --git a/config/simple.conf b/config/simple.conf index d282b77..9f16efa 100644 --- a/config/simple.conf +++ b/config/simple.conf @@ -2,8 +2,7 @@ # Server Configuration server { - port 9696; - host localhost; # Choose the port and host; default for this host:port + listen 127.0.0.1:8080; server_name lucy_saus; # Setup the server_names or not client_max_body_size 3M; # Limit client body size error_pages 404; @@ -14,3 +13,56 @@ server { allow_methods GET POST; # Define a list of accepted HTTP methods for the route } } + +server { + listen 127.0.1.1:8080; + server_name lucy_saus; # Setup the server_names or not + client_max_body_size 3M; # Limit client body size + error_pages 404; + + location / { + root /data/www; # Define a directory where the file should be searched + index index.html; # Set a default file to answer if the request is a directory + allow_methods GET POST; # Define a list of accepted HTTP methods for the route + } +} + +server { + listen localhost:8080; + server_name sala-SAUS; # Setup the server_names or not + client_max_body_size 3M; # Limit client body size + error_pages 404; + + location / { + root /data/www; # Define a directory where the file should be searched + index index.html; # Set a default file to answer if the request is a directory + allow_methods GET POST; # Define a list of accepted HTTP methods for the route + } +} + +server { + listen localhost:8080; + server_name maarty-saus; # Setup the server_names or not + client_max_body_size 3M; # Limit client body size + error_pages 404; + + location / { + root /data/www; # Define a directory where the file should be searched + index index.html; # Set a default file to answer if the request is a directory + allow_methods GET POST; # Define a list of accepted HTTP methods for the route + } +} + +server { + listen dump-linux:8080; + server_name LINUX_SAUS; # Setup the server_names or not + client_max_body_size 3M; # Limit client body size + error_pages 404; + + location / { + root /data/www; # Define a directory where the file should be searched + index index.html; # Set a default file to answer if the request is a directory + allow_methods GET POST; # Define a list of accepted HTTP methods for the route + } +} + diff --git a/include/ConfigParser.hpp b/include/ConfigParser.hpp index 8119622..d61e56b 100644 --- a/include/ConfigParser.hpp +++ b/include/ConfigParser.hpp @@ -29,7 +29,7 @@ class ConfigParser void ParseConfig(); const std::vector &getServerSettings(); - const std::vector> sortServerSettings(); + void sortServerSettings(); }; void tokenizeStream(std::stringstream sstream, diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 12a604f..7ec0d97 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -6,6 +6,9 @@ #include #include +#include +#include +#include #include #include #include @@ -19,17 +22,36 @@ ConfigParser::~ConfigParser() { } -const std::vector> -ConfigParser::sortServerSettings() +void ConfigParser::sortServerSettings() { - std::vector> vec; Logger &logger = Logger::getInstance(); logger.log(INFO, "sortServerSettings"); - for (const ServerSettings &block : _server_settings) + std::map> map_servers; + + for (ServerSettings block : _server_settings) + { + std::map>::iterator it = + map_servers.find(block.getListen()); + if (it == map_servers.end()) + { + std::vector vec; + vec.push_back(block); + map_servers.emplace(block.getListen(), vec); + } + else + it->second.emplace_back(block); + } + + /* + for (auto vec : map_servers) { + logger.log(DEBUG, "HOST:PORT\t" + vec.second.at(0).getListen()); + for (auto block : vec.second) + block.printServerSettings(); } - return (vec); + exit(10); + */ } const std::vector &ConfigParser::getServerSettings() diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index f1923f9..5c4414e 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -42,9 +42,8 @@ void HTTPServer::setupServers(void) Logger &logger = Logger::getInstance(); logger.log(INFO, "Setting up server sockets"); - const std::vector> list = - _parser.sortServerSettings(); - + _parser.sortServerSettings(); + /* for (const auto &server_setting : list) { std::shared_ptr server = @@ -52,6 +51,7 @@ void HTTPServer::setupServers(void) _active_servers.emplace(server->getFD(), server); _poll.addPollFD(server->getFD(), POLLIN); } + */ } void HTTPServer::handleActivePollFDs() diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index 4c2ecdd..5192f92 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -6,6 +6,8 @@ #include #include +#include +#include #include #include #include @@ -51,7 +53,31 @@ ServerSettings::ServerSettings(std::vector::iterator &token) } } -void validateListen(const std::string &str) +const std::string convertHost(const std::string &str) +{ + Logger &logger = Logger::getInstance(); + + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // AF_INET or AF_INET6 to force version + hints.ai_socktype = SOCK_STREAM; + + struct addrinfo *res = NULL; + int ret; + + if ((ret = getaddrinfo(str.c_str(), "http", &hints, &res)) != 0) + { + logger.log(WARNING, + "Unable to get IPv4: " + std::string(gai_strerror(ret))); + // TODO: trhow? + } + void *addr = &((struct sockaddr_in *)res->ai_addr)->sin_addr; + char ipstr[INET_ADDRSTRLEN]; + inet_ntop(res->ai_family, addr, ipstr, sizeof(ipstr)); + return (std::string(ipstr)); +} + +const std::string validateListen(const std::string &str) { size_t pos = str.find_first_of(":"); if (pos == std::string::npos || pos != str.find_last_of(":")) @@ -63,23 +89,23 @@ void validateListen(const std::string &str) try { int port_ = std::stoi(port); - if (port_ < 1 || port_ > 65535) // + if (port_ < 1 || port_ > 65535) throw std::exception(); } catch (std::exception &e) { - throw std::runtime_error("Parsing Error: invalid port found in listen"); + throw std::runtime_error("Parsing Error: found invalid PORT in listen"); } + return (convertHost(ip) + ":" + port); } void ServerSettings::parseListen(const Token value) { Logger &logger = Logger::getInstance(); - validateListen(value.getString()); if (!_listen.empty()) logger.log(WARNING, "ConfigParser: redefining listen"); - _listen = value.getString(); + _listen = validateListen(value.getString()); } void ServerSettings::parseServerName(const Token value) @@ -242,9 +268,9 @@ void ServerSettings::printServerSettings() const for (auto &location_instance : _location_settings) { - logger.log(DEBUG, "\n"); location_instance.printLocationSettings(); } + logger.log(DEBUG, "\n"); // We can go over the different strings by using Getline // From d7c4fc39f67ba20d3cd755922956e2d48f6faa90 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Thu, 25 Apr 2024 20:24:12 +0200 Subject: [PATCH 31/34] changed return of sortServersettings to vector, also changed Server constructor --- config/simple.conf | 10 +++++----- include/ConfigParser.hpp | 2 +- include/Server.hpp | 4 ++-- src/ConfigParser.cpp | 29 +++++++++++------------------ src/HTTPServer.cpp | 11 +++++------ src/Server.cpp | 9 ++++----- 6 files changed, 28 insertions(+), 37 deletions(-) diff --git a/config/simple.conf b/config/simple.conf index 9f16efa..6641fc6 100644 --- a/config/simple.conf +++ b/config/simple.conf @@ -3,7 +3,7 @@ # Server Configuration server { listen 127.0.0.1:8080; - server_name lucy_saus; # Setup the server_names or not + server_name eerste_saus; # Setup the server_names or not client_max_body_size 3M; # Limit client body size error_pages 404; @@ -16,7 +16,7 @@ server { server { listen 127.0.1.1:8080; - server_name lucy_saus; # Setup the server_names or not + server_name tweede_saus; # Setup the server_names or not client_max_body_size 3M; # Limit client body size error_pages 404; @@ -29,7 +29,7 @@ server { server { listen localhost:8080; - server_name sala-SAUS; # Setup the server_names or not + server_name sala_SAUS; # Setup the server_names or not client_max_body_size 3M; # Limit client body size error_pages 404; @@ -42,7 +42,7 @@ server { server { listen localhost:8080; - server_name maarty-saus; # Setup the server_names or not + server_name Lucy_saus; # Setup the server_names or not client_max_body_size 3M; # Limit client body size error_pages 404; @@ -55,7 +55,7 @@ server { server { listen dump-linux:8080; - server_name LINUX_SAUS; # Setup the server_names or not + server_name maarty-saus; # Setup the server_names or not client_max_body_size 3M; # Limit client body size error_pages 404; diff --git a/include/ConfigParser.hpp b/include/ConfigParser.hpp index d61e56b..683e78e 100644 --- a/include/ConfigParser.hpp +++ b/include/ConfigParser.hpp @@ -29,7 +29,7 @@ class ConfigParser void ParseConfig(); const std::vector &getServerSettings(); - void sortServerSettings(); + std::vector> sortServerSettings(); }; void tokenizeStream(std::stringstream sstream, diff --git a/include/Server.hpp b/include/Server.hpp index 92fa401..deb8301 100644 --- a/include/Server.hpp +++ b/include/Server.hpp @@ -8,7 +8,7 @@ class Server { public: - Server(const ServerSettings &settings); + Server(const std::vector &server_settings); Server() = delete; Server(const Server &rhs) = delete; Server &operator=(const Server &rhs) = delete; @@ -18,7 +18,7 @@ class Server const ServerSettings &getServerSettings(void) const; private: - const ServerSettings &_server_settings; + const std::vector _server_settings; Socket _socket; }; diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 7ec0d97..66cc7bf 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -7,8 +7,8 @@ #include #include -#include #include +#include #include #include #include @@ -22,36 +22,29 @@ ConfigParser::~ConfigParser() { } -void ConfigParser::sortServerSettings() +std::vector> ConfigParser::sortServerSettings() { Logger &logger = Logger::getInstance(); logger.log(INFO, "sortServerSettings"); - std::map> map_servers; + std::set hpset; + std::vector> vec_servers; for (ServerSettings block : _server_settings) { - std::map>::iterator it = - map_servers.find(block.getListen()); - if (it == map_servers.end()) + std::set::iterator it = hpset.find(block.getListen()); + if (it == hpset.end()) { + hpset.emplace(block.getListen()); std::vector vec; vec.push_back(block); - map_servers.emplace(block.getListen(), vec); + vec_servers.emplace_back(vec); } else - it->second.emplace_back(block); + vec_servers.at(std::distance(hpset.begin(), it)) + .emplace_back(block); } - - /* - for (auto vec : map_servers) - { - logger.log(DEBUG, "HOST:PORT\t" + vec.second.at(0).getListen()); - for (auto block : vec.second) - block.printServerSettings(); - } - exit(10); - */ + return (vec_servers); } const std::vector &ConfigParser::getServerSettings() diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index 5c4414e..6ae1d1f 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -42,16 +42,15 @@ void HTTPServer::setupServers(void) Logger &logger = Logger::getInstance(); logger.log(INFO, "Setting up server sockets"); - _parser.sortServerSettings(); - /* - for (const auto &server_setting : list) + std::vector> servers = + _parser.sortServerSettings(); + + for (const std::vector &list : servers) { - std::shared_ptr server = - std::make_shared(server_setting); + std::shared_ptr server = std::make_shared(list); _active_servers.emplace(server->getFD(), server); _poll.addPollFD(server->getFD(), POLLIN); } - */ } void HTTPServer::handleActivePollFDs() diff --git a/src/Server.cpp b/src/Server.cpp index 627de4e..2bea4b0 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -1,17 +1,16 @@ #include #include #include +#include -Server::Server(const ServerSettings &server_settings) +Server::Server(const std::vector &server_settings) : _server_settings(server_settings), _socket() { Logger &logger = Logger::getInstance(); - _socket.setupServer( - _server_settings.getListen()); // TODO: make sure setupServer is capable - // of having getListen as an input. + _socket.setupServer(_server_settings.at(0).getListen()); logger.log(DEBUG, "Created Server on host:port " + - _server_settings.getListen() + + _server_settings.at(0).getListen() + " on fd: " + std::to_string(_socket.getFD())); } From 251476cf8270373129c26a16468b2f8d4cd769fc Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Fri, 26 Apr 2024 20:09:53 +0200 Subject: [PATCH 32/34] Vectored serversettings has been implemented --- include/Client.hpp | 6 ++++-- include/FileManager.hpp | 5 +++-- include/HTTPRequest.hpp | 5 +++++ include/HTTPServer.hpp | 2 +- include/LocationSettings.hpp | 2 +- include/Server.hpp | 4 ++-- include/ServerSettings.hpp | 2 +- src/Client.cpp | 33 +++++++++++++++++++++++++++++---- src/FileManager.cpp | 10 +++++++--- src/HTTPRequest.cpp | 36 ++++++++++++++++++++++++------------ src/HTTPServer.cpp | 8 ++++---- src/LocationSettings.cpp | 2 +- src/Server.cpp | 2 +- src/ServerSettings.cpp | 12 ++++++++++++ src/Socket.cpp | 10 +--------- 15 files changed, 96 insertions(+), 43 deletions(-) diff --git a/include/Client.hpp b/include/Client.hpp index 507c8bd..d019cac 100644 --- a/include/Client.hpp +++ b/include/Client.hpp @@ -11,13 +11,14 @@ class Client { public: - Client(const int &server_fd, const ServerSettings &serversettings); + Client(const int &server_fd, std::vector &serversettings); Client() = delete; Client(const Client &other) = delete; const Client &operator=(const Client &other) = delete; ~Client(); ClientState handleConnection(short events); + void resolveServerSetting(); int getFD(void) const; private: @@ -26,7 +27,8 @@ class Client FileManager _file_manager; CGI _cgi; Socket _socket; - ServerSettings _serversetting; // TODO: make multiple serverblocks work; + const std::vector &_server_list; + ServerSettings &_serversetting; ClientState _state; }; diff --git a/include/FileManager.hpp b/include/FileManager.hpp index 3648e68..6070fab 100644 --- a/include/FileManager.hpp +++ b/include/FileManager.hpp @@ -14,7 +14,7 @@ class FileManager private: std::string _response; std::fstream _request_target; - const ServerSettings &_serversetting; + ServerSettings _serversetting; bool _autoindex; std::string applyLocationSettings(const std::string &request_target, @@ -22,7 +22,6 @@ class FileManager public: FileManager(); - FileManager(const ServerSettings &ServerSettings); FileManager(const FileManager &other) = delete; void operator=(const FileManager &other) = delete; ~FileManager(); @@ -41,6 +40,8 @@ class FileManager const std::string &getResponse(void) const; void addToResponse(const std::string str); void setResponse(const std::string str); + + void setServerSetting(const ServerSettings &serversetting); }; #endif diff --git a/include/HTTPRequest.hpp b/include/HTTPRequest.hpp index 0ae06df..6a2aac5 100644 --- a/include/HTTPRequest.hpp +++ b/include/HTTPRequest.hpp @@ -52,9 +52,14 @@ class HTTPRequest const std::string &getHeader(const std::string &key) const; const std::string &getBody(void) const; + ClientState setRequestVariables(size_t pos); ClientState receive(int fd); + void setHeaderEnd(bool b); + bool getHeaderEnd() const; + private: + bool _header_end; ssize_t _bytes_read; size_t _content_length; size_t _max_body_size; diff --git a/include/HTTPServer.hpp b/include/HTTPServer.hpp index 8d0c76e..28464f2 100644 --- a/include/HTTPServer.hpp +++ b/include/HTTPServer.hpp @@ -28,7 +28,7 @@ class HTTPServer void setupServers(void); void handleActivePollFDs(); - void handleNewConnection(int fd, const ServerSettings &ServerBlock); + void handleNewConnection(int fd, std::vector &ServerBlock); void handleExistingConnection(const pollfd &poll_fd); }; diff --git a/include/LocationSettings.hpp b/include/LocationSettings.hpp index 7d742fc..a4162a6 100644 --- a/include/LocationSettings.hpp +++ b/include/LocationSettings.hpp @@ -24,7 +24,7 @@ class LocationSettings ~LocationSettings(); LocationSettings(std::vector::iterator &token); LocationSettings(const LocationSettings &rhs); - LocationSettings &operator=(LocationSettings &rhs); + LocationSettings &operator=(const LocationSettings &rhs); // Functionality: // getters: diff --git a/include/Server.hpp b/include/Server.hpp index deb8301..c59db2d 100644 --- a/include/Server.hpp +++ b/include/Server.hpp @@ -15,10 +15,10 @@ class Server ~Server(); int getFD(void) const; - const ServerSettings &getServerSettings(void) const; + std::vector &getServerSettings(void); private: - const std::vector _server_settings; + std::vector _server_settings; Socket _socket; }; diff --git a/include/ServerSettings.hpp b/include/ServerSettings.hpp index ba6829b..3ed6117 100644 --- a/include/ServerSettings.hpp +++ b/include/ServerSettings.hpp @@ -13,7 +13,7 @@ class ServerSettings ServerSettings(std::vector::iterator &token); ~ServerSettings(); ServerSettings(const ServerSettings &rhs); - ServerSettings &operator=(const ServerSettings &rhs) = delete; + ServerSettings &operator=(const ServerSettings &rhs); // Functionality: const LocationSettings & diff --git a/src/Client.cpp b/src/Client.cpp index 2d2f046..d8f9faf 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -8,18 +8,41 @@ #include -Client::Client(const int &server_fd, const ServerSettings &serversetting) - : _request(), _file_manager(serversetting), _socket(server_fd), - _serversetting(serversetting) +Client::Client(const int &server_fd, std::vector &serversetting) + : _request(), _file_manager(), _socket(server_fd), + _server_list(serversetting), _serversetting(serversetting.at(0)) { _socket.setupClient(); - _request.setMaxBodySize(_serversetting.getClientMaxBodySize()); } Client::~Client() { } +void Client::resolveServerSetting() +{ + const std::string &host = _request.getHeader("Host"); + for (const ServerSettings &block : _server_list) + { + std::stringstream ss(block.getServerName()); + std::string name; + + for (; std::getline(ss, name, ' ');) + { + if (host == name) + { + _serversetting = block; + _request.setHeaderEnd(false); + break; + } + } + if (_request.getHeaderEnd() == false) + break; + } + _request.setMaxBodySize(_serversetting.getClientMaxBodySize()); + _file_manager.setServerSetting(_serversetting); +} + int Client::getFD(void) const { return (_socket.getFD()); @@ -35,6 +58,8 @@ ClientState Client::handleConnection(short events) if (events & POLLIN) { _state = _request.receive(_socket.getFD()); + if (_request.getHeaderEnd()) + resolveServerSetting(); return (_state); } else if (events & POLLOUT && _state == ClientState::Loading) diff --git a/src/FileManager.cpp b/src/FileManager.cpp index adf9d53..6faf405 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -8,9 +8,8 @@ #include #include -FileManager::FileManager(const ServerSettings &ServerSettings) - : _response(), _request_target(), _serversetting(ServerSettings), - _autoindex(false) +FileManager::FileManager() + : _response(), _request_target(), _serversetting(), _autoindex(false) { } @@ -214,3 +213,8 @@ void FileManager::setResponse(const std::string str) { _response = str; } + +void FileManager::setServerSetting(const ServerSettings &serversetting) +{ + _serversetting = serversetting; +} diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index 543e3d0..7030399 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -1,3 +1,4 @@ + #include #include #include @@ -93,6 +94,16 @@ const std::string &HTTPRequest::getBody(void) const return (_body); } +void HTTPRequest::setHeaderEnd(bool b) +{ + _header_end = b; +} + +bool HTTPRequest::getHeaderEnd() const +{ + return (_header_end); +} + size_t HTTPRequest::parseStartLine(size_t &i) { Logger &logger = Logger::getInstance(); @@ -134,6 +145,18 @@ size_t HTTPRequest::parseHeaders(size_t &i) return (i); } +ClientState HTTPRequest::setRequestVariables(size_t pos) +{ + _header_end = true; + if (_headers.find("Content-length") != _headers.end()) + _content_length = std::stoi(getHeader("Content-length")); + + if (_content_length == 0) + return (ClientState::Loading); + _body += _http_request.substr(pos + 2); + return (ClientState::Receiving); +} + ClientState HTTPRequest::receive(int client_fd) { Logger &logger = Logger::getInstance(); @@ -165,18 +188,7 @@ ClientState HTTPRequest::receive(int client_fd) { header_end = _http_request.substr(pos - 2, 4); if (header_end == "\r\n\r\n") - { - if (_headers.find("Content-length") != _headers.end()) - { - _content_length = std::stoi(getHeader("Content-length")); - if (_content_length == 0) - return (ClientState::Loading); - _body += _http_request.substr(pos + 2); - return (ClientState::Receiving); - } - else - return (ClientState::Loading); - } + return (setRequestVariables(pos)); pos = parseHeaders(i); } return (ClientState::Receiving); diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index 6ae1d1f..d6d0516 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -42,10 +42,10 @@ void HTTPServer::setupServers(void) Logger &logger = Logger::getInstance(); logger.log(INFO, "Setting up server sockets"); - std::vector> servers = + std::vector> server_list = _parser.sortServerSettings(); - for (const std::vector &list : servers) + for (const std::vector &list : server_list) { std::shared_ptr server = std::make_shared(list); _active_servers.emplace(server->getFD(), server); @@ -86,8 +86,8 @@ void HTTPServer::handleActivePollFDs() } } -void HTTPServer::handleNewConnection(int fd, - const ServerSettings &ServerSettings) +void HTTPServer::handleNewConnection( + int fd, std::vector &ServerSettings) { std::shared_ptr client = std::make_shared(fd, ServerSettings); diff --git a/src/LocationSettings.cpp b/src/LocationSettings.cpp index 45a9a47..6bf2625 100644 --- a/src/LocationSettings.cpp +++ b/src/LocationSettings.cpp @@ -20,7 +20,7 @@ LocationSettings::LocationSettings(const LocationSettings &rhs) { } -LocationSettings &LocationSettings::operator=(LocationSettings &rhs) +LocationSettings &LocationSettings::operator=(const LocationSettings &rhs) { if (this == &rhs) return (*this); diff --git a/src/Server.cpp b/src/Server.cpp index 2bea4b0..2b33923 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -18,7 +18,7 @@ Server::~Server() { } -const ServerSettings &Server::getServerSettings(void) const +std::vector &Server::getServerSettings(void) { return (_server_settings); } diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index 5192f92..13ec324 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -26,6 +26,18 @@ ServerSettings::ServerSettings(const ServerSettings &rhs) { } +ServerSettings &ServerSettings::operator=(const ServerSettings &rhs) +{ + if (this == &rhs) + return (*this); + _listen = rhs._listen; + _server_name = rhs._server_name; + _error_dir = rhs._error_dir; + _client_max_body_size = rhs._client_max_body_size; + _location_settings = rhs._location_settings; + return (*this); +} + ServerSettings::~ServerSettings() { } diff --git a/src/Socket.cpp b/src/Socket.cpp index d0e21f4..c85178d 100644 --- a/src/Socket.cpp +++ b/src/Socket.cpp @@ -49,17 +49,9 @@ Socket::~Socket() void Socket::initSockaddrIn(t_sockaddr_in &addr, const std::string &_listen) { - Logger &logger = Logger::getInstance(); - size_t pos = _listen.find(":"); std::string host = _listen.substr(0, pos); - std::string port; - if (pos == std::string::npos) - port = "80"; // DEFUALT 80 - else - port = _listen.substr(pos + 1); - logger.log(DEBUG, - "listen: " + _listen + "\nhost: " + host + "\nport: " + port); + std::string port = _listen.substr(pos + 1); bzero(&addr, sizeof(addr)); addr.sin_family = AF_INET; From 7e03a0be3d0d75d2fd6fc3582a2c84b53d9eecc9 Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Fri, 26 Apr 2024 21:06:05 +0200 Subject: [PATCH 33/34] Bugfix: was looking for ; (not :) in Host; BUG: Can't load images noted where it's failing --- config/default.conf | 6 +++--- src/Client.cpp | 5 ++++- src/FileManager.cpp | 8 +++++++- src/ServerSettings.cpp | 13 ------------- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/config/default.conf b/config/default.conf index b532ee7..ee5c443 100644 --- a/config/default.conf +++ b/config/default.conf @@ -11,8 +11,8 @@ # Server Configuration server { - listen 127.4.4.4:8081; - server_name localhost; # [M - O] retup the server_names ; [A-Za-z_]* ; default: [EMPTY] + listen 127.0.0.1:8080; + server_name lucy_saus; # [M - O] retup the server_names ; [A-Za-z_]* ; default: [EMPTY] error_dir /data/errors/; # [1 - O] Set a directory that has error page ; [/]{1}[A-Za-z_/:w]* ; Default: [EMPTY] client_max_body_size 3M; # [1 - O] Limit client body size ; [\d]{1,3}[KkMm]? ; Default: 1 mB @@ -46,7 +46,7 @@ server { location /images/ { alias /data/images/; allowed_methods GET POST; - autoindex off; + autoindex on; } location /png/ { diff --git a/src/Client.cpp b/src/Client.cpp index d8f9faf..be81d57 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -21,7 +21,9 @@ Client::~Client() void Client::resolveServerSetting() { - const std::string &host = _request.getHeader("Host"); + Logger &logger = Logger::getInstance(); + const std::string &hp = _request.getHeader("Host"); + std::string host = hp.substr(0, hp.find_first_of(":")); for (const ServerSettings &block : _server_list) { std::stringstream ss(block.getServerName()); @@ -39,6 +41,7 @@ void Client::resolveServerSetting() if (_request.getHeaderEnd() == false) break; } + logger.log(INFO, "Found ServerSetting: " + _serversetting.getServerName()); _request.setMaxBodySize(_serversetting.getClientMaxBodySize()); _file_manager.setServerSetting(_serversetting); } diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 6faf405..49966f2 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -51,8 +51,10 @@ FileManager::applyLocationSettings(const std::string &request_target, void FileManager::openGetFile(const std::string &request_target_path) { + Logger &logger = Logger::getInstance(); const std::string resolved_target = applyLocationSettings(request_target_path, HTTPMethod::GET); + if (_autoindex == true) { HTTPStatus status(StatusCode::OK); @@ -60,11 +62,15 @@ void FileManager::openGetFile(const std::string &request_target_path) return; } - if (!std::filesystem::exists(resolved_target)) + logger.log(DEBUG, "REQUESTtarget: " + resolved_target); + if (!std::filesystem::exists( + resolved_target)) // TODO: ERROR: can't print image throw ClientException(StatusCode::NotFound); + logger.log(DEBUG, "file exists"); _request_target.open(resolved_target, std::ios::in | std::ios::binary); if (!_request_target.is_open()) throw ClientException(StatusCode::NotFound); + logger.log(DEBUG, "file can be found"); HTTPStatus status(StatusCode::OK); _response += status.getStatusLine("HTTP/1.1"); } diff --git a/src/ServerSettings.cpp b/src/ServerSettings.cpp index 13ec324..d17467a 100644 --- a/src/ServerSettings.cpp +++ b/src/ServerSettings.cpp @@ -250,19 +250,6 @@ ServerSettings::resolveLocation(const std::string &request_target) const return (*ret); } -/* TODO: move this method to relevant class, i think it should be Client or - Filemanager - -bool ServerSettings::resolveServerName(const std::string &RequestHost) -{ - std::stringstream ss(getServerName()); - std::string option; - - for (; std::getline(ss, option, ' ');) - { - } -} -*/ // Printing: void ServerSettings::printServerSettings() const From 9c6e59ed31417b2653782055ff89eb543d7dc66a Mon Sep 17 00:00:00 2001 From: Martijn Weverling Date: Sun, 28 Apr 2024 18:49:25 +0200 Subject: [PATCH 34/34] Bugfix: Images can be loaded but I'm not sure how it was fixed... --- src/FileManager.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/FileManager.cpp b/src/FileManager.cpp index 49966f2..4b6375f 100644 --- a/src/FileManager.cpp +++ b/src/FileManager.cpp @@ -51,7 +51,6 @@ FileManager::applyLocationSettings(const std::string &request_target, void FileManager::openGetFile(const std::string &request_target_path) { - Logger &logger = Logger::getInstance(); const std::string resolved_target = applyLocationSettings(request_target_path, HTTPMethod::GET); @@ -62,15 +61,11 @@ void FileManager::openGetFile(const std::string &request_target_path) return; } - logger.log(DEBUG, "REQUESTtarget: " + resolved_target); - if (!std::filesystem::exists( - resolved_target)) // TODO: ERROR: can't print image + if (!std::filesystem::exists(resolved_target)) throw ClientException(StatusCode::NotFound); - logger.log(DEBUG, "file exists"); _request_target.open(resolved_target, std::ios::in | std::ios::binary); if (!_request_target.is_open()) throw ClientException(StatusCode::NotFound); - logger.log(DEBUG, "file can be found"); HTTPStatus status(StatusCode::OK); _response += status.getStatusLine("HTTP/1.1"); }