diff --git a/exemples/test.toml b/exemples/test.toml index 79a5a77..760746f 100644 --- a/exemples/test.toml +++ b/exemples/test.toml @@ -11,8 +11,8 @@ port = 8080 402 = "uwu.html" [server.location./] -methods = { "GET" } -root = "/home/adjoly" +methods = { "GET", "POST" } +root = "./exemples/webpage" dirlist = true client_max_body_size = "10M" index = "index.html" diff --git a/catually.png b/exemples/webpage/catually.png similarity index 100% rename from catually.png rename to exemples/webpage/catually.png diff --git a/index.html b/exemples/webpage/index.html similarity index 100% rename from index.html rename to exemples/webpage/index.html diff --git a/not_found.html b/exemples/webpage/not_found.html similarity index 100% rename from not_found.html rename to exemples/webpage/not_found.html diff --git a/exemples/webpage/omg.html b/exemples/webpage/omg.html new file mode 100644 index 0000000..820a075 --- /dev/null +++ b/exemples/webpage/omg.html @@ -0,0 +1,20 @@ + + + + + + POST Request Test + + +

Test POST Request

+
+ + +
+ + +
+ +
+ + diff --git a/exemples/webpage/test.py b/exemples/webpage/test.py new file mode 100755 index 0000000..e8b3c24 --- /dev/null +++ b/exemples/webpage/test.py @@ -0,0 +1,30 @@ +#!/nix/store/kjvgj2n3yn70hmjifg6y0bk9m4rf7jba-python3-3.12.10/bin/python3 + +import cgi +import cgitb + +# Enable error reporting +cgitb.enable() + +print("Content-Type: text/html") # HTML is following +print() # blank line, end of headers + +form = cgi.FieldStorage() + +# Get data from fields +name = form.getvalue("name") +email = form.getvalue("email") + +print(f""" + + + + POST Request Received + + +

POST Request Received

+

Name: {name}

+

Email: {email}

+ + +""") diff --git a/includes/server/CgiIn.hpp b/includes/server/CgiIn.hpp index 164974b..81e08ce 100644 --- a/includes/server/CgiIn.hpp +++ b/includes/server/CgiIn.hpp @@ -6,7 +6,7 @@ /* By: adjoly +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 18:14:45 by adjoly #+# #+# */ -/* Updated: 2025/05/27 18:59:29 by adjoly ### ########.fr */ +/* Updated: 2025/05/29 11:34:40 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,6 +14,7 @@ #include "server/AResource.hpp" #include +#include #include namespace webserv { @@ -34,7 +35,10 @@ class CgiIn : public AClientResource { void process(void) { _processed = true; - // TODO: send the body + ssize_t bytes_written = write(_fd, _body.c_str(), _body.size()); + if (bytes_written == -1) { + throw std::runtime_error("write error could not write body to cgi stdin"); + } } clientResType type(void) const { return CGI_IN; } short event(void) const { return POLLIN; } diff --git a/src/requests_handling/Cgi.cpp b/src/requests_handling/Cgi.cpp index 3fb4bc8..34d329a 100644 --- a/src/requests_handling/Cgi.cpp +++ b/src/requests_handling/Cgi.cpp @@ -6,7 +6,7 @@ /* By: gadelbes +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/24 13:46:34 by gadelbes #+# #+# */ -/* Updated: 2025/05/27 22:26:52 by adjoly ### ########.fr */ +/* Updated: 2025/05/29 11:30:07 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/src/requests_handling/requestImplementation/Get.cpp b/src/requests_handling/requestImplementation/Get.cpp index 82ef408..04629dd 100644 --- a/src/requests_handling/requestImplementation/Get.cpp +++ b/src/requests_handling/requestImplementation/Get.cpp @@ -6,7 +6,7 @@ /* By: adjoly +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/30 09:40:16 by adjoly #+# #+# */ -/* Updated: 2025/05/28 11:28:01 by adjoly ### ########.fr */ +/* Updated: 2025/05/29 11:44:03 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ @@ -91,28 +91,6 @@ void Get::parse(std::string const &data) { pfd.fd = _cgi->getId(); server::PfdManager::append(pfd, server::RES); } - - /* - std::cout << "-- start-line --" << std::endl; - std::cout << "method: " << this->_method << std::endl; - std::cout << "target: " << this->_target << std::You can use every macro and -define like FD_SET, FD_CLR, FD_ISSET and, FD_ZERO (understanding what they do -and how they work is very useful). • A request to your server should never hang -indefinitely. • Your server must be compatible with standard web browsers of -your choice. • We will consider that NGINX is HTTP 1.1 compliant and may be used -to compare headers and answer behaviors. • Your HTTP response status codes must -be accurate. • Your server must have default error pages if none are provided. -• You can’t use fork for anything other than CGI (like PHP, or Python, and so -forth). • You must be able to serve a fully static website. • Clients must be -able to upload files. • You need at least the GET, POST, and DELETE methodendl; - 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; - */ } char isDirectory(const std::string &path) { diff --git a/src/requests_handling/requestImplementation/Post.cpp b/src/requests_handling/requestImplementation/Post.cpp index ecf32a1..a2822cc 100644 --- a/src/requests_handling/requestImplementation/Post.cpp +++ b/src/requests_handling/requestImplementation/Post.cpp @@ -6,7 +6,7 @@ /* By: adjoly +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/30 09:50:20 by adjoly #+# #+# */ -/* Updated: 2025/05/28 11:28:35 by adjoly ### ########.fr */ +/* Updated: 2025/05/29 11:44:46 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,6 +19,7 @@ #include #include #include +#include using namespace webserv::http; @@ -57,20 +58,29 @@ void Post::parse(std::string const &data) { this->_body = body_stream.str(); _url = new URL(_target); - std::cout << *_url << std::endl; - /* - 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; - */ + std::string targ = _target; + + if (targ[targ.length() - 1] == '/') { + targ += _route->getIndex(); + } + + if (_route->isCgi(targ)) { + _log->info("cgi added"); + try { + _cgi = new server::Cgi(this, _route); + } catch (std::exception &e) { + _log->error(e.what()); + _method = "500"; + return; + } + server::ResourceManager::append(_cgi); + struct pollfd pfd; + pfd.events = _cgi->event(); + pfd.revents = 0; + pfd.fd = _cgi->getId(); + server::PfdManager::append(pfd, server::RES); + } } std::string Post::extractFilename(const std::string &header) { @@ -108,9 +118,58 @@ void Post::handleMultipartData(const std::string &body, } } +Response parseCgiOut(std::string cgi_str) { + Response response; + std::istringstream stream(cgi_str); + std::string line; + + response.setStatusCode(200); + while (std::getline(stream, line) && line != "") { + 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); + response.addHeader(key, value); + } + } + std::ostringstream body_stream; + while (std::getline(stream, line)) + body_stream << line << "\n"; + response.setBody(body_stream.str()); + + if (response.getHeader("Content-Length") == "") { + std::stringstream length; + length << response.getBody().length(); + response.addHeader("Content-Length", length.str()); + } + return response; +} + + Response Post::execute(void) { http::Response response; + if (_cgi != not_nullptr) { + if (_method == "500") { + response.setStatusCode(500); + response.addHeader("Content-Type", "text/html"); + response.setBody(http::Errors::getResponseBody( + response.getStatusCode(), + _srv->getErrorPage(response.getStatusCode()))); + server::PfdManager::remove(_cgi->getId()); + server::ResourceManager::remove(_cgi->getId()); + _cgi = not_nullptr; + return response; + } + std::string str = static_cast(_cgi)->str(); + response = parseCgiOut(str); + response.setProtocol(_protocol); + server::PfdManager::remove(_cgi->getId()); + server::ResourceManager::remove(_cgi->getId()); + _cgi = not_nullptr; + return response; + } + try { handleMultipartData( this->_body, diff --git a/test.py b/test.py deleted file mode 100755 index 7b050f5..0000000 --- a/test.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/nix/store/kjvgj2n3yn70hmjifg6y0bk9m4rf7jba-python3-3.12.10/bin/python3 - -# Import modules for CGI handling -import cgi -import cgitb - -# Enable error reporting -cgitb.enable() - -# Create instance of FieldStorage -form = cgi.FieldStorage() - -# Set the content type to HTML -print("Content-Type: text/html") - -print("") - -# Output a simple HTML page -print("") -print("") -print("CGI Script Test") -print("") -print("") -print("

CGI Script is Running

") -print("

Your web server is working correctly!

") -print("") -print("")