From 2cacdbc773a537c827a1ae73a0c16616924c61ce Mon Sep 17 00:00:00 2001 From: deer Date: Thu, 29 Jun 2023 00:21:32 +0900 Subject: [PATCH 1/6] refacotr: change HttpResponse headers type from vector> to map --- playground/tkg/Design1/src/HttpResponse.cpp | 17 ++++++----------- playground/tkg/Design1/src/HttpResponse.hpp | 4 ++-- playground/tkg/Design1/test/e2e_test.cpp | 6 ++++-- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/playground/tkg/Design1/src/HttpResponse.cpp b/playground/tkg/Design1/src/HttpResponse.cpp index 9d5382f..c5b16f6 100644 --- a/playground/tkg/Design1/src/HttpResponse.cpp +++ b/playground/tkg/Design1/src/HttpResponse.cpp @@ -24,7 +24,6 @@ void HttpResponse::setStatusAndReason(const int status, const std::string &reaso reason_phrase_ = reason; } - void HttpResponse::setContentType(const std::string &path) { std::string ext = getExtension(path); if (ext == "") return; @@ -36,18 +35,14 @@ void HttpResponse::appendBody(const char *str, size_t size) { body_.insert(body_ void HttpResponse::appendBody(const std::string &str) { body_.insert(body_.end(), str.begin(), str.end()); } - -void HttpResponse::appendHeader(const std::string &key, const std::string &value) { - headers.push_back(header(key, value)); -} +void HttpResponse::appendHeader(const std::string &key, const std::string &value) { headers_[key] = value; } const std::vector &HttpResponse::getBody() const { return body_; } bool HttpResponse::hasHeader(const std::string &target_name) { - for (std::vector
::const_iterator itr = headers.cbegin(); itr != headers.cend(); itr++) { - if (itr->first == target_name) return true; - } - return false; + t_headers::iterator key = headers_.find(target_name); + if (key == headers_.end()) return false; + return true; } void HttpResponse::createResponse() { @@ -61,7 +56,7 @@ void HttpResponse::createResponse() { // status-line ss << "HTTP/1.1 " << status_ << " " << conf_->cache_.statusMsg_[status_] << CRLF; // header-fields - for (std::vector
::const_iterator itr = headers.cbegin(); itr != headers.cend(); itr++) { + for (t_headers::const_iterator itr = headers_.cbegin(); itr != headers_.cend(); itr++) { ss << itr->first << ": " << itr->second << CRLF; } ss << CRLF; @@ -102,7 +97,7 @@ void HttpResponse::refresh() { status_ = 0; body_.clear(); response_.clear(); - headers.clear(); + headers_.clear(); sending_response_size_ = 0; response_size_ = 0; } diff --git a/playground/tkg/Design1/src/HttpResponse.hpp b/playground/tkg/Design1/src/HttpResponse.hpp index 1859523..781d06c 100644 --- a/playground/tkg/Design1/src/HttpResponse.hpp +++ b/playground/tkg/Design1/src/HttpResponse.hpp @@ -15,7 +15,7 @@ class EventManager; class HttpResponse { public: - typedef std::pair header; + typedef std::map t_headers; enum State { Free, Sending, End }; HttpResponse(int fd, int port, Config *conf) @@ -50,7 +50,7 @@ class HttpResponse { Config *conf_; std::vector body_; std::vector response_; - std::vector
headers; + t_headers headers_; int response_size_; int sending_response_size_; }; diff --git a/playground/tkg/Design1/test/e2e_test.cpp b/playground/tkg/Design1/test/e2e_test.cpp index 7f49a61..4b3ae0a 100644 --- a/playground/tkg/Design1/test/e2e_test.cpp +++ b/playground/tkg/Design1/test/e2e_test.cpp @@ -51,7 +51,8 @@ TEST(E2E, CGIClientRedirect) { std::cerr << res << std::endl; // ASSERT_TRUE(includes(res, "HTTP/1.1 200 OK")); - ASSERT_TRUE(includes(res, "HTTP/1.1 302 Found\nlocation: http://example.com")); + ASSERT_TRUE(includes(res, "HTTP/1.1 302 Found\n")); + ASSERT_TRUE(includes(res, "location: http://example.com")); } TEST(E2E, CGIClientRedirectWithDoc) { @@ -81,7 +82,8 @@ TEST(E2E, CGILocalRedirectToClientRedirect) { std::string res = sendRequest(host, port, method, path, body, headers); std::cerr << res << std::endl; - ASSERT_TRUE(includes(res, "HTTP/1.1 302 Found\nlocation: http://example.com")); + ASSERT_TRUE(includes(res, "HTTP/1.1 302 Found\n")); + ASSERT_TRUE(includes(res, "location: http://example.com")); } TEST(E2E, Get) { From f8b9791005bd9367061d880113f4487498863773 Mon Sep 17 00:00:00 2001 From: deer Date: Thu, 29 Jun 2023 02:43:34 +0900 Subject: [PATCH 2/6] fix: CGI Response handling --- .../cgi-bin/script/cgi_ClientRedirWithDoc.cpp | 2 +- .../tkg/Design1/cgi-bin/script/cgi_meta.cpp | 2 +- .../tkg/Design1/src/Observee/CGI/CGI.cpp | 236 ++++++++---------- .../tkg/Design1/src/Observee/CGI/CGI.hpp | 22 +- 4 files changed, 120 insertions(+), 142 deletions(-) diff --git a/playground/tkg/Design1/cgi-bin/script/cgi_ClientRedirWithDoc.cpp b/playground/tkg/Design1/cgi-bin/script/cgi_ClientRedirWithDoc.cpp index cb0b4f0..5dbef4d 100644 --- a/playground/tkg/Design1/cgi-bin/script/cgi_ClientRedirWithDoc.cpp +++ b/playground/tkg/Design1/cgi-bin/script/cgi_ClientRedirWithDoc.cpp @@ -6,8 +6,8 @@ int main() { std::string input; std::cin >> input; - std::cout << "Location:http://example.com" << std::endl; std::cout << "Status:301 CRWD(CGI)" << std::endl; + std::cout << "Location:http://example.com" << std::endl; std::cout << "Content-Type:text/html" << std::endl; std::cout << std::endl; std::stringstream ss; diff --git a/playground/tkg/Design1/cgi-bin/script/cgi_meta.cpp b/playground/tkg/Design1/cgi-bin/script/cgi_meta.cpp index 0363c8c..4870558 100644 --- a/playground/tkg/Design1/cgi-bin/script/cgi_meta.cpp +++ b/playground/tkg/Design1/cgi-bin/script/cgi_meta.cpp @@ -6,8 +6,8 @@ int main() { extern char **environ; std::string input; std::cin >> input; - std::cout << "Content-Type:text/plain" << std::endl; std::cout << "Status:200 " << std::endl; + std::cout << "Content-Type:text/plain" << std::endl; std::cout << std::endl; std::cout << input << std::endl; std::cout << "AUTH_TYPE: " << getenv("AUTH_TYPE") << std::endl; diff --git a/playground/tkg/Design1/src/Observee/CGI/CGI.cpp b/playground/tkg/Design1/src/Observee/CGI/CGI.cpp index 23d1ef4..fccb689 100644 --- a/playground/tkg/Design1/src/Observee/CGI/CGI.cpp +++ b/playground/tkg/Design1/src/Observee/CGI/CGI.cpp @@ -44,194 +44,164 @@ void CGI::terminate() { std::pair getHeaderField(std::string &field) { std::stringstream ss(field); std::string name, value; - if (field.find(':') == std::string::npos) throw std::runtime_error("invalid header field"); + if (field.find(':') == std::string::npos) throw InternalServerErrorException("invalid header field"); std::getline(ss, name, ':'); + toLower(name); std::getline(ss, value); trimOws(value); return std::pair(name, value); } -void CGI::parseDocRes(std::vector &lines) { - DEBUG_PUTS("parseDocRes"); - std::size_t i = 0; - while (i < lines.size() && lines[i] != "") { - t_field field = getHeaderField(lines[i]); - if (i == 0) { - response_->appendHeader("content-type", field.second); - } else if (i == 1 && field.first == "Status") { - std::istringstream iss(field.second); +void CGI::processDocRes(std::string &body) { + DEBUG_PUTS("processDocRes"); + for (HttpResponse::t_headers::const_iterator itr = headers_.cbegin(); itr != headers_.cend(); itr++) { + if (itr->first == "status") { + std::istringstream iss(itr->second); std::string status; std::string reason; iss >> status; iss.ignore(); - getline(iss, reason, '\n'); + getline(iss, reason); response_->setStatusAndReason(std::atoi(status.c_str()), reason); } else { - response_->appendHeader(toLower(field.first), field.second); + response_->appendHeader(itr->first, itr->second); } - i++; - } - // parse body - i++; - for (; i < lines.size(); i++) { - response_->appendBody(lines[i] + "\n"); } - return; + response_->appendBody(body); + em_->registerWriteEvent(parent_->id_); + shutdown(); } -void CGI::parseClientRedirect(std::vector &lines) { - DEBUG_PUTS("parseClientRedirect"); - t_field field = getHeaderField(lines[0]); - response_->appendHeader("location", field.second); +void CGI::processClientRedirect() { + DEBUG_PUTS("processClientRedirect"); + for (HttpResponse::t_headers::const_iterator itr = headers_.cbegin(); itr != headers_.cend(); itr++) { + response_->appendHeader(itr->first, itr->second); + } response_->setStatusAndReason(302, ""); + em_->registerWriteEvent(parent_->id_); + shutdown(); } -void CGI::parseClientRedirectWithDoc(std::vector &lines) { - DEBUG_PUTS("parseClientRedirectWithDoc"); - t_field field = getHeaderField(lines[0]); - response_->appendHeader("location", field.second); - field = getHeaderField(lines[1]); - response_->setStatusAndReason(std::atoi(field.second.c_str()), field.second.substr(4)); - field = getHeaderField(lines[2]); - response_->appendHeader("content-type", field.second); - std::size_t i = 3; - while (i < lines.size() && lines[i] != "") { - field = getHeaderField(lines[i]); - response_->appendHeader(toLower(field.first), field.second); - i++; - } - if (lines[i] == "") i++; - while (i < lines.size() && lines[i] != "") { - response_->appendBody(lines[i] + "\n"); - i++; +void CGI::processClientRedirectWithDoc(std::string &body) { + DEBUG_PUTS("processClientRedirectWithDoc"); + for (HttpResponse::t_headers::const_iterator itr = headers_.cbegin(); itr != headers_.cend(); itr++) { + if (itr->first == "status") { + std::istringstream iss(itr->second); + std::string status; + std::string reason; + iss >> status; + iss.ignore(); + getline(iss, reason); + response_->setStatusAndReason(std::atoi(status.c_str()), reason); + } else { + response_->appendHeader(itr->first, itr->second); + } } + response_->appendBody(body); + em_->registerWriteEvent(parent_->id_); + shutdown(); } -void CGI::parseLocalRedirect(std::vector &lines) { - DEBUG_PUTS("parseLocalRedirect"); - t_field field = getHeaderField(lines[0]); +void CGI::processLocalRedirect() { + DEBUG_PUTS("processLocalRedirect"); + std::string loc_value = headers_["location"]; try { - const size_t fragment_pos = field.second.find("#"); + const size_t fragment_pos = loc_value.find("#"); std::string fragment; if (fragment_pos != std::string::npos) { - fragment = field.second.substr(fragment_pos + 1); + fragment = loc_value.substr(fragment_pos + 1); } - URI *uri = URI::parseRequestURI(field.second.substr(0, fragment_pos)); + URI *uri = URI::parseRequestURI(loc_value.substr(0, fragment_pos)); delete request_->request_target_; request_->request_target_ = uri; request_->body_.clear(); dynamic_cast(parent_)->initExtension(); + ConnectionSocket *parent = dynamic_cast(parent_); + shutdown(); + parent->process(); } catch (std::runtime_error &e) { - throw(InternalServerErrorException("CGI response URI is invalid")); + throw InternalServerErrorException("CGI Local Redirect response URI is invalid"); } } -bool CGI::isDocRes(std::vector &lines) { - try { - std::size_t i = 0; - while (i < lines.size() && lines[i] != "") { - t_field field = getHeaderField(lines[i]); - if (i == 0 && field.first != "Content-Type") return false; - if (i == 1 && field.first == "Status" && !CGIValidation::isStatusHeaderValue(field.second)) return false; - i++; - } - } catch (std::runtime_error &e) { - std::cout << e.what() << std::endl; +bool CGI::isDocRes() { + if (headers_.find("content-type") == headers_.end()) return false; + if (!CGIValidation::isMediaType(headers_["content-type"])) return false; + if (headers_.find("status") != headers_.end() && !CGIValidation::isStatusHeaderValue(headers_["status"])) return false; - } + if (headers_.find("location") != headers_.end()) return false; return true; } -bool CGI::isLocalRedirectRes(std::vector &lines) { - if (lines.size() != 2) return false; - try { - t_field field = getHeaderField(lines[0]); - if (field.first != "Location") return false; - if (!CGIValidation::isAbsPath(field.second.c_str())) return false; - if (lines[1] != "") return false; - } catch (std::runtime_error &e) { - std::cout << e.what() << std::endl; - return false; - } +bool CGI::isLocalRedirectRes() { + if (headers_.size() != 1) return false; + if (headers_.find("location") == headers_.end()) return false; + if (!CGIValidation::isAbsPath(headers_["location"].c_str())) return false; + return true; } -bool CGI::isClientRedirectRes(std::vector &lines) { - if (lines.size() != 2) return false; - try { - t_field filed = getHeaderField(lines[0]); - if (filed.first != "Location") return false; - if (!CGIValidation::isAbsURI(filed.second)) return false; - if (lines[1] != "") return false; - } catch (std::runtime_error &e) { - std::cout << e.what() << std::endl; - return false; - } +bool CGI::isClientRedirectRes() { + if (headers_.find("location") == headers_.end()) return false; + if (!CGIValidation::isAbsURI(headers_["location"])) return false; + if (headers_.find("content-type") != headers_.end()) return false; + if (headers_.find("status") != headers_.end()) return false; return true; } -bool CGI::isClientRedirectWithDocRes(std::vector &lines) { - if (lines.size() < 3) return false; - try { - t_field field = getHeaderField(lines[0]); - if (field.first != "Location" || !CGIValidation::isAbsURI(field.second)) return false; - field = getHeaderField(lines[1]); - if (field.first != "Status" || !CGIValidation::isStatusHeaderValue(field.second)) return false; - field = getHeaderField(lines[2]); - if (field.first != "Content-Type" || !CGIValidation::isMediaType(field.second)) return false; - std::size_t i = 3; - while (i < lines.size() && lines[i] != "") { - field = getHeaderField(lines[i]); - i++; - } - if (i == lines.size() && lines[i - 1] != "") return false; - } catch (std::runtime_error &e) { - std::cout << e.what() << std::endl; - return false; +bool CGI::isClientRedirectWithDocRes() { + if (headers_.find("location") == headers_.end()) return false; + if (!CGIValidation::isAbsURI(headers_["location"])) return false; + if (headers_.find("content-type") == headers_.end()) return false; + if (!CGIValidation::isMediaType(headers_["content-type"])) return false; + if (headers_.find("status") != headers_.end()) { + if (!CGIValidation::isStatusHeaderValue(headers_["status"])) return false; } return true; } -CGI::Type CGI::getResponseType(std::vector &lines) { - if (isDocRes(lines)) { +CGI::Type CGI::getResponseType() { + if (isDocRes()) { return CGI::Doc; - } else if (isLocalRedirectRes(lines)) { + } else if (isLocalRedirectRes()) { return CGI::LocalRedir; - } else if (isClientRedirectRes(lines)) { + } else if (isClientRedirectRes()) { return CGI::ClientRedir; - } else if (isClientRedirectWithDocRes(lines)) { + } else if (isClientRedirectWithDocRes()) { return CGI::ClientRedirWithDoc; } return CGI::Error; } -void CGI::parseCGIResponse() { - std::vector lines = CGIValidation::extractLines(recieved_data_); - CGI::Type type = getResponseType(lines); +void CGI::parseHeaders(std::string &headers) { + std::vector fields = CGIValidation::extractLines(headers); + std::vector::size_type i = 0; + while (i < fields.size() && fields[i] != "") { + t_field field = getHeaderField(fields[i]); + headers_[field.first] = field.second; + i++; + } +} + +void CGI::handleCGIResponse() { + DEBUG_PRINTF("CGI LAST RESULT: '%s'\n", escape(recieved_data_).c_str()); + std::size_t nlnl_pos = recieved_data_.find("\n\n"); + if (nlnl_pos == std::string::npos) + throw InternalServerErrorException("CGI response is invalid(no end NL of headers)"); + std::string headers = recieved_data_.substr(0, nlnl_pos); + std::string body = recieved_data_.substr(recieved_data_.find("\n\n") + 2); + parseHeaders(headers); + CGI::Type type = getResponseType(); if (type == CGI::Error) { - response_->setStatusAndReason(500, ""); + throw InternalServerErrorException("CGI response is invalid(no end NL of headers)"); } else if (type == CGI::Doc) { - parseDocRes(lines); + processDocRes(body); } else if (type == CGI::LocalRedir) { - DEBUG_PRINTF("CGI LAST RESULT: '%s'\n", escape(recieved_data_).c_str()); - try { - parseLocalRedirect(lines); - ConnectionSocket *parent = dynamic_cast(parent_); - shutdown(); - parent->process(); - } catch (HttpException &e) { - response_->setStatusAndReason(e.statusCode(), ""); - type = CGI::Error; - } + processLocalRedirect(); } else if (type == CGI::ClientRedir) { - parseClientRedirect(lines); + processClientRedirect(); } else if (type == CGI::ClientRedirWithDoc) { - parseClientRedirectWithDoc(lines); - } - if (type != CGI::LocalRedir) { - DEBUG_PRINTF("CGI LAST RESULT: '%s'\n", escape(recieved_data_).c_str()); - em_->registerWriteEvent(parent_->id_); - shutdown(); + processClientRedirectWithDoc(body); } } @@ -244,13 +214,19 @@ void CGI::notify(struct kevent ev) { int res = read(id_, &buff[0], FILE_READ_SIZE); if (res == -1) { - response_->setStatusAndReason(501, ""); + response_->setStatusAndReason(500, ""); em_->registerWriteEvent(parent_->id_); shutdown(); return; } else if (res == 0) { response_->setStatusAndReason(200, ""); - parseCGIResponse(); + try { + handleCGIResponse(); + } catch (HttpException &e) { + response_->setStatusAndReason(e.statusCode(), ""); + em_->registerWriteEvent(parent_->id_); + shutdown(); + } } else { std::cout << "CGI read res: " << res << std::endl; buff[res] = '\0'; @@ -269,7 +245,7 @@ void CGI::notify(struct kevent ev) { int res = write(id_, response + sending_size_, size); if (res == -1) { perror("sendto"); - response_->setStatusAndReason(501, ""); + response_->setStatusAndReason(500, ""); em_->registerWriteEvent(parent_->id_); shutdown(); return; diff --git a/playground/tkg/Design1/src/Observee/CGI/CGI.hpp b/playground/tkg/Design1/src/Observee/CGI/CGI.hpp index 90e9a28..f32ba0a 100644 --- a/playground/tkg/Design1/src/Observee/CGI/CGI.hpp +++ b/playground/tkg/Design1/src/Observee/CGI/CGI.hpp @@ -20,21 +20,23 @@ class CGI : public Observee { void notify(struct kevent ev); void shutdown(); void terminate(); - void parseCGIResponse(); - Type getResponseType(std::vector &lines); - bool isDocRes(std::vector &line); - bool isLocalRedirectRes(std::vector &line); - bool isClientRedirectRes(std::vector &line); - bool isClientRedirectWithDocRes(std::vector &line); - void parseDocRes(std::vector &lines); - void parseClientRedirect(std::vector &lines); - void parseLocalRedirect(std::vector &lines); - void parseClientRedirectWithDoc(std::vector &lines); + void handleCGIResponse(); + void parseHeaders(std::string &headers); + Type getResponseType(); + bool isDocRes(); + bool isLocalRedirectRes(); + bool isClientRedirectRes(); + bool isClientRedirectWithDocRes(); + void processDocRes(std::string &body); + void processClientRedirect(); + void processLocalRedirect(); + void processClientRedirectWithDoc(std::string &body); private: pid_t pid_; HttpRequest *request_; HttpResponse *response_; + HttpResponse::t_headers headers_; std::string recieved_data_; std::size_t sending_size_; std::size_t recieved_size_; From aae137c04b1115565ccdd0a9d0f2be4490a66e3f Mon Sep 17 00:00:00 2001 From: deer Date: Thu, 29 Jun 2023 03:01:17 +0900 Subject: [PATCH 3/6] fix: client.py bug --- playground/tkg/Design1/test/client.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/playground/tkg/Design1/test/client.py b/playground/tkg/Design1/test/client.py index ca7e706..b49842a 100755 --- a/playground/tkg/Design1/test/client.py +++ b/playground/tkg/Design1/test/client.py @@ -34,6 +34,7 @@ def send_http_request(host, port, method, path, body, headers): body = argv[5] headers = dict() for h in argv[6:]: - pair = h.split(":") - headers[pair[0]] = pair[1] + name = h[:h.find(":")] + value = h[h.find(":")+1:] + headers[name] = value send_http_request(host, port, method, path, body, headers) \ No newline at end of file From a0b4cb2814ea8e88c28ffad53d8cbaec2fb2d184 Mon Sep 17 00:00:00 2001 From: deer Date: Thu, 29 Jun 2023 03:02:19 +0900 Subject: [PATCH 4/6] feat: change to directory where CGI script files exists in child process --- .../tkg/Design1/cgi-bin/script/cgi_getCWD.cpp | 18 ++++++++++++++++++ .../tkg/Design1/src/Observee/CGI/CGI.cpp | 7 ++++--- .../tkg/Design1/src/Observee/CGI/CGIInfo.cpp | 2 ++ .../tkg/Design1/src/Observee/CGI/CGIInfo.hpp | 1 + .../tkg/Design1/src/Observee/CGI/helper.cpp | 2 +- .../Design1/src/Observee/ConnectionSocket.cpp | 7 +++++++ playground/tkg/Design1/test/e2e_test.cpp | 13 +++++++++++++ 7 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 playground/tkg/Design1/cgi-bin/script/cgi_getCWD.cpp diff --git a/playground/tkg/Design1/cgi-bin/script/cgi_getCWD.cpp b/playground/tkg/Design1/cgi-bin/script/cgi_getCWD.cpp new file mode 100644 index 0000000..25a2d42 --- /dev/null +++ b/playground/tkg/Design1/cgi-bin/script/cgi_getCWD.cpp @@ -0,0 +1,18 @@ +#include + +#include +#include + +int main() { + std::string input; + std::cin >> input; + std::cout << "Content-Type:text/html" << std::endl; + std::cout << std::endl; + + std::stringstream ss; + char cwd[1028]; + getcwd(cwd, 1028); + ss << input << std::endl; + ss << cwd << std::endl; + std::cout << ss.str(); +} \ No newline at end of file diff --git a/playground/tkg/Design1/src/Observee/CGI/CGI.cpp b/playground/tkg/Design1/src/Observee/CGI/CGI.cpp index fccb689..03ba914 100644 --- a/playground/tkg/Design1/src/Observee/CGI/CGI.cpp +++ b/playground/tkg/Design1/src/Observee/CGI/CGI.cpp @@ -31,8 +31,8 @@ void CGI::shutdown() { em_->deleteTimerEvent(id_); kill(pid_, SIGTERM); waitpid(pid_, &status, 0); - em_->remove(std::pair(id_, FD)); if (status != 0) response_->setStatusAndReason(500, ""); + em_->remove(std::pair(id_, FD)); } void CGI::terminate() { @@ -48,7 +48,7 @@ std::pair getHeaderField(std::string &field) { std::getline(ss, name, ':'); toLower(name); std::getline(ss, value); - trimOws(value); + value = trimOws(value); return std::pair(name, value); } @@ -193,7 +193,7 @@ void CGI::handleCGIResponse() { parseHeaders(headers); CGI::Type type = getResponseType(); if (type == CGI::Error) { - throw InternalServerErrorException("CGI response is invalid(no end NL of headers)"); + throw InternalServerErrorException("CGI response is invalid"); } else if (type == CGI::Doc) { processDocRes(body); } else if (type == CGI::LocalRedir) { @@ -223,6 +223,7 @@ void CGI::notify(struct kevent ev) { try { handleCGIResponse(); } catch (HttpException &e) { + DEBUG_PUTS(e.what()); response_->setStatusAndReason(e.statusCode(), ""); em_->registerWriteEvent(parent_->id_); shutdown(); diff --git a/playground/tkg/Design1/src/Observee/CGI/CGIInfo.cpp b/playground/tkg/Design1/src/Observee/CGI/CGIInfo.cpp index 2add2f2..5e434f0 100644 --- a/playground/tkg/Design1/src/Observee/CGI/CGIInfo.cpp +++ b/playground/tkg/Design1/src/Observee/CGI/CGIInfo.cpp @@ -22,6 +22,8 @@ std::string getScriptName(const std::string &path, const std::string &ext) { return ""; } +std::string CGIInfo::getCGIWorkingDirectory() { return script_name_.substr(0, script_name_.rfind("/")); } + std::string getPathInfo(const std::string &path, const std::string &ext) { std::size_t pos = path.find(ext); while (pos != std::string::npos) { diff --git a/playground/tkg/Design1/src/Observee/CGI/CGIInfo.hpp b/playground/tkg/Design1/src/Observee/CGI/CGIInfo.hpp index 14a4ff2..beb8137 100644 --- a/playground/tkg/Design1/src/Observee/CGI/CGIInfo.hpp +++ b/playground/tkg/Design1/src/Observee/CGI/CGIInfo.hpp @@ -25,6 +25,7 @@ struct CGIInfo { std::string extension_var_name_; void setEnv(std::vector &env); + std::string getCGIWorkingDirectory(); }; std::string getPathInfo(const std::string &path, const std::string &ext); diff --git a/playground/tkg/Design1/src/Observee/CGI/helper.cpp b/playground/tkg/Design1/src/Observee/CGI/helper.cpp index 9f7c40a..adb345f 100644 --- a/playground/tkg/Design1/src/Observee/CGI/helper.cpp +++ b/playground/tkg/Design1/src/Observee/CGI/helper.cpp @@ -105,7 +105,7 @@ bool isPrintable(const char c) { bool isMediaType(std::string &raw_media) { std::string media = raw_media.substr(0, raw_media.find(";")); - trimOws(media); + media = trimOws(media); toLower(media); std::size_t pos = media.find("/"); if (pos == std::string::npos) return false; diff --git a/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp b/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp index 759e63f..a8455df 100644 --- a/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp +++ b/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp @@ -78,6 +78,13 @@ void ConnectionSocket::execCGI(const std::string &path) { em_->terminateAll(); std::vector env; info.setEnv(env); + std::string cwd = info.getCGIWorkingDirectory(); + if (chdir(cwd.c_str()) == -1) { + perror("chdir"); + close(fd[1]); + deleteEnv(env); + exit(1); + } argv[0] = const_cast(info.script_name_.c_str()); if (dup2(fd[1], STDIN_FILENO) == -1) { perror("dup2"); diff --git a/playground/tkg/Design1/test/e2e_test.cpp b/playground/tkg/Design1/test/e2e_test.cpp index 4b3ae0a..6d650f4 100644 --- a/playground/tkg/Design1/test/e2e_test.cpp +++ b/playground/tkg/Design1/test/e2e_test.cpp @@ -25,6 +25,19 @@ TEST(E2E, CGIDoc) { ASSERT_TRUE(includes(res, "CGI Response \n")); } +TEST(E2E, CGI_CWD) { + std::string host = "localhost"; + std::string port = "80"; + std::string method = "GET"; + std::string path = "/cgi-bin/cgi_getCWD.cgi?query"; + std::string body = ""; + std::string headers = "Host: localhost;Content-Length:0;Date: Wed, 16 Oct 2019 07:28:00 GMT"; + std::string res = sendRequest(host, port, method, path, body, headers); + + // ASSERT_TRUE(includes(res, "HTTP/1.1 200 OK")); + ASSERT_TRUE(includes(res, "/playground/tkg/Design1/cgi-bin\n")); +} + TEST(E2E, CGILocalRedirect) { std::string host = "localhost"; std::string port = "80"; From c1c0d6d75872f995db894049e0e8b581dcfab16c Mon Sep 17 00:00:00 2001 From: deer Date: Fri, 7 Jul 2023 14:29:02 +0900 Subject: [PATCH 5/6] delete: deleteEnv() --- playground/tkg/Design1/src/Observee/ConnectionSocket.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp b/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp index a8455df..be75892 100644 --- a/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp +++ b/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp @@ -82,29 +82,25 @@ void ConnectionSocket::execCGI(const std::string &path) { if (chdir(cwd.c_str()) == -1) { perror("chdir"); close(fd[1]); - deleteEnv(env); exit(1); } argv[0] = const_cast(info.script_name_.c_str()); if (dup2(fd[1], STDIN_FILENO) == -1) { perror("dup2"); close(fd[1]); - deleteEnv(env); exit(1); } if (dup2(fd[1], STDOUT_FILENO) == -1) { perror("dup2"); close(fd[1]); - deleteEnv(env); exit(1); } close(fd[1]); if (execve(info.script_name_.c_str(), argv, &env[0]) == -1) { perror("execve"); - deleteEnv(env); exit(1); } - deleteEnv(env); + exit(1); } else { close(fd[1]); std::cout << "pid: " << pid << std::endl; From 51dfa2642dfa7e88e0208ea7dca7e93ac0b1a75d Mon Sep 17 00:00:00 2001 From: deer Date: Fri, 7 Jul 2023 14:35:18 +0900 Subject: [PATCH 6/6] fix: setStatusAndReason() --- playground/tkg/Design1/src/HttpResponse.cpp | 5 +++++ playground/tkg/Design1/src/HttpResponse.hpp | 1 + playground/tkg/Design1/src/Observee/CGI/CGI.cpp | 12 ++++++------ .../tkg/Design1/src/Observee/ConnectionSocket.cpp | 6 +++--- playground/tkg/Design1/src/Observee/GET.cpp | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/playground/tkg/Design1/src/HttpResponse.cpp b/playground/tkg/Design1/src/HttpResponse.cpp index c5b16f6..0e50783 100644 --- a/playground/tkg/Design1/src/HttpResponse.cpp +++ b/playground/tkg/Design1/src/HttpResponse.cpp @@ -24,6 +24,11 @@ void HttpResponse::setStatusAndReason(const int status, const std::string &reaso reason_phrase_ = reason; } +void HttpResponse::setStatusAndReason(const int status) { + status_ = status; + reason_phrase_ = conf_->cache_.statusMsg_[status_]; +} + void HttpResponse::setContentType(const std::string &path) { std::string ext = getExtension(path); if (ext == "") return; diff --git a/playground/tkg/Design1/src/HttpResponse.hpp b/playground/tkg/Design1/src/HttpResponse.hpp index 781d06c..8b11b42 100644 --- a/playground/tkg/Design1/src/HttpResponse.hpp +++ b/playground/tkg/Design1/src/HttpResponse.hpp @@ -33,6 +33,7 @@ class HttpResponse { int getStatus() const; void setStatus(const int status); void setStatusAndReason(const int status, const std::string &reason); + void setStatusAndReason(const int status); void setContentType(const std::string &path); void appendHeader(const std::string &key, const std::string &value); void appendBody(const char *str, size_t size); diff --git a/playground/tkg/Design1/src/Observee/CGI/CGI.cpp b/playground/tkg/Design1/src/Observee/CGI/CGI.cpp index 03ba914..8bed1ea 100644 --- a/playground/tkg/Design1/src/Observee/CGI/CGI.cpp +++ b/playground/tkg/Design1/src/Observee/CGI/CGI.cpp @@ -31,7 +31,7 @@ void CGI::shutdown() { em_->deleteTimerEvent(id_); kill(pid_, SIGTERM); waitpid(pid_, &status, 0); - if (status != 0) response_->setStatusAndReason(500, ""); + if (status != 0) response_->setStatusAndReason(500); em_->remove(std::pair(id_, FD)); } @@ -77,7 +77,7 @@ void CGI::processClientRedirect() { for (HttpResponse::t_headers::const_iterator itr = headers_.cbegin(); itr != headers_.cend(); itr++) { response_->appendHeader(itr->first, itr->second); } - response_->setStatusAndReason(302, ""); + response_->setStatusAndReason(302); em_->registerWriteEvent(parent_->id_); shutdown(); } @@ -214,17 +214,17 @@ void CGI::notify(struct kevent ev) { int res = read(id_, &buff[0], FILE_READ_SIZE); if (res == -1) { - response_->setStatusAndReason(500, ""); + response_->setStatusAndReason(500); em_->registerWriteEvent(parent_->id_); shutdown(); return; } else if (res == 0) { - response_->setStatusAndReason(200, ""); + response_->setStatusAndReason(200); try { handleCGIResponse(); } catch (HttpException &e) { DEBUG_PUTS(e.what()); - response_->setStatusAndReason(e.statusCode(), ""); + response_->setStatusAndReason(e.statusCode()); em_->registerWriteEvent(parent_->id_); shutdown(); } @@ -246,7 +246,7 @@ void CGI::notify(struct kevent ev) { int res = write(id_, response + sending_size_, size); if (res == -1) { perror("sendto"); - response_->setStatusAndReason(500, ""); + response_->setStatusAndReason(500); em_->registerWriteEvent(parent_->id_); shutdown(); return; diff --git a/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp b/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp index be75892..bc27214 100644 --- a/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp +++ b/playground/tkg/Design1/src/Observee/ConnectionSocket.cpp @@ -172,7 +172,7 @@ void ConnectionSocket::processGET() { if (idx_path == "" && loc_conf_->common_.autoindex_) { DEBUG_PUTS("autoindex"); response_.appendBody(GET::listFilesAndDirectories(path, request_)); - response_.setStatusAndReason(200, ""); + response_.setStatusAndReason(200); em_->disableReadEvent(id_); em_->registerWriteEvent(id_); return; // 200 OK @@ -194,7 +194,7 @@ void ConnectionSocket::processRedirect() { if (!isAcceptableMethod(loc_conf_, request_.method_)) { throw MethodNotAllowedException("No Suitable Location"); } - response_.setStatusAndReason(std::atoi(loc_conf_->getRedirectStatus().c_str()), ""); + response_.setStatusAndReason(std::atoi(loc_conf_->getRedirectStatus().c_str())); response_.appendHeader("location", loc_conf_->getRedirectURI()); em_->disableReadEvent(id_); em_->registerWriteEvent(id_); @@ -245,7 +245,7 @@ void ConnectionSocket::notify(struct kevent ev) { } catch (HttpException &e) { // all 4xx 5xx exception(readRequest and process) is caught here std::cerr << e.what() << std::endl; - response_.setStatusAndReason(e.statusCode(), ""); + response_.setStatusAndReason(e.statusCode()); if (loc_conf_) { // error_page directive is ignored when error ocuured reading Request processErrorPage(loc_conf_); diff --git a/playground/tkg/Design1/src/Observee/GET.cpp b/playground/tkg/Design1/src/Observee/GET.cpp index db5c3d3..f91d0bf 100644 --- a/playground/tkg/Design1/src/Observee/GET.cpp +++ b/playground/tkg/Design1/src/Observee/GET.cpp @@ -85,7 +85,7 @@ void GET::notify(struct kevent ev) { response_->appendBody(buff, res); if (res == 0 || res == ev.data) { close(id_); - response_->setStatusAndReason(200, ""); + response_->setStatusAndReason(200); parent_->obliviateChild(this); em_->deleteTimerEvent(id_); em_->registerWriteEvent(parent_->id_);