Skip to content

Commit

Permalink
add: cgi-redirect
Browse files Browse the repository at this point in the history
  • Loading branch information
ak0327 committed Mar 9, 2024
1 parent 67c6168 commit 75db24f
Show file tree
Hide file tree
Showing 13 changed files with 101 additions and 43 deletions.
2 changes: 1 addition & 1 deletion conf/webserv.conf
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ http {
}

cgi_mode on; # original; cgi_mode (on/off)
cgi_extension py php sh; # original; extension of cgi file
cgi_extension py pl sh; # original; extension of cgi file
cgi_timeout 10s; # original; cgi process timeout (sec/min)
}

Expand Down
2 changes: 1 addition & 1 deletion html/cgi-bin/hello.pl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use warnings;


print "Content-Type: text/html\n\n";
print "Content-Type: text/html\n";
print "\n";

print "hello\n";
17 changes: 17 additions & 0 deletions html/cgi-bin/redirect_to_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env python3


def header():
print('Status: 302 Found')
print('Content-Type: text/html')
print('Location: /')
print()


def main():
print('redirect to index')


if __name__ == "__main__":
header()
main()
1 change: 1 addition & 0 deletions html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ <h3>GET</h3>
<li><a href="http://localhost:4343/cgi-bin/hello.py">hello.py</a>
<li><a href="http://localhost:4343/cgi-bin/page.py">page.py</a>
<li><a href="http://localhost:4343/cgi-bin/cgi_params.py/path/info?query/string">cgi_params.py</a>
<li><a href="http://localhost:4343/cgi-bin/redirect_to_index.py">redirect to CGI-server index</a>
<li><a href="http://localhost:4343/cgi-bin/hello_400.py">hello_400.py -> 400</a>
<li><a href="http://localhost:4343/cgi-bin/hello_404.py">hello_404.py -> 404</a>
<li><a href="http://localhost:4343/cgi-bin/hello_500.py">hello_500.py -> 500</a>
Expand Down
6 changes: 4 additions & 2 deletions srcs/Const/Constant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ std::map<StatusCode, std::string> init_reason_phrases() {

reason_phrases[MultipleChoices] = "Multiple Choices";
reason_phrases[MovedPermanently] = "Moved Permanently";
reason_phrases[Found] = "Found";
reason_phrases[SeeOther] = "See Other";

reason_phrases[BadRequest] = "Bad Request";
Expand Down Expand Up @@ -639,8 +640,9 @@ MimeTypeMap init_mime_types() {
mime_types["htm"] = "text/htm";
mime_types["css"] = "text/css";
mime_types["txt"] = "text/plain";
mime_types["py"] = "text/x-python";
// mime_types["sh"] = "text/x-shell";
mime_types["py"] = "text/x-python"; // view python file
// mime_types["sh"] = "text/x-shell"; // tmp
// mime_types["pl"] = "text/x-perl"; // tmp

mime_types["gif"] = "image/gif";
mime_types["jpeg"] = "image/jpeg";
Expand Down
14 changes: 11 additions & 3 deletions srcs/Event/process_client_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "Error.hpp"
#include "FileHandler.hpp"
#include "HttpResponse.hpp"
#include "HttpMessageParser.hpp"
#include "Socket.hpp"
#include "StringHandler.hpp"

Expand Down Expand Up @@ -473,9 +474,9 @@ ProcResult HttpResponse::exec_cgi_process() {
The newline (NL) sequence is LF; servers should also accept CR LF as a newline.
^^^^^^
*/
// todo: where?? status <- .cgi_status
void HttpResponse::interpret_cgi_output() {
if (is_status_server_error(this->status_code())) { // server error
// exec failure -> 500/502/504 already set
if (HttpMessageParser::is_status_server_error(this->status_code())) {
return;
}

Expand All @@ -485,11 +486,18 @@ void HttpResponse::interpret_cgi_output() {
if (is_status_error()) {
return;
}
if (HttpMessageParser::is_redirection_status(this->status_code())) {
ReturnDirective redirect;
redirect.return_on = true;
redirect.code = this->status_code();
redirect.text = this->cgi_handler_.location();
get_redirect_content(redirect);
return;
}
if (!is_supported_by_media_type(this->cgi_handler_.content_type())) {
this->set_status_code(UnsupportedMediaType);
return;
}

this->body_buf_ = this->cgi_handler_.cgi_body();
add_content_header_by_media_type(this->cgi_handler_.content_type());
}
30 changes: 30 additions & 0 deletions srcs/HttpResponse/CgiHandler/CgiHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,9 @@ std::string CgiHandler::content_type() {
}


std::string CgiHandler::location() { return this->location_; }


Result<StatusCode, ProcResult> parse_status_line(const std::string &field_value) {
int code;
std::string reason_prase;
Expand All @@ -308,9 +311,15 @@ Result<StatusCode, ProcResult> parse_status_line(const std::string &field_value)
}


/*
Location = URI-reference
https://datatracker.ietf.org/doc/html/rfc7231#section-7.1.2
*/
StatusCode CgiHandler::parse_document_response() {
StatusCode cgi_status = StatusOk;
int content_count = 0;
int status_count = 0;
int location_count = 0;
while (true) {
Result<std::string, ProcResult> line_result = pop_line_from_buf();
if (line_result.is_err()) {
Expand All @@ -327,15 +336,32 @@ StatusCode CgiHandler::parse_document_response() {
if (split.is_err()) {
return InternalServerError;
}
if (field_value.empty()) {
return InternalServerError;
}
field_name = StringHandler::to_lower(field_name);
if (field_name == std::string(CONTENT_TYPE)) {
++content_count;
if (1 < content_count) {
return InternalServerError;
}
if (this->media_type_.is_ok()) {
return InternalServerError;
}
this->media_type_ = MediaType(field_value);
if (this->media_type_.is_err()) {
return InternalServerError;
}
} else if (field_name == std::string(LOCATION)) {
++location_count;
if (1 < location_count) {
return InternalServerError;
}
if (HttpMessageParser::is_uri_ref(field_value)) {
this->location_ = field_value;
} else {
return InternalServerError;
}
} else if (field_name == "status") {
++status_count;
if (1 < status_count) {
Expand All @@ -351,6 +377,10 @@ StatusCode CgiHandler::parse_document_response() {
if (this->media_type_.is_err()) {
return InternalServerError;
}
if (HttpMessageParser::is_redirection_status(this->cgi_status_)
&& location_count != 1) {
return InternalServerError;
}
return cgi_status;
}

Expand Down
2 changes: 2 additions & 0 deletions srcs/HttpResponse/CgiHandler/CgiHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class CgiHandler {
StatusCode parse_document_response();

std::string content_type();
std::string location();

#ifdef UNIT_TEST
friend class CgiHandlerFriend;
Expand All @@ -75,6 +76,7 @@ class CgiHandler {

MediaType media_type_;
StatusCode cgi_status_;
std::string location_;

std::size_t send_size_;
std::vector<unsigned char> recv_buf_;
Expand Down
9 changes: 4 additions & 5 deletions srcs/HttpResponse/GET/get_request_body.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,17 @@ bool HttpResponse::is_redirect() const {

StatusCode HttpResponse::get_redirect_content(const ReturnDirective &redirect) {
DEBUG_PRINT(RED, "redirect.text: %s (L:%d)", redirect.text.c_str(), __LINE__);
Result<HostPortPair, StatusCode> info_result = this->request_.server_info();
if (info_result.is_err()) {
return info_result.err_value();
}

std::string redirect_path;
if (HttpMessageParser::is_absolute_uri(redirect.text)) {
DEBUG_PRINT(RED, "external redirect", __LINE__);
// external redirect
redirect_path = redirect.text;
} else {
DEBUG_PRINT(RED, "local redirect", __LINE__);
Result<HostPortPair, StatusCode> info_result = this->request_.server_info();
if (info_result.is_err()) {
return info_result.err_value();
}
// local redirect
HostPortPair server_info = info_result.ok_value();
redirect_path = "http://";
Expand Down
4 changes: 0 additions & 4 deletions srcs/HttpResponse/HttpResponse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ class HttpResponse {

void create_echo_msg(const std::vector<unsigned char> &recv_msg);
bool is_status_error() const;
static bool is_successful_status(StatusCode code);
static bool is_redirection_status(StatusCode code);
static bool is_status_client_error(StatusCode code);
static bool is_status_server_error(StatusCode code);
bool is_keepalive() const;

void set_status_to_cgi_timeout();
Expand Down
29 changes: 2 additions & 27 deletions srcs/HttpResponse/create_response_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,43 +54,18 @@ void HttpResponse::create_response_message() {


bool HttpResponse::is_status_error() const {
if (is_status_client_error(this->status_code())) {
if (HttpMessageParser::is_status_client_error(this->status_code())) {
DEBUG_PRINT(MAGENTA, "is_status_error: %d: client error");
return true;
}
if (is_status_server_error(this->status_code())) {
if (HttpMessageParser::is_status_server_error(this->status_code())) {
DEBUG_PRINT(MAGENTA, "is_status_error: %d: server error");
return true;
}
return false;
}


bool HttpResponse::is_successful_status(StatusCode code) {
int code_num = static_cast<int>(code);
return 200 <= code_num && code_num <= 299;
}


bool HttpResponse::is_redirection_status(StatusCode code) {
int code_num = static_cast<int>(code);
return 300 <= code_num && code_num <= 399;
}


bool HttpResponse::is_status_client_error(StatusCode code) {
int code_num = static_cast<int>(code);
return 400 <= code_num && code_num <= 499;
}


bool HttpResponse::is_status_server_error(StatusCode code) {
int code_num = static_cast<int>(code);
return 500 <= code_num && code_num <= 599;
}



bool HttpResponse::is_response_error_page() const {
Result<std::string, int> result;
result = Config::get_error_page(this->server_config_,
Expand Down
5 changes: 5 additions & 0 deletions srcs/StringHandler/HttpMessageParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ bool is_parameter_weight(const std::string &parameter_name,
const std::string &parameter_value);
bool is_parameter_weight(const std::string &parameter_name);

bool is_successful_status(StatusCode code);
bool is_redirection_status(StatusCode code);
bool is_status_client_error(StatusCode code);
bool is_status_server_error(StatusCode code);

////////////////////////////////////////////////////////////////////////////////

void skip_ows(const std::string &str, std::size_t *pos);
Expand Down
23 changes: 23 additions & 0 deletions srcs/StringHandler/HttpMessageParserIs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1043,5 +1043,28 @@ bool is_atom(const std::string &str) {
return str[end] == '\0';
}

bool is_successful_status(StatusCode code) {
int code_num = static_cast<int>(code);
return 200 <= code_num && code_num <= 299;
}


bool is_redirection_status(StatusCode code) {
int code_num = static_cast<int>(code);
return 300 <= code_num && code_num <= 399;
}


bool is_status_client_error(StatusCode code) {
int code_num = static_cast<int>(code);
return 400 <= code_num && code_num <= 499;
}


bool is_status_server_error(StatusCode code) {
int code_num = static_cast<int>(code);
return 500 <= code_num && code_num <= 599;
}


} // namespace HttpMessageParser

0 comments on commit 75db24f

Please sign in to comment.