diff --git a/memo.txt b/memo.txt index eb86386..c076cb7 100644 --- a/memo.txt +++ b/memo.txt @@ -1,11 +1,10 @@ IN 42 SUBJECT, PRIORITY : - chunked request (response not mandatory it seems) -- 505 HTTP Version Not Supported - CGI - index (default file directory) - Ecrire des tests ! -- handle redirection +- handle redirection (weird behavior, to fix) - upload files with config "upload_repo" ----------------------------- - autoindex (done, need test) diff --git a/srcs/utils.hpp b/srcs/utils.hpp index bd48de3..faa73c8 100644 --- a/srcs/utils.hpp +++ b/srcs/utils.hpp @@ -12,15 +12,6 @@ # define LF "\n" # define CRLF CR LF -// enum http_method -// { -// UNKNOWN = 0b00000000, -// GET = 0b00000001, -// POST = 0b00000010, -// DELETE = 0b00000100, -// ANY_METHODS = 0b11111111, -// }; - enum http_method { UNKNOWN = 0b0, diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index 5084386..518cd24 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -72,36 +72,29 @@ class Webserv void _accept_connection(listen_socket &lsocket); // request.cpp void _request(Client *client); - void _read_request(Client *client); + int _read_request(Client *client); // response.cpp void _response(Client *client); - void _send_response(Client *client); - + int _send_response(Client *client); void _append_base_headers(Client *client); void _construct_response(Client *client); void _process_method(Client *client); void _insert_status_line(Client *client); void _error_html_response(Client *client); void _append_body(Client *client, const std::string &body, const std::string &file_extension = ""); - - void _get(Client *client); - // void _get(Client *client, ServerConfig &server, LocationConfig &location); - -// in progress - void _autoindex(Client *client, std::string &path); - - - void _get_file(Client *client, const std::string &path); - - void _post(Client *client); - void _post_file(Client *client, const std::string &path); - - void _delete(Client *client); - void _delete_file(Client *client, const std::string &path); - ServerConfig *_determine_process_server(Client *client); // cant be const cause of error_pages.operator[] const LocationConfig *_determine_location(const ServerConfig &server, const std::string &path) const; std::string _determine_file_extension(const std::string &path) const; + // method_get.cpp + void _get(Client *client); + void _get_file(Client *client, const std::string &path); + void _autoindex(Client *client, std::string &path); + // method_post.cpp + void _post(Client *client); + void _post_file(Client *client, const std::string &path); + // method_delete.cpp + void _delete(Client *client); + void _delete_file(Client *client, const std::string &path); // cgi_script.cpp bool _is_cgi(Client *client); void _exec_cgi(Client *client); diff --git a/srcs/webserv/http_status.hpp b/srcs/webserv/http_status.hpp index d6017f0..beba594 100644 --- a/srcs/webserv/http_status.hpp +++ b/srcs/webserv/http_status.hpp @@ -30,6 +30,13 @@ # define S201 "201 Created" # define S204 "204 No Content" +# define S301 "301 Moved Permanently" +# define S302 "302 Found" +# define S303 "303 See Other" +# define S304 "304 Not Modified" // unused +# define S307 "307 Temporary Redirect" +# define S308 "308 Permanent Redirect" + # define S400 "400 Bad Request" # define S403 "403 Forbidden" # define S404 "404 Not Found" @@ -38,5 +45,6 @@ # define S500 "500 Internal Server Error" # define S501 "501 Not Implemented" +# define S505 "505 HTTP Version Not Supported" #endif diff --git a/srcs/webserv/init.cpp b/srcs/webserv/init.cpp index cfe877b..4b034ce 100644 --- a/srcs/webserv/init.cpp +++ b/srcs/webserv/init.cpp @@ -99,6 +99,13 @@ void Webserv::_init_http_status_map() _http_status.insert(status_pair(201, S201)); _http_status.insert(status_pair(204, S204)); + _http_status.insert(status_pair(301, S301)); + _http_status.insert(status_pair(302, S302)); + _http_status.insert(status_pair(303, S303)); + _http_status.insert(status_pair(304, S304)); + _http_status.insert(status_pair(307, S307)); + _http_status.insert(status_pair(308, S308)); + _http_status.insert(status_pair(400, S400)); _http_status.insert(status_pair(403, S403)); _http_status.insert(status_pair(404, S404)); diff --git a/srcs/webserv/request.cpp b/srcs/webserv/request.cpp index b492a63..707e24a 100644 --- a/srcs/webserv/request.cpp +++ b/srcs/webserv/request.cpp @@ -4,14 +4,31 @@ #define BUFSIZE 8192 #define MAX_HEADER_SIZE 42000 // arbitrary +enum read_return +{ + READ_IN_PROGRESS, + READ_COMPLETE, + READ_CLOSE, +}; + void Webserv::_request(Client *client) { - _read_request(client); + int ret = _read_request(client); + if (g_last_signal) - _handle_last_signal(); + _handle_last_signal(); + + if (ret == READ_CLOSE) + { + _close_client(client->fd); + } + else if (ret == READ_COMPLETE) + { + _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); + } } -void Webserv::_read_request(Client *client) // Messy, Need refactoring +int Webserv::_read_request(Client *client) // Messy, Need refactoring { char buf[BUFSIZE]; ssize_t ret; @@ -24,13 +41,12 @@ void Webserv::_read_request(Client *client) // Messy, Need refactoring std::perror("err recv()"); std::cerr << "client ptr =" << client << "\n"; // DEBUG std::cerr << "client.fd =" << client->fd << "\n"; // DEBUG - _close_client(client->fd); - return ; + return READ_CLOSE; } if (ret == 0) { - _close_client(client->fd); - return ; + std::cerr << "recv() read 0, then close client" << "\n"; // DEBUG + return READ_CLOSE; } client->raw_request.append(buf, ret); @@ -38,23 +54,29 @@ void Webserv::_read_request(Client *client) // Messy, Need refactoring { if (client->raw_request.find(CRLF CRLF) != std::string::npos) { + // std::cerr << "Raw_request :\n|||||||||||||||||||||||||||||\n " << client->raw_request << "\n|||||||||||||||||||||||||||||\n"; // DEBUG client->header_complete = true; client->parse_request(); // TODO : split function to avoid useless parsing ? + if (client->status) // WIP, need to change client->parse_request() for status update + return READ_COMPLETE; client->assigned_server = _determine_process_server(client); client->assigned_location = _determine_location(*client->assigned_server, client->get_path()); + if (client->get_version().compare(0, sizeof("HTTP/1") - 1, "HTTP/1") != 0) + { // TODO : move in Client parsing ? + client->status = 505; + return READ_COMPLETE; + } if (!client->get_headers("Content-Length").empty() && ::atoi(client->get_headers("Content-Length").c_str()) > (int)client->assigned_server->client_body_limit) { client->status = 413; - _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); - return; + return READ_COMPLETE; } } else if (client->raw_request.size() > MAX_HEADER_SIZE) { client->status = 400; - _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); - return; + return READ_COMPLETE; } } else if (client->header_complete) @@ -63,22 +85,21 @@ void Webserv::_read_request(Client *client) // Messy, Need refactoring if (client->read_body_size > client->assigned_server->client_body_limit) { client->status = 413; - _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); - return; + return READ_COMPLETE; } - if ((int)client->read_body_size > ::atoi(client->get_headers("Content-Length").c_str())) + if ((int)client->read_body_size >= ::atoi(client->get_headers("Content-Length").c_str())) { client->parse_request(); // reparse for the body - _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); - return; + return READ_COMPLETE; } } if (client->header_complete && client->get_headers("Content-Type").empty() && client->get_headers("Content-Length").empty() ) { - _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD); - return; + return READ_COMPLETE; } + + return READ_IN_PROGRESS; } diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index 53861c0..179842b 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -1,14 +1,37 @@ #include "Webserv.hpp" +enum send_return +{ + SEND_IN_PROGRESS, // unused + SEND_COMPLETE, + SEND_CLOSE, +}; + void Webserv::_response(Client *client) { - _send_response(client); + int ret = _send_response(client); + if (g_last_signal) _handle_last_signal(); + + if (ret == SEND_CLOSE) + { + _close_client(client->fd); + } + else if (ret == SEND_COMPLETE) + { + if (client->get_headers("Connection") == "close") + _close_client(client->fd); + else + { + _epoll_update(client->fd, EPOLLIN, EPOLL_CTL_MOD); + client->clear(); + } + } } -void Webserv::_send_response(Client *client) +int Webserv::_send_response(Client *client) { ssize_t ret; @@ -27,18 +50,11 @@ void Webserv::_send_response(Client *client) { std::perror("err send()"); std::cerr << "client.fd =" << client->fd << "\n"; // DEBUG - _close_client(client->fd); - return ; + return SEND_CLOSE; } std::cerr << "ret send() = " << ret << "\n"; // DEBUG - if (client->get_headers("Connection") == "close") - _close_client(client->fd); - else - { - _epoll_update(client->fd, EPOLLIN, EPOLL_CTL_MOD); - client->clear(); - } + return SEND_COMPLETE; } void Webserv::_append_base_headers(Client *client) @@ -59,6 +75,24 @@ void Webserv::_construct_response(Client *client) client->status = 413; return; } +/* if (client->assigned_location->redirect_status) + { + // (for codes 301, 302, 303, 307, and 308) + client->status = client->assigned_location->redirect_status; + client->response.append("Location: "); + client->response.append(client->assigned_location->redirect_uri); + client->response.append(CRLF); + } */ + if (client->get_path().find("redirect_test") != std::string::npos) // Test block + { // Weird behavior. The web browser seems to wait for a complete response until timeout. + // (for codes 301, 302, 303, 307, and 308) + client->status = 307; + client->response.append("Location: "); + client->response.append("https://www.rfc-editor.org/rfc/rfc3875#section-3.3"); + client->response.append(CRLF); + client->response.append(CRLF); + return ; + } _process_method(client); } @@ -105,7 +139,7 @@ void Webserv::_insert_status_line(Client *client) void Webserv::_error_html_response(Client *client) { - if (client->assigned_server->error_pages[client->status].empty()) + if (!client->assigned_server || client->assigned_server->error_pages[client->status].empty()) { std::string html_page = HTML_ERROR; ::replace_all_substr(html_page, STATUS_PLACEHOLDER, _http_status[client->status]); diff --git a/srcs/webserv/run_loop.cpp b/srcs/webserv/run_loop.cpp index 04c1e03..cb91672 100644 --- a/srcs/webserv/run_loop.cpp +++ b/srcs/webserv/run_loop.cpp @@ -57,6 +57,11 @@ void Webserv::run() std::vector().swap(_clients); break; } + catch (const std::exception& e) + { + std::cerr << e.what() << '\n'; + ++i; + } } } }