From 28713b407a8a0307aa6fd63861e4808246281d2a Mon Sep 17 00:00:00 2001 From: y-syo Date: Fri, 14 Feb 2025 17:11:33 +0100 Subject: [PATCH 1/9] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D=20w?= =?UTF-8?q?ip(requests):=20work=20in=20progress,=20not=20done=20yet.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/requests/HttpIMessage.hpp | 4 +- includes/requests/HttpRequest.hpp | 3 +- src/main.cpp | 34 +++++----- src/requests_handling/HttpRequests.cpp | 86 +++++++++++++++++++++++++- 4 files changed, 106 insertions(+), 21 deletions(-) diff --git a/includes/requests/HttpIMessage.hpp b/includes/requests/HttpIMessage.hpp index e72e361..d2c1a79 100644 --- a/includes/requests/HttpIMessage.hpp +++ b/includes/requests/HttpIMessage.hpp @@ -6,7 +6,7 @@ /* By: mmoussou _headers; std::string _body; + static const std::map _response_status_codes; + }; } // -namespace http diff --git a/includes/requests/HttpRequest.hpp b/includes/requests/HttpRequest.hpp index 830bfaa..8670da5 100644 --- a/includes/requests/HttpRequest.hpp +++ b/includes/requests/HttpRequest.hpp @@ -6,7 +6,7 @@ /* By: mmoussou #include #include #include diff --git a/src/main.cpp b/src/main.cpp index c718751..a17cea2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ /* By: mmoussou _body = body_stream.str(); - /* + ///* + std::cout << "-- start-line --" << std::endl; std::cout << "method: " << this->_method << std::endl; std::cout << "target: " << this->_target << std::endl; std::cout << "protocol: " << this->_protocol << std::endl; @@ -112,7 +113,7 @@ void http::Get::parse(std::string const &data) std::cout << it->first << ": " << it->second << std::endl; std::cout << std::endl; std::cout << "-- body --" << std::endl << this->_body << std::endl; - */ + //*/ } http::Response http::Get::execute(void) @@ -142,3 +143,82 @@ http::Response http::Get::execute(void) } // ------------------------------------------------------------------ + +http::Delete::Delete(void) +{ +} + +http::Delete::Delete(std::string &data) +{ + this->parse(data); +} + +void http::Delete::parse(std::string const &data) +{ + std::istringstream stream(data); + std::string line; + + if (std::getline(stream, line)) + { + std::istringstream line_stream(line); + line_stream >> this->_method >> this->_target >> this->_protocol; + this->_target.insert(this->_target.begin(), '.'); + } + + while (std::getline(stream, line) && line != "\r") + { + size_t delimiter_index = line.find(':'); + if (delimiter_index != std::string::npos) + { + std::string key = line.substr(0, delimiter_index); + std::string value = line.substr(delimiter_index + 2); + this->_headers.insert(std::make_pair(key, value)); + } + } + + std::ostringstream body_stream; + while (std::getline(stream, line)) + body_stream << line << "\n"; + this->_body = body_stream.str(); + + ///* + std::cout << "-- start-line --" << std::endl; + std::cout << "method: " << this->_method << std::endl; + std::cout << "target: " << this->_target << std::endl; + std::cout << "protocol: " << this->_protocol << std::endl; + std::cout << std::endl; + std::cout << "-- headers --" << std::endl; + for (std::map::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it) + std::cout << it->first << ": " << it->second << std::endl; + std::cout << std::endl; + std::cout << "-- body --" << std::endl << this->_body << std::endl; + //*/ +} + +http::Response http::Delete::execute(void) +{ + http::Response response; + + try + { + if (std::remove(this->_target.c_str())) + throw; + response.setProtocol(this->_protocol); + response.setStatusCode(204); + response.setStatusText("No Content"); + time_t now = std::time(NULL); + response.addHeader("Date", std::string(std::ctime(&now))); + } + catch (...) + { + // TODO: replace with a predefined array of error pages + response.setProtocol(this->_protocol); + response.setStatusCode(404); + response.setStatusText("Not Found"); + response.addHeader("Content-Type", "text/html"); + response.setBody("nuh uh, get 404'd >:D"); + } + + return (response); +} + From 5f9fec9568dad9a88b565e4f40f20f0ee8048f35 Mon Sep 17 00:00:00 2001 From: y-syo Date: Mon, 17 Mar 2025 14:33:38 +0100 Subject: [PATCH 2/9] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D=20w?= =?UTF-8?q?ip:=20work=20in=20progress,=20not=20done=20yet.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/requests/Errors.hpp | 132 +++++++++++++++++++++++++ includes/requests/default.hpp | 3 +- src/main.cpp | 2 +- src/requests_handling/Errors.cpp | 100 +++++++++++++++++++ src/requests_handling/HttpRequests.cpp | 79 ++++++++++++++- src/requests_handling/HttpResponse.cpp | 8 +- 6 files changed, 316 insertions(+), 8 deletions(-) create mode 100644 includes/requests/Errors.hpp create mode 100644 src/requests_handling/Errors.cpp diff --git a/includes/requests/Errors.hpp b/includes/requests/Errors.hpp new file mode 100644 index 0000000..225293d --- /dev/null +++ b/includes/requests/Errors.hpp @@ -0,0 +1,132 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Errors.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: mmoussou +#include + +#include + +namespace webserv { +namespace http { + +/* + * DOES NOT WORK + * still need to do uh things but base is done at least :D +*/ + +class Errors { +public: + static http::Response &getRequest(int error_code); + static void setEntry(const std::string &key, int value); + +private: + static std::map populateMessages(); + + static std::map message; + static std::map set_error_pages; + +}; + +/*std::map Errors::populateMessages() +{ + std::map m; + + m[100] = "Continue"; + m[101] = "Switching Protocols"; + m[102] = "Processing"; + m[103] = "Early Hints"; + m[200] = "OK"; + m[201] = "Created"; + m[202] = "Accepted"; + m[203] = "Non-Authoritative Information"; + m[204] = "No Content"; + m[205] = "Reset Content"; + m[206] = "Partial Content"; + m[207] = "Multi-Status"; + m[208] = "Already Reported"; + m[226] = "IM Used"; + m[300] = "Multiple Choices"; + m[301] = "Moved Permanently"; + m[302] = "Found"; + m[303] = "See Other"; + m[304] = "Not Modified"; + m[305] = "Use Proxy"; + m[306] = "Switch Proxy"; + m[307] = "Temporary Redirect"; + m[308] = "Permanent Redirect"; + m[400] = "Bad Request"; + m[401] = "Unauthorized"; + m[402] = "Payment Required"; + m[403] = "Forbidden"; + m[404] = "Not Found"; + m[405] = "Method Not Allowed"; + m[406] = "Not Acceptable"; + m[407] = "Proxy Authentication Required"; + m[408] = "Request Timeout"; + m[409] = "Conflict"; + m[410] = "Gone"; + m[411] = "Length Required"; + m[412] = "Precondition Failed"; + m[413] = "Payload Too Large"; + m[414] = "URI Too Long"; + m[415] = "Unsupported Media Type"; + m[416] = "Range Not Satisfiable"; + m[417] = "Expectation Failed"; + m[418] = "I'm a teapot"; + m[420] = "Method Failure"; + m[421] = "Misdirected Request"; + m[422] = "Unprocessable Entity"; + m[423] = "Locked"; + m[424] = "Failed Dependency"; + m[426] = "Upgrade Required"; + m[428] = "Precondition Required"; + m[429] = "Too Many Requests"; + m[431] = "Request Header Fields Too Large"; + m[451] = "Unavailable For Legal Reasons"; + m[500] = "Internal Server error"; + m[501] = "Not Implemented"; + m[502] = "Bad Gateway"; + m[503] = "Service Unavailable"; + m[504] = "gateway Timeout"; + m[505] = "Http version not supported"; + m[506] = "Varient Also negotiate"; + m[507] = "Insufficient Storage"; + m[508] = "Loop Detected"; + m[510] = "Not Extended"; + m[511] = "Network Authentication Required"; + + return m; +} + +std::map Errors::message = Errors::populateMessages(); + +std::map Errors::set_error_pages; + +http::Response &Errors::getRequest(int error_code) +{ + http::Response *result = new http::Response; + + if (Errors::set_error_pages.find(error_code) != Errors::set_error_pages.end()) + result->setBody(Errors::set_error_pages[error_code]); + else + result->setBody("

" + Errors::message[error_code] + "

"); + return (*result); +}*/ + +} // -namespace http +} // -namespace webserv + +#endif // __WEBSERV_REQUESTS_ERRORS_HPP__ diff --git a/includes/requests/default.hpp b/includes/requests/default.hpp index 3c8763d..82636b6 100644 --- a/includes/requests/default.hpp +++ b/includes/requests/default.hpp @@ -6,7 +6,7 @@ /* By: mmoussou #include #include diff --git a/src/main.cpp b/src/main.cpp index a17cea2..a7a18f4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ /* By: mmoussou + +using namespace webserv; + +http::Response &http::Errors::getRequest(int error_code) +{ + http::Response *result = new http::Response; + + if (http::Errors::set_error_pages.find(error_code) != http::Errors::set_error_pages.end()) + result->setBody(Errors::set_error_pages[error_code]); + else + result->setBody("

" + http::Errors::message[error_code] + "

"); + return (*result); +} + +std::map http::Errors::message = Errors::populateMessages(); +std::map http::Errors::set_error_pages; + +std::map http::Errors::populateMessages() +{ + std::map m; + + m[100] = "Continue"; + m[101] = "Switching Protocols"; + m[102] = "Processing"; + m[103] = "Early Hints"; + m[200] = "OK"; + m[201] = "Created"; + m[202] = "Accepted"; + m[203] = "Non-Authoritative Information"; + m[204] = "No Content"; + m[205] = "Reset Content"; + m[206] = "Partial Content"; + m[207] = "Multi-Status"; + m[208] = "Already Reported"; + m[226] = "IM Used"; + m[300] = "Multiple Choices"; + m[301] = "Moved Permanently"; + m[302] = "Found"; + m[303] = "See Other"; + m[304] = "Not Modified"; + m[305] = "Use Proxy"; + m[306] = "Switch Proxy"; + m[307] = "Temporary Redirect"; + m[308] = "Permanent Redirect"; + m[400] = "Bad Request"; + m[401] = "Unauthorized"; + m[402] = "Payment Required"; + m[403] = "Forbidden"; + m[404] = "Not Found"; + m[405] = "Method Not Allowed"; + m[406] = "Not Acceptable"; + m[407] = "Proxy Authentication Required"; + m[408] = "Request Timeout"; + m[409] = "Conflict"; + m[410] = "Gone"; + m[411] = "Length Required"; + m[412] = "Precondition Failed"; + m[413] = "Payload Too Large"; + m[414] = "URI Too Long"; + m[415] = "Unsupported Media Type"; + m[416] = "Range Not Satisfiable"; + m[417] = "Expectation Failed"; + m[418] = "I'm a teapot"; + m[420] = "Method Failure"; + m[421] = "Misdirected Request"; + m[422] = "Unprocessable Entity"; + m[423] = "Locked"; + m[424] = "Failed Dependency"; + m[426] = "Upgrade Required"; + m[428] = "Precondition Required"; + m[429] = "Too Many Requests"; + m[431] = "Request Header Fields Too Large"; + m[451] = "Unavailable For Legal Reasons"; + m[500] = "Internal Server error"; + m[501] = "Not Implemented"; + m[502] = "Bad Gateway"; + m[503] = "Service Unavailable"; + m[504] = "gateway Timeout"; + m[505] = "Http version not supported"; + m[506] = "Varient Also negotiate"; + m[507] = "Insufficient Storage"; + m[508] = "Loop Detected"; + m[510] = "Not Extended"; + m[511] = "Network Authentication Required"; + + return m; +} diff --git a/src/requests_handling/HttpRequests.cpp b/src/requests_handling/HttpRequests.cpp index 3f04829..6582ad8 100644 --- a/src/requests_handling/HttpRequests.cpp +++ b/src/requests_handling/HttpRequests.cpp @@ -6,7 +6,7 @@ /* By: mmoussou _protocol); response.setStatusCode(200); response.setStatusText("OK"); - response.addHeader("Content-Type", "text/html"); + response.addHeader("Content-Type", "text/html"); // TODO: change it to check the file extension and set it to the corresponding MIME or text/plain if unkown. we will only implement the important MIME types in the Mozilla documentation because https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types + + std::ifstream file_end(this->_target.c_str(), std::ios::binary | std::ios::ate); + std::stringstream length; + length << (file_end.tellg() - file.tellg()); + std::cout << length.str(); + response.addHeader("Content-Length", length.str()); + response.setBody(std::string((std::istreambuf_iterator(file)), std::istreambuf_iterator())); } catch (...) @@ -204,14 +211,15 @@ http::Response http::Delete::execute(void) if (std::remove(this->_target.c_str())) throw; response.setProtocol(this->_protocol); - response.setStatusCode(204); + response.setStatusCode(204); // this cool dude on the internet said i should not do that so i'll change it https://blog.ploeh.dk/2013/04/30/rest-lesson-learned-avoid-204-responses/ response.setStatusText("No Content"); time_t now = std::time(NULL); response.addHeader("Date", std::string(std::ctime(&now))); } catch (...) { - // TODO: replace with a predefined array of error pages + // TODO: check errno value and get corresponding error page, check for corresponding error code : https://cdn.discordapp.com/attachments/784779058407014403/1350841524778307586/image.png?ex=67d8dd74&is=67d78bf4&hm=c030468d3862627d6402bf200960d1a15249ba2f8dac772af3283b368a77f2f5& + response.setProtocol(this->_protocol); response.setStatusCode(404); response.setStatusText("Not Found"); @@ -222,3 +230,66 @@ http::Response http::Delete::execute(void) return (response); } +// ------------------------------------------------------------------ + +http::Post::Post(void) +{ +} + +http::Post::Post(std::string &data) +{ + this->parse(data); +} + +void http::Post::parse(std::string const &data) +{ + std::istringstream stream(data); + std::string line; + + if (std::getline(stream, line)) + { + std::istringstream line_stream(line); + line_stream >> this->_method >> this->_target >> this->_protocol; + this->_target.insert(this->_target.begin(), '.'); + } + + while (std::getline(stream, line) && line != "\r") + { + size_t delimiter_index = line.find(':'); + if (delimiter_index != std::string::npos) + { + std::string key = line.substr(0, delimiter_index); + std::string value = line.substr(delimiter_index + 2); + this->_headers.insert(std::make_pair(key, value)); + } + } + + std::ostringstream body_stream; + while (std::getline(stream, line)) + body_stream << line << "\n"; + this->_body = body_stream.str(); + + ///* + std::cout << "-- start-line --" << std::endl; + std::cout << "method: " << this->_method << std::endl; + std::cout << "target: " << this->_target << std::endl; + std::cout << "protocol: " << this->_protocol << std::endl; + std::cout << std::endl; + std::cout << "-- headers --" << std::endl; + for (std::map::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it) + std::cout << it->first << ": " << it->second << std::endl; + std::cout << std::endl; + std::cout << "-- body --" << std::endl << this->_body << std::endl; + //*/ +} + +http::Response http::Post::execute(void) +{ + http::Response response; + + // uh idk anymore + + return (response); +} + +// ------------------------------------------------------------------ diff --git a/src/requests_handling/HttpResponse.cpp b/src/requests_handling/HttpResponse.cpp index 5857f28..a5dbb24 100644 --- a/src/requests_handling/HttpResponse.cpp +++ b/src/requests_handling/HttpResponse.cpp @@ -6,17 +6,20 @@ /* By: mmoussou /* - do a map of all the status_text and get it from here, not storing them - get error pages from an array of predefined response, that would be modified by the config */ +// tmp, need to be cleaned +#include + using namespace webserv; http::Response::Response(void) @@ -36,6 +39,7 @@ std::string http::Response::str(void) const response << "\r\n"; response << this->_body; + std::cout << "------------ RESPONSE -------------" << std::endl << response.str(); return (response.str()); } From cf509f09b7b41b75195ed7b40d3f51d88d2794cc Mon Sep 17 00:00:00 2001 From: y-syo Date: Wed, 19 Mar 2025 03:15:20 +0100 Subject: [PATCH 3/9] =?UTF-8?q?=E3=80=8C=E2=9C=A8=E3=80=8D=20feat(http/GET?= =?UTF-8?q?):=20file=20listing=20page=20if=20opening=20a=20directory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/requests/Errors.hpp | 90 +------------------------- includes/requests/HttpResponse.hpp | 3 +- src/main.cpp | 7 +- src/requests_handling/Errors.cpp | 2 +- src/requests_handling/HttpRequests.cpp | 87 ++++++++++++++++++++----- src/requests_handling/HttpResponse.cpp | 9 +-- 6 files changed, 84 insertions(+), 114 deletions(-) diff --git a/includes/requests/Errors.hpp b/includes/requests/Errors.hpp index 225293d..2eb958c 100644 --- a/includes/requests/Errors.hpp +++ b/includes/requests/Errors.hpp @@ -6,7 +6,7 @@ /* By: mmoussou message; private: static std::map populateMessages(); - static std::map message; static std::map set_error_pages; }; -/*std::map Errors::populateMessages() -{ - std::map m; - - m[100] = "Continue"; - m[101] = "Switching Protocols"; - m[102] = "Processing"; - m[103] = "Early Hints"; - m[200] = "OK"; - m[201] = "Created"; - m[202] = "Accepted"; - m[203] = "Non-Authoritative Information"; - m[204] = "No Content"; - m[205] = "Reset Content"; - m[206] = "Partial Content"; - m[207] = "Multi-Status"; - m[208] = "Already Reported"; - m[226] = "IM Used"; - m[300] = "Multiple Choices"; - m[301] = "Moved Permanently"; - m[302] = "Found"; - m[303] = "See Other"; - m[304] = "Not Modified"; - m[305] = "Use Proxy"; - m[306] = "Switch Proxy"; - m[307] = "Temporary Redirect"; - m[308] = "Permanent Redirect"; - m[400] = "Bad Request"; - m[401] = "Unauthorized"; - m[402] = "Payment Required"; - m[403] = "Forbidden"; - m[404] = "Not Found"; - m[405] = "Method Not Allowed"; - m[406] = "Not Acceptable"; - m[407] = "Proxy Authentication Required"; - m[408] = "Request Timeout"; - m[409] = "Conflict"; - m[410] = "Gone"; - m[411] = "Length Required"; - m[412] = "Precondition Failed"; - m[413] = "Payload Too Large"; - m[414] = "URI Too Long"; - m[415] = "Unsupported Media Type"; - m[416] = "Range Not Satisfiable"; - m[417] = "Expectation Failed"; - m[418] = "I'm a teapot"; - m[420] = "Method Failure"; - m[421] = "Misdirected Request"; - m[422] = "Unprocessable Entity"; - m[423] = "Locked"; - m[424] = "Failed Dependency"; - m[426] = "Upgrade Required"; - m[428] = "Precondition Required"; - m[429] = "Too Many Requests"; - m[431] = "Request Header Fields Too Large"; - m[451] = "Unavailable For Legal Reasons"; - m[500] = "Internal Server error"; - m[501] = "Not Implemented"; - m[502] = "Bad Gateway"; - m[503] = "Service Unavailable"; - m[504] = "gateway Timeout"; - m[505] = "Http version not supported"; - m[506] = "Varient Also negotiate"; - m[507] = "Insufficient Storage"; - m[508] = "Loop Detected"; - m[510] = "Not Extended"; - m[511] = "Network Authentication Required"; - - return m; -} - -std::map Errors::message = Errors::populateMessages(); - -std::map Errors::set_error_pages; - -http::Response &Errors::getRequest(int error_code) -{ - http::Response *result = new http::Response; - - if (Errors::set_error_pages.find(error_code) != Errors::set_error_pages.end()) - result->setBody(Errors::set_error_pages[error_code]); - else - result->setBody("

" + Errors::message[error_code] + "

"); - return (*result); -}*/ - } // -namespace http } // -namespace webserv diff --git a/includes/requests/HttpResponse.hpp b/includes/requests/HttpResponse.hpp index c9c7304..db5a7d7 100644 --- a/includes/requests/HttpResponse.hpp +++ b/includes/requests/HttpResponse.hpp @@ -6,7 +6,7 @@ /* By: mmoussou +#include + #include +#include +#include using namespace webserv; @@ -116,32 +121,86 @@ void http::Get::parse(std::string const &data) //*/ } +char isDirectory(const std::string& path) { + struct stat fileStat; + if (stat(path.c_str(), &fileStat) != 0) + throw; + return S_ISDIR(fileStat.st_mode); +} + http::Response http::Get::execute(void) { http::Response response; try { - std::ifstream file(this->_target.c_str(), std::ios::binary); - response.setProtocol(this->_protocol); - response.setStatusCode(200); - response.setStatusText("OK"); - response.addHeader("Content-Type", "text/html"); // TODO: change it to check the file extension and set it to the corresponding MIME or text/plain if unkown. we will only implement the important MIME types in the Mozilla documentation because https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types + if (isDirectory(this->_target)) + { + DIR *dir; + struct dirent *entry; + struct stat file_stat; + std::vector files; + + if ((dir = opendir(this->_target.c_str())) == NULL) + throw; + while ((entry = readdir(dir)) != NULL) + { + std::string file_name = entry->d_name; + if (file_name == ".") + continue; + std::string file_path = this->_target + "/" + file_name; + if (stat(file_path.c_str(), &file_stat) == 0) + { + if (S_ISDIR(file_stat.st_mode)) + files.push_back(file_name + "/"); + else + files.push_back(file_name); + } + } + closedir(dir); - std::ifstream file_end(this->_target.c_str(), std::ios::binary | std::ios::ate); - std::stringstream length; - length << (file_end.tellg() - file.tellg()); - std::cout << length.str(); - response.addHeader("Content-Length", length.str()); + std::sort(files.begin(), files.end()); - response.setBody(std::string((std::istreambuf_iterator(file)), std::istreambuf_iterator())); + std::string body = "
    \n"; + for (size_t i = 0; i < files.size(); i++) + body += "
  • " + files[i] + "
  • \n"; + body += "
"; + + response.setProtocol(this->_protocol); + response.setStatusCode(200); + std::stringstream length; + length << body.length(); + response.addHeader("Content-Length", length.str()); + response.addHeader("Content-Type", "text/html"); + response.setBody(body); + + } + else + { + std::ifstream file(this->_target.c_str(), std::ios::binary); + std::streampos file_start = file.tellg(); + response.setBody(std::string((std::istreambuf_iterator(file)), std::istreambuf_iterator())); + std::stringstream length; + length << (file.tellg() - file_start); + std::cout << length.str() << std::endl; + response.addHeader("Content-Length", length.str()); + + response.setProtocol(this->_protocol); + response.setStatusCode(200); + response.addHeader("Content-Type", "text/html"); // TODO: change it to check the file extension and set it to the corresponding MIME or text/plain if unkown. we will only implement the important MIME types in the Mozilla documentation because https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types + + //std::ifstream file_end(this->_target.c_str(), std::ios::binary | std::ios::ate); + //std::stringstream length; + //length << (file_end.tellg() - file.tellg()); + //std::cout << length.str() << std::endl; + //response.addHeader("Content-Length", length.str()); + } } catch (...) { // TODO: replace with a predefined array of error pages response.setProtocol(this->_protocol); response.setStatusCode(404); - response.setStatusText("Not Found"); response.addHeader("Content-Type", "text/html"); response.setBody("nuh uh, get 404'd >:D"); } @@ -212,7 +271,6 @@ http::Response http::Delete::execute(void) throw; response.setProtocol(this->_protocol); response.setStatusCode(204); // this cool dude on the internet said i should not do that so i'll change it https://blog.ploeh.dk/2013/04/30/rest-lesson-learned-avoid-204-responses/ - response.setStatusText("No Content"); time_t now = std::time(NULL); response.addHeader("Date", std::string(std::ctime(&now))); } @@ -222,7 +280,6 @@ http::Response http::Delete::execute(void) response.setProtocol(this->_protocol); response.setStatusCode(404); - response.setStatusText("Not Found"); response.addHeader("Content-Type", "text/html"); response.setBody("nuh uh, get 404'd >:D"); } diff --git a/src/requests_handling/HttpResponse.cpp b/src/requests_handling/HttpResponse.cpp index a5dbb24..0626827 100644 --- a/src/requests_handling/HttpResponse.cpp +++ b/src/requests_handling/HttpResponse.cpp @@ -6,11 +6,12 @@ /* By: mmoussou +#include /* - do a map of all the status_text and get it from here, not storing them @@ -66,9 +67,5 @@ void http::Response::setProtocol(std::string const protocol) void http::Response::setStatusCode(size_t const status_code) { this->_status_code = status_code; -} - -void http::Response::setStatusText(std::string const status_text) -{ - this->_status_text = status_text; + this->_status_text = Errors::message[status_code]; } From 7c2a6e10e22c602db65f3d2fbb86eae9840fabf1 Mon Sep 17 00:00:00 2001 From: y-syo Date: Mon, 24 Mar 2025 13:11:27 +0100 Subject: [PATCH 4/9] =?UTF-8?q?=E3=80=8C=E2=9C=8F=EF=B8=8F=E3=80=8D=20norm?= =?UTF-8?q?(http/requests.cpp):=20normed=20variable=20names?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/requests_handling/HttpRequests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/requests_handling/HttpRequests.cpp b/src/requests_handling/HttpRequests.cpp index 6c4aa5a..c17f982 100644 --- a/src/requests_handling/HttpRequests.cpp +++ b/src/requests_handling/HttpRequests.cpp @@ -6,7 +6,7 @@ /* By: mmoussou Date: Mon, 24 Mar 2025 16:01:45 +0100 Subject: [PATCH 5/9] =?UTF-8?q?=E3=80=8C=F0=9F=94=A8=E3=80=8D=20fix(reques?= =?UTF-8?q?ts/Errors):=20now=20working,=20kinda?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/requests/Errors.hpp | 7 ++++--- src/requests_handling/Errors.cpp | 11 +++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/includes/requests/Errors.hpp b/includes/requests/Errors.hpp index 2eb958c..c57a05d 100644 --- a/includes/requests/Errors.hpp +++ b/includes/requests/Errors.hpp @@ -6,7 +6,7 @@ /* By: mmoussou message; private: diff --git a/src/requests_handling/Errors.cpp b/src/requests_handling/Errors.cpp index 4313652..2139389 100644 --- a/src/requests_handling/Errors.cpp +++ b/src/requests_handling/Errors.cpp @@ -6,7 +6,7 @@ /* By: mmoussou setBody(Errors::set_error_pages[error_code]); + return(Errors::set_error_pages[error_code]); else - result->setBody("

" + http::Errors::message[error_code] + "

"); - return (*result); + return("

" + http::Errors::message[error_code] + "

"); } std::map http::Errors::message = Errors::populateMessages(); From f6263c85500076bbd01630b0af2f2fa67e4e0575 Mon Sep 17 00:00:00 2001 From: y-syo Date: Mon, 24 Mar 2025 16:01:56 +0100 Subject: [PATCH 6/9] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D=20w?= =?UTF-8?q?ip(http):=20work=20in=20progress,=20not=20done=20yet.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/requests/HttpResponse.hpp | 10 ++++++---- src/requests_handling/HttpRequests.cpp | 25 +++++++++++++++---------- src/requests_handling/HttpResponse.cpp | 6 +++--- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/includes/requests/HttpResponse.hpp b/includes/requests/HttpResponse.hpp index db5a7d7..1c4283b 100644 --- a/includes/requests/HttpResponse.hpp +++ b/includes/requests/HttpResponse.hpp @@ -6,7 +6,7 @@ /* By: mmoussou +typedef unsigned int uint; + namespace webserv { namespace http { @@ -26,17 +28,17 @@ public: Response(void); std::string getProtocol(void) const; - size_t getStatusCode(void) const; + uint getStatusCode(void) const; std::string getStatusText(void) const; void setProtocol(std::string const protocol); - void setStatusCode(size_t const status_code); + void setStatusCode(uint const status_code); std::string str(void) const; private: std::string _protocol; - size_t _status_code; + uint _status_code; std::string _status_text; }; diff --git a/src/requests_handling/HttpRequests.cpp b/src/requests_handling/HttpRequests.cpp index c17f982..7b205fe 100644 --- a/src/requests_handling/HttpRequests.cpp +++ b/src/requests_handling/HttpRequests.cpp @@ -6,7 +6,7 @@ /* By: mmoussou #include +#include #include #include @@ -107,7 +108,7 @@ void http::Get::parse(std::string const &data) body_stream << line << "\n"; this->_body = body_stream.str(); - ///* + /* std::cout << "-- start-line --" << std::endl; std::cout << "method: " << this->_method << std::endl; std::cout << "target: " << this->_target << std::endl; @@ -118,13 +119,17 @@ void http::Get::parse(std::string const &data) std::cout << it->first << ": " << it->second << std::endl; std::cout << std::endl; std::cout << "-- body --" << std::endl << this->_body << std::endl; - //*/ + */ } -char isDirectory(const std::string& path) { +char isDirectory(const std::string& path) +{ struct stat file_stat; + if (stat(path.c_str(), &file_stat) != 0) - throw; + { + throw std::runtime_error("can't open file (non-existant ?)"); + } return S_ISDIR(file_stat.st_mode); } @@ -202,7 +207,7 @@ http::Response http::Get::execute(void) response.setProtocol(this->_protocol); response.setStatusCode(404); response.addHeader("Content-Type", "text/html"); - response.setBody("nuh uh, get 404'd >:D"); + response.setBody(http::Errors::getResponseBody(response.getStatusCode())); } return (response); @@ -247,7 +252,7 @@ void http::Delete::parse(std::string const &data) body_stream << line << "\n"; this->_body = body_stream.str(); - ///* + /* std::cout << "-- start-line --" << std::endl; std::cout << "method: " << this->_method << std::endl; std::cout << "target: " << this->_target << std::endl; @@ -258,7 +263,7 @@ void http::Delete::parse(std::string const &data) std::cout << it->first << ": " << it->second << std::endl; std::cout << std::endl; std::cout << "-- body --" << std::endl << this->_body << std::endl; - //*/ + */ } http::Response http::Delete::execute(void) @@ -268,7 +273,7 @@ http::Response http::Delete::execute(void) try { if (std::remove(this->_target.c_str())) - throw; + throw std::runtime_error("can't remove file, FF"); response.setProtocol(this->_protocol); response.setStatusCode(204); // this cool dude on the internet said i should not do that so i'll change it https://blog.ploeh.dk/2013/04/30/rest-lesson-learned-avoid-204-responses/ time_t now = std::time(NULL); @@ -281,7 +286,7 @@ http::Response http::Delete::execute(void) response.setProtocol(this->_protocol); response.setStatusCode(404); response.addHeader("Content-Type", "text/html"); - response.setBody("nuh uh, get 404'd >:D"); + response.setBody(http::Errors::getResponseBody(response.getStatusCode())); } return (response); diff --git a/src/requests_handling/HttpResponse.cpp b/src/requests_handling/HttpResponse.cpp index 0626827..7810f18 100644 --- a/src/requests_handling/HttpResponse.cpp +++ b/src/requests_handling/HttpResponse.cpp @@ -6,7 +6,7 @@ /* By: mmoussou _protocol); } -size_t http::Response::getStatusCode(void) const +uint http::Response::getStatusCode(void) const { return (this->_status_code); } @@ -64,7 +64,7 @@ void http::Response::setProtocol(std::string const protocol) this->_protocol = protocol; } -void http::Response::setStatusCode(size_t const status_code) +void http::Response::setStatusCode(uint const status_code) { this->_status_code = status_code; this->_status_text = Errors::message[status_code]; From 0264b5616988d70aed79cfbc1e4a05673af76a20 Mon Sep 17 00:00:00 2001 From: y-syo Date: Wed, 2 Apr 2025 05:28:11 +0200 Subject: [PATCH 7/9] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D=20w?= =?UTF-8?q?ip(requests/POST):=20updating=20only=20things=20that=20does=20m?= =?UTF-8?q?ake=20sense?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- includes/requests/HttpIMessage.hpp | 8 +-- src/main.cpp | 29 +++++++-- src/requests_handling/Errors.cpp | 2 +- src/requests_handling/HttpIMessage.cpp | 6 +- src/requests_handling/HttpRequests.cpp | 61 +++++++++++++++-- src/requests_handling/HttpResponse.cpp | 4 +- upload.html | 90 ++++++++++++++++++++++++++ 7 files changed, 179 insertions(+), 21 deletions(-) create mode 100644 upload.html diff --git a/includes/requests/HttpIMessage.hpp b/includes/requests/HttpIMessage.hpp index d2c1a79..9ed38b2 100644 --- a/includes/requests/HttpIMessage.hpp +++ b/includes/requests/HttpIMessage.hpp @@ -6,7 +6,7 @@ /* By: mmoussou getHeaders(void) const; + virtual std::map getHeaders(void) const; virtual std::string getBody(void) const; - virtual void setHeaders(std::multimap const headers); + virtual void setHeaders(std::map const headers); virtual void setBody(std::string const body); virtual void addHeader(std::string const key, std::string const value); @@ -34,7 +34,7 @@ public: virtual std::string str(void) const = 0; protected: - std::multimap _headers; + std::map _headers; std::string _body; static const std::map _response_status_codes; diff --git a/src/main.cpp b/src/main.cpp index 8c0507c..c4fb958 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ /* By: mmoussou http::IMessage::getHeaders(void) const +std::map http::IMessage::getHeaders(void) const { return (this->_headers); } @@ -24,7 +24,7 @@ std::string http::IMessage::getBody(void) const return (this->_body); } -void http::IMessage::setHeaders(std::multimap const headers) +void http::IMessage::setHeaders(std::map const headers) { this->_headers = headers; } diff --git a/src/requests_handling/HttpRequests.cpp b/src/requests_handling/HttpRequests.cpp index 7b205fe..0e37862 100644 --- a/src/requests_handling/HttpRequests.cpp +++ b/src/requests_handling/HttpRequests.cpp @@ -6,7 +6,7 @@ /* By: mmoussou _method << " " << this->_target << " " << this->_protocol; response << "\r\n"; - for (std::multimap::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it) + for (std::map::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it) response << it->first << ": " << it->second << "\r\n"; response << "\r\n"; @@ -187,7 +187,6 @@ http::Response http::Get::execute(void) response.setBody(std::string((std::istreambuf_iterator(file)), std::istreambuf_iterator())); std::stringstream length; length << (file.tellg() - file_start); - std::cout << length.str() << std::endl; response.addHeader("Content-Length", length.str()); response.setProtocol(this->_protocol); @@ -345,12 +344,64 @@ void http::Post::parse(std::string const &data) //*/ } +std::string extractFilename(const std::string &header) +{ + size_t start = header.find("filename=\"") + 10; + size_t end = header.find("\"", start); + return header.substr(start, end - start); +} + +void handleMultipartData(const std::string &body, const std::string &boundary) +{ + size_t i = 0; + std::string delim = "--" + boundary; + delim.erase(delim.size() - 1); + + while ((i = body.find(delim, i)) != std::string::npos) + { + size_t start = i + delim.length(); + size_t end = body.find("\r\n\r\n", start); + + if (end != std::string::npos) + { + std::string part_header = body.substr(start, end - start); + std::cout << std::endl<< std::endl<< std::endl<< std::endl<< std::endl; + std::string part_content = body.substr(end + 4, body.find(delim, end) - end - 4); + + std::ofstream outfile(extractFilename(part_header).c_str(), std::ios::binary); + if (outfile.is_open()) + { + outfile.write(part_content.c_str(), part_content.length()); + outfile.close(); + } + else + { + std::cerr << "open failed" << std::endl; + } + } + + i += delim.length(); + } +} + http::Response http::Post::execute(void) { http::Response response; - // uh idk anymore - + try + { + handleMultipartData(this->_body, this->getHeaders()["Content-Type"].substr(this->getHeaders()["Content-Type"].find("=", this->getHeaders()["Content-Type"].find(";")) + 1)); + + response.setProtocol(this->_protocol); + response.setStatusCode(204); + } + catch (...) + { + response.setProtocol(this->_protocol); + response.setStatusCode(500); + response.addHeader("Content-Type", "text/html"); + response.setBody(http::Errors::getResponseBody(response.getStatusCode())); + } return (response); } diff --git a/src/requests_handling/HttpResponse.cpp b/src/requests_handling/HttpResponse.cpp index 7810f18..c0d91dd 100644 --- a/src/requests_handling/HttpResponse.cpp +++ b/src/requests_handling/HttpResponse.cpp @@ -6,7 +6,7 @@ /* By: mmoussou _protocol << " " << this->_status_code << " " << this->_status_text; response << "\r\n"; - for (std::multimap::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it) + for (std::map::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it) response << it->first << ": " << it->second << "\r\n"; response << "\r\n"; diff --git a/upload.html b/upload.html new file mode 100644 index 0000000..a9e575f --- /dev/null +++ b/upload.html @@ -0,0 +1,90 @@ + + + + upload + + + + + +
+
+ +

+

+
+ + + + + From 4ce004ee06fc97c511e8f3b36ef98ff80e53c0a6 Mon Sep 17 00:00:00 2001 From: y-syo Date: Tue, 8 Apr 2025 01:13:02 +0200 Subject: [PATCH 8/9] =?UTF-8?q?=E3=80=8C=F0=9F=93=9D=E3=80=8D=20doc(http):?= =?UTF-8?q?=20removed=20debug=20logs=20for=20readable=20stdout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/requests_handling/HttpRequests.cpp | 12 ++++++------ src/requests_handling/HttpResponse.cpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/requests_handling/HttpRequests.cpp b/src/requests_handling/HttpRequests.cpp index 0e37862..1a1e7dd 100644 --- a/src/requests_handling/HttpRequests.cpp +++ b/src/requests_handling/HttpRequests.cpp @@ -6,7 +6,7 @@ /* By: mmoussou _target.c_str())) throw std::runtime_error("can't remove file, FF"); response.setProtocol(this->_protocol); - response.setStatusCode(204); // this cool dude on the internet said i should not do that so i'll change it https://blog.ploeh.dk/2013/04/30/rest-lesson-learned-avoid-204-responses/ + response.setStatusCode(204); time_t now = std::time(NULL); response.addHeader("Date", std::string(std::ctime(&now))); } @@ -330,7 +330,7 @@ void http::Post::parse(std::string const &data) body_stream << line << "\n"; this->_body = body_stream.str(); - ///* + /* std::cout << "-- start-line --" << std::endl; std::cout << "method: " << this->_method << std::endl; std::cout << "target: " << this->_target << std::endl; @@ -340,8 +340,8 @@ void http::Post::parse(std::string const &data) for (std::map::const_iterator it = this->_headers.begin(); it != this->_headers.end(); ++it) std::cout << it->first << ": " << it->second << std::endl; std::cout << std::endl; - std::cout << "-- body --" << std::endl << this->_body << std::endl; - //*/ + //std::cout << "-- body --" << std::endl << this->_body << std::endl; + */ } std::string extractFilename(const std::string &header) @@ -365,7 +365,7 @@ void handleMultipartData(const std::string &body, const std::string &boundary) if (end != std::string::npos) { std::string part_header = body.substr(start, end - start); - std::cout << std::endl<< std::endl<< std::endl<< std::endl<< std::endl; + //std::cout << std::endl << std::endl << std::endl << std::endl; std::string part_content = body.substr(end + 4, body.find(delim, end) - end - 4); std::ofstream outfile(extractFilename(part_header).c_str(), std::ios::binary); diff --git a/src/requests_handling/HttpResponse.cpp b/src/requests_handling/HttpResponse.cpp index c0d91dd..9fccdb4 100644 --- a/src/requests_handling/HttpResponse.cpp +++ b/src/requests_handling/HttpResponse.cpp @@ -6,7 +6,7 @@ /* By: mmoussou _body; - std::cout << "------------ RESPONSE -------------" << std::endl << response.str(); + //std::cout << "------------ RESPONSE -------------" << std::endl << response.str(); return (response.str()); } From ebb37d80916a00b011d7838ca980c769f59430ca Mon Sep 17 00:00:00 2001 From: Malik Moussouni Date: Thu, 10 Apr 2025 12:18:48 +0200 Subject: [PATCH 9/9] =?UTF-8?q?=E3=80=8C=F0=9F=8F=97=EF=B8=8F=E3=80=8D=20w?= =?UTF-8?q?ip(http):=20work=20in=20progress,=20not=20done=20yet.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 5 +++-- src/main.cpp | 14 +++++++++++--- src/requests_handling/HttpRequests.cpp | 6 ++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index dceb576..eb79aeb 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: adjoly +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2024/10/25 16:09:27 by adjoly #+# #+# # -# Updated: 2025/02/03 16:43:32 by mmoussou ### ########.fr # +# Updated: 2025/04/10 11:52:13 by mmoussou ### ########.fr # # # # **************************************************************************** # @@ -57,6 +57,7 @@ fclean: clean @rm -Rf $(OBJSDIR) @printf "$(RED)「🗑️」 fclean($(NAME)): program deleted\n" -re: fclean all +re: fclean + @$(MAKE) -s all .PHONY: clean fclean all re diff --git a/src/main.cpp b/src/main.cpp index c4fb958..b8a6ace 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ /* By: mmoussou _body, this->getHeaders()["Content-Type"].substr(this->getHeaders()["Content-Type"].find("=", this->getHeaders()["Content-Type"].find(";")) + 1)); response.setProtocol(this->_protocol); - response.setStatusCode(204); + response.setStatusCode(200); + response.addHeader("Content-Type", "text/html"); + response.setBody(http::Errors::getResponseBody(response.getStatusCode())); } catch (...) {