From f86bc0c5b608e02f5d256ee6cbc243273401b181 Mon Sep 17 00:00:00 2001 From: Taanviir <66136914+Taanviir@users.noreply.github.com> Date: Tue, 16 Apr 2024 01:58:24 +0400 Subject: [PATCH] feat(error-handling): added debug message macro - now error messages print the file and line --- includes/webserv.hpp | 7 ++ .../http/handler/RequestHandlerFactory.hpp | 2 +- sources/http/request/Request.cpp | 2 +- sources/http/response/Response.cpp | 2 +- sources/main.cpp | 9 +-- sources/parser/ConfigParser.cpp | 68 +++++++++---------- sources/parser/ConfigParser.hpp | 2 +- sources/server/Server.cpp | 6 +- 8 files changed, 53 insertions(+), 45 deletions(-) diff --git a/includes/webserv.hpp b/includes/webserv.hpp index 15c9ff4..2883438 100644 --- a/includes/webserv.hpp +++ b/includes/webserv.hpp @@ -82,6 +82,13 @@ typedef vector > vsp; // socket_descriptor type typedef int fd; /* ----------------------------- ERROR MESSAGES ----------------------------- */ +#define THROW_EXCEPTION_WITH_INFO(msg) \ + do { \ + std::ostringstream oss; \ + oss << __FILE__ << ":" << __LINE__ << ": " << R << "error: " << RE << (msg); \ + throw std::runtime_error(oss.str()); \ + } while (0) + static std::string ERR_NULL("Socket: null ptr error"); static std::string ERR_CREAT("Socket: creation failed"); static std::string ERR_BIND("Socket: binding failed"); diff --git a/sources/http/handler/RequestHandlerFactory.hpp b/sources/http/handler/RequestHandlerFactory.hpp index 7cc3e03..8c258b3 100644 --- a/sources/http/handler/RequestHandlerFactory.hpp +++ b/sources/http/handler/RequestHandlerFactory.hpp @@ -20,7 +20,7 @@ class RequestHandlerFactory switch (m) { case GET: return new GetRequestHandler; - default: throw runtime_error("Request Method not implemented\n"); + default: THROW_EXCEPTION_WITH_INFO("Request Method not implemented\n"); } } }; diff --git a/sources/http/request/Request.cpp b/sources/http/request/Request.cpp index 9317f2f..6a3d6f9 100644 --- a/sources/http/request/Request.cpp +++ b/sources/http/request/Request.cpp @@ -11,7 +11,7 @@ Request::Request(const string &rawRequest) } catch (std::ios_base::failure &f) { - throw runtime_error("Invalid request\n"); + THROW_EXCEPTION_WITH_INFO("Invalid request\n"); } } diff --git a/sources/http/response/Response.cpp b/sources/http/response/Response.cpp index 8dfd0dc..7c4f959 100644 --- a/sources/http/response/Response.cpp +++ b/sources/http/response/Response.cpp @@ -115,7 +115,7 @@ void Response::send_response(fd recv_socket) const { result = send(recv_socket, &message[bytesSent], message.size() - bytesSent, 0); if (result == -1) - throw runtime_error(ERR_SEND_FAIL + strerror(errno)); + THROW_EXCEPTION_WITH_INFO(ERR_SEND_FAIL + strerror(errno)); bytesSent += result; } } diff --git a/sources/main.cpp b/sources/main.cpp index 69ac841..c6f593a 100644 --- a/sources/main.cpp +++ b/sources/main.cpp @@ -4,8 +4,9 @@ #include "../includes/webserv.hpp" int main(int argc, char **argv) { - if (argc > 2) { - std::cerr << "Usage: " << argv[0] << " []" << std::endl; + if (argc > 2) + { + cerr << "Usage: " << argv[0] << " []" << endl; exit(1); } @@ -18,8 +19,8 @@ int main(int argc, char **argv) { Server &webserv = Server::get_instance(configs[0], 10); webserv.start(SELECT); } - catch (std::exception &e) + catch (std::exception &error) { - std::cerr << e.what(); + cerr << error.what() << endl; } } diff --git a/sources/parser/ConfigParser.cpp b/sources/parser/ConfigParser.cpp index 693cf9a..df6f851 100644 --- a/sources/parser/ConfigParser.cpp +++ b/sources/parser/ConfigParser.cpp @@ -5,19 +5,19 @@ ConfigParser::ConfigParser(string const& configFile) { // checking file extension if (configFile.find(".conf") == string::npos) - throw runtime_error(ERR_INVALID_FILE); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_FILE); // check if file exists and is a regular file struct stat fileStat; if (stat(configFile.c_str(), &fileStat) == -1 || !S_ISREG(fileStat.st_mode)) - throw runtime_error(ERR_STAT); + THROW_EXCEPTION_WITH_INFO(ERR_STAT); // open file ifstream file(configFile.c_str()); if (!file.is_open()) - throw runtime_error(ERR_OPEN); + THROW_EXCEPTION_WITH_INFO(ERR_OPEN); else if (file.peek() == ifstream::traits_type::eof()) // check if file is empty - throw runtime_error(ERR_EMPTY); + THROW_EXCEPTION_WITH_INFO(ERR_EMPTY); string line; while (std::getline(file, line)) { @@ -44,11 +44,11 @@ void ConfigParser::_parse_error_page(map& errorPages, strin DEBUG_MSG("Parsing error_page directive", RE); if (root.empty()) - throw runtime_error(ERR_MISSING_ROOT); + THROW_EXCEPTION_WITH_INFO(ERR_MISSING_ROOT); ++_itr; // move to error code if (*_itr == ";") - throw runtime_error(ERR_ERROR_CODE); + THROW_EXCEPTION_WITH_INFO(ERR_ERROR_CODE); vector codes; while (_is_string_number(*_itr)) { @@ -56,20 +56,20 @@ void ConfigParser::_parse_error_page(map& errorPages, strin ++_itr; // move to next error code } if (*_itr == ";") - throw runtime_error(ERR_ERROR_PATH); + THROW_EXCEPTION_WITH_INFO(ERR_ERROR_PATH); string errorPath = *_itr; if (errorPath.find(".html") == string::npos && errorPath.find(".htm") == string::npos && errorPath.find(".txt") == string::npos) - throw runtime_error(ERR_INVALID_ERROR_PATH); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_ERROR_PATH); if (errorPath.find("/") == string::npos) - throw runtime_error(ERR_INVALID_ERROR_PATH); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_ERROR_PATH); else if (errorPath.find_first_of("/") != errorPath.find_last_of("/")) - throw runtime_error(ERR_INVALID_ERROR_PATH); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_ERROR_PATH); if (errorPath.find("x") == string::npos) { if (errorPath.find_first_of("x") != errorPath.find_last_of("x")) - throw runtime_error(ERR_INVALID_ERROR_PATH); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_ERROR_PATH); } for (vector::const_iterator itr = codes.begin(); itr != codes.end(); ++itr) { @@ -90,12 +90,12 @@ vector ConfigParser::_parse_index(string const& root) { vector indexFiles; if (root.empty()) - throw runtime_error(ERR_MISSING_ROOT); + THROW_EXCEPTION_WITH_INFO(ERR_MISSING_ROOT); ++_itr; // move to index file while (*_itr != ";") { if (_is_keyword(*_itr)) - throw runtime_error(ERR_INVALID_INDEX); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_INDEX); indexFiles.push_back(root + "/" + *_itr); ++_itr; } @@ -108,7 +108,7 @@ Location ConfigParser::_parse_location_context(void) { ++_itr; // move to location modifier/path if (*_itr == "{") - throw runtime_error(ERR_INVALID_LOCATION); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_LOCATION); Location location; if (*_itr == "=" || *_itr == "~") { @@ -119,7 +119,7 @@ Location ConfigParser::_parse_location_context(void) { ++_itr; // move to { if (*_itr != "{") - throw runtime_error(ERR_INVALID_LOCATION); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_LOCATION); ++_itr; // move to location content while (*_itr != "}") { @@ -131,7 +131,7 @@ Location ConfigParser::_parse_location_context(void) { location.indexFiles = _parse_index(location.root); else { cout << *_itr << endl; - throw runtime_error(ERR_UNEXPECTED_TOKENS_IN_LOCATION); + THROW_EXCEPTION_WITH_INFO(ERR_UNEXPECTED_TOKENS_IN_LOCATION); } ++_itr; } @@ -145,14 +145,14 @@ fd ConfigParser::_parse_listen(void) { ++_itr; // move to port number if (*(_itr + 1) != ";") - throw runtime_error(ERR_MISSING_SEMICOLON); + THROW_EXCEPTION_WITH_INFO(ERR_MISSING_SEMICOLON); if (!_is_string_number(*_itr)) - throw runtime_error(ERR_INVALID_LISTEN); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_LISTEN); fd listenerPort = std::atoi(_itr->c_str()); //! listen can also handle IP address like 0.0.0.0:80 if (listenerPort > MAX_PORT || listenerPort < 0) - throw runtime_error(ERR_INVALID_LISTEN); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_LISTEN); _check_semicolon(); return listenerPort; @@ -164,7 +164,7 @@ void ConfigParser::_parse_server_name(vector& serverName) { ++_itr; // move to server name while (*_itr != ";") { if (_is_keyword(*_itr)) - throw runtime_error(ERR_INVALID_SERVER_NAME); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_SERVER_NAME); serverName.push_back(*_itr); ++_itr; } @@ -175,7 +175,7 @@ string ConfigParser::_parse_root(void) { ++_itr; // move to root path if (*(_itr + 1) != ";") - throw runtime_error(ERR_MISSING_SEMICOLON); + THROW_EXCEPTION_WITH_INFO(ERR_MISSING_SEMICOLON); string rootPath = *_itr; _check_semicolon(); @@ -188,13 +188,13 @@ string ConfigParser::_parse_client_max_body_size(void) { ++_itr; // move to max body size if (*(_itr + 1) != ";") - throw runtime_error(ERR_MISSING_SEMICOLON); + THROW_EXCEPTION_WITH_INFO(ERR_MISSING_SEMICOLON); string maxBodySize = *_itr; //! need to handle suffixes like 1m, 1k, 1g if (maxBodySize.find_first_not_of("0123456789kKmMgG") != string::npos) - throw runtime_error(ERR_INVALID_BODY_SIZE); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_BODY_SIZE); else if (maxBodySize.find_first_of("0123456789") == string::npos) - throw runtime_error(ERR_INVALID_BODY_SIZE); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_BODY_SIZE); _check_semicolon(); @@ -207,7 +207,7 @@ bool ConfigParser::_parse_autoindex(void) { ++_itr; // move to on/off string autoindex = *_itr; if (autoindex != "on" && autoindex != "off") - throw runtime_error(ERR_INVALID_AUTOINDEX); + THROW_EXCEPTION_WITH_INFO(ERR_INVALID_AUTOINDEX); _check_semicolon(); return autoindex == "on"; } @@ -217,7 +217,7 @@ ServerConfig ConfigParser::_parse_server_context(void) { ++_itr; // move to { if (*_itr != "{") - throw runtime_error(ERR_OPENINING_BRACE); + THROW_EXCEPTION_WITH_INFO(ERR_OPENINING_BRACE); ++_itr; // move to first directive ServerConfig _serverConfig; @@ -239,7 +239,7 @@ ServerConfig ConfigParser::_parse_server_context(void) { else if (*_itr == "autoindex") _serverConfig.autoindex = _parse_autoindex(); else - throw runtime_error(ERR_UNEXPECTED_TOKENS_IN_SERVER); + THROW_EXCEPTION_WITH_INFO(ERR_UNEXPECTED_TOKENS_IN_SERVER); if (*_itr == ";") ++_itr; } @@ -253,11 +253,11 @@ vector ConfigParser::_parse_HTTP_context(void) { // setting values for Config object _itr = _tokens.begin(); if (*_itr != "http") //! maybe there's stuff in the global context - throw runtime_error(ERR_MISSING_HTTP); + THROW_EXCEPTION_WITH_INFO(ERR_MISSING_HTTP); ++_itr; // move to { if (*_itr != "{") - throw runtime_error(ERR_OPENINING_BRACE); + THROW_EXCEPTION_WITH_INFO(ERR_OPENINING_BRACE); ++_itr; // move to first directive vector serverConfigs; @@ -265,12 +265,12 @@ vector ConfigParser::_parse_HTTP_context(void) { if (*_itr == "server") serverConfigs.push_back(_parse_server_context()); else - throw runtime_error(ERR_UNEXPECTED_TOKENS_IN); + THROW_EXCEPTION_WITH_INFO(ERR_UNEXPECTED_TOKENS_IN); ++_itr; } if ((_itr + 1) != _tokens.end()) - throw runtime_error(ERR_UNEXPECTED_TOKENS_OUT); + THROW_EXCEPTION_WITH_INFO(ERR_UNEXPECTED_TOKENS_OUT); return serverConfigs; } @@ -303,17 +303,17 @@ vector ConfigParser::parse(void) { if (*itr == "{") { if (*(itr - 1) != "server" && *(itr - 1) != "http" && *(itr - 2) != "location" && *(itr - 3) != "location") - throw runtime_error(ERR_MISSING_CONTEXT); + THROW_EXCEPTION_WITH_INFO(ERR_MISSING_CONTEXT); braces.push("{"); } else if (*itr == "}") { if (braces.empty()) // missing opening brace - throw runtime_error(ERR_OPENINING_BRACE); + THROW_EXCEPTION_WITH_INFO(ERR_OPENINING_BRACE); braces.pop(); } } if (!braces.empty()) // missing closing brace - throw runtime_error(ERR_CLOSING_BRACE); + THROW_EXCEPTION_WITH_INFO(ERR_CLOSING_BRACE); return _parse_HTTP_context(); } diff --git a/sources/parser/ConfigParser.hpp b/sources/parser/ConfigParser.hpp index 24be91b..f11fa10 100644 --- a/sources/parser/ConfigParser.hpp +++ b/sources/parser/ConfigParser.hpp @@ -99,7 +99,7 @@ class ConfigParser { } void _check_semicolon(void) { if (*(_itr + 1) != ";") - throw runtime_error(ERR_MISSING_SEMICOLON); + THROW_EXCEPTION_WITH_INFO(ERR_MISSING_SEMICOLON); ++_itr; // move to semicolon } }; diff --git a/sources/server/Server.cpp b/sources/server/Server.cpp index 959afeb..73c2118 100644 --- a/sources/server/Server.cpp +++ b/sources/server/Server.cpp @@ -80,7 +80,7 @@ bool Server::handle_connection(fd recvSocket) bytesReceived = recv(recvSocket, &buffer[0], BUFFER_SIZE, 0); if (bytesReceived == -1) - throw runtime_error(strerror(errno)); + THROW_EXCEPTION_WITH_INFO(strerror(errno)); if (bytesReceived == 0) return CLOSE_CONNECTION; @@ -134,7 +134,7 @@ void Server::select_strat() readytoRead = activeSockets; if (select(maxSocketDescriptor + 1, &readytoRead, NULL, NULL, &selectTimeOut) < 0) - throw runtime_error(strerror(errno)); + THROW_EXCEPTION_WITH_INFO(strerror(errno)); selectTimeOut.tv_sec = SELECTWAITTIME; for (fd currentSocket = 0; currentSocket <= maxSocketDescriptor; currentSocket++) @@ -177,6 +177,6 @@ void Server::start(enum polling_strat strategy) // case KQUEUE: kqueue_strat(); break; // case POLL: poll_strat(); break; // case EPOLL: epoll_strat(); break; - default: throw runtime_error("Invalid strategy"); break; + default: THROW_EXCEPTION_WITH_INFO("Invalid strategy"); break; } }