diff --git a/Makefile b/Makefile
index 0c35a34..1761476 100644
--- a/Makefile
+++ b/Makefile
@@ -22,6 +22,7 @@ SRCS_D = srcs \
SRCS = main.cpp \
base.cpp init.cpp close.cpp epoll_update.cpp signal.cpp \
accept.cpp request.cpp response.cpp \
+ method_get.cpp method_post.cpp method_delete.cpp \
run_loop.cpp \
parser.cpp \
extraConfig.cpp \
diff --git a/memo.txt b/memo.txt
index 5b32a3e..eb86386 100644
--- a/memo.txt
+++ b/memo.txt
@@ -1,12 +1,15 @@
IN 42 SUBJECT, PRIORITY :
- chunked request (response not mandatory it seems)
-- upload files with confif "upload_dir"
- 505 HTTP Version Not Supported
- CGI
-- handle redirection
-- index and autoindex
+- index (default file directory)
- Ecrire des tests !
+
+- handle redirection
+- upload files with config "upload_repo"
-----------------------------
+- autoindex (done, need test)
+--------------
- replace atoi() with a better function
- 408 Request Timeout
- gerer le champ "Accept" du client
diff --git a/srcs/utils.cpp b/srcs/utils.cpp
index 47ab461..4df5eab 100644
--- a/srcs/utils.cpp
+++ b/srcs/utils.cpp
@@ -68,7 +68,7 @@ http_method str_to_http_method(std::string &str)
return POST;
else if (str == "DELETE")
return DELETE;
- else if (str == "ALL_METHODS")
+ else if (str == "ALL_METHODS") // for Eric: why this test ? can we delete it?
return ANY_METHODS;
// would prefere ALL_METHODS
return UNKNOWN;
diff --git a/srcs/webserv/method_delete.cpp b/srcs/webserv/method_delete.cpp
new file mode 100644
index 0000000..f707e3a
--- /dev/null
+++ b/srcs/webserv/method_delete.cpp
@@ -0,0 +1,40 @@
+
+#include "Webserv.hpp"
+
+void Webserv::_delete(Client *client)
+{
+/*
+ WIP
+ https://www.rfc-editor.org/rfc/rfc9110.html#name-delete
+*/
+ std::string path = client->get_path();
+ path.insert(0, client->assigned_location->root);
+
+ /* CGI Here ? */
+
+ _delete_file(client, path);
+}
+
+void Webserv::_delete_file(Client *client, const std::string &path)
+{
+ if (access(path.c_str(), F_OK) == -1)
+ {
+ std::perror("err access()");
+ client->status = 404;
+ return ;
+ }
+
+ if (access(path.c_str(), W_OK) == -1)
+ {
+ std::perror("err access()");
+ client->status = 403;
+ return ;
+ }
+
+ if (remove(path.c_str()) == -1)
+ {
+ std::perror("err remove()");
+ client->status = 500;
+ return ;
+ }
+}
diff --git a/srcs/webserv/method_get.cpp b/srcs/webserv/method_get.cpp
new file mode 100644
index 0000000..e5bca7e
--- /dev/null
+++ b/srcs/webserv/method_get.cpp
@@ -0,0 +1,192 @@
+
+#include "Webserv.hpp"
+
+void Webserv::_get(Client *client)
+{
+/* RULES **
+
+if path is a valid dir check if index is specified and serve that
+if no index and autoindex, server that
+if file, server that!
+
+WHere does cgi fit in in all this ???
+
+
+*/
+ std::string path = client->get_path();
+
+ // this might not be the best thing, a voir
+ path.insert(0, client->assigned_location->root);
+
+ std::cerr << "path = " << path << "\n";
+
+ // path = root + location.path
+ // we will tack on an index if there is a valid one
+ // or autoindex if allowed
+ // or let _get_file sort out the error otherwise.
+
+ if (path_is_valid(path) == 1)
+ {
+ // std::cout << "path is valid\n";
+ if (path[path.size() - 1] != '/')
+ path.push_back('/');
+ for (size_t i = 0; i < client->assigned_location->index.size(); i++)
+ {
+// std::cout << "location path: " << client->assigned_location->path << '\n';
+// std::cout << "location index: " << client->assigned_location->index[i] << '\n';
+// std::cout << "path with index: " << path + assigned_location->index[i] << '\n';
+ if (path_is_valid(path + client->assigned_location->index[i]) == 2)
+ {
+ // std::cout << "found a valid index\n";
+ path.append(client->assigned_location->index[i]);
+ break ; // what if index and autoindex in a single location?
+ // does this completely fail?
+ // do this instead of break?
+ //_get_file(client, path);
+ }
+ }
+ if (client->assigned_location->autoindex == true)
+ {
+ // _autoindex(client, client->assigned_location, path);
+ _autoindex(client, path);
+ return ;
+ }
+ }
+// else
+// _get_file(client, path);
+ // what about cgi ???
+
+
+
+ // TMP HUGO
+ //
+ if (_is_cgi(client))
+ {
+ _exec_cgi(client);
+ return;
+ }
+ //
+ // END TMP HUGO
+
+ _get_file(client, path);
+}
+
+# define MAX_FILESIZE 1000000 // (1Mo)
+void Webserv::_get_file(Client *client, const std::string &path)
+{
+/*
+ std::ios::binary
+ https://gcc.gnu.org/onlinedocs/libstdc++/manual/fstreams.html#std.io.filestreams.binary
+ tldr : its seems to not be so simple to do read/write of binary file in a portable way.
+*/
+ std::ifstream ifd; // For chunk, ifstream directly in struct CLient for multiples read without close() ?
+ std::stringstream buf;
+
+ std::cout << "made it to get_file\n";
+
+ if (access(path.c_str(), F_OK) == -1)
+ {
+ std::perror("err access()");
+ client->status = 404;
+ return ;
+ }
+
+ if (access(path.c_str(), R_OK) == -1)
+ {
+ std::perror("err access()");
+ client->status = 403;
+ return ;
+ }
+
+ ifd.open(path.c_str(), std::ios::ate);
+ if (!ifd)
+ {
+ std::cerr << path << ": ifd.open fail" << '\n';
+ client->status = 500;
+ }
+ else
+ {
+ std::streampos size = ifd.tellg();
+
+ // WIP : Chunk or not chunk (if filesize too big)
+ if (size > MAX_FILESIZE)
+ {
+ // Then chunk
+ client->status = 500; // WIP temp
+ std::cerr << "File too large for non chunk body\n";
+ return ;
+ }
+
+ ifd.seekg(0, std::ios::beg);
+ buf << ifd.rdbuf();
+ if (!ifd || !buf)
+ {
+ std::cerr << path << ": ifd.read fail" << '\n';
+ client->status = 500;
+ }
+ else
+ {
+ client->status = 200;
+ std::string file_ext = _determine_file_extension(path);
+ _append_body(client, buf.str(), file_ext);
+ }
+ }
+}
+
+// i only sort of need &path...
+// def can improve but works for now...
+//void Webserv::_autoindex(Client *client, LocationConfig &location, std::string &path)
+void Webserv::_autoindex(Client *client, std::string &path)
+{
+// std::cout << "made it to _autoindex\n";
+
+ (void)path;
+ std::string dir_list;
+ DIR *dir;
+ struct dirent *ent;
+
+// std::cout << "location root: " << client->assigned_location->root << " location path: "
+// << client->assigned_location->path << '\n';
+
+// if ((dir = opendir (path.c_str())) != NULL)
+ if ((dir = opendir ((client->assigned_location->root + client->assigned_location->path).c_str())) != NULL)
+ {
+ /* print all the files and directories within directory */
+ dir_list.append(AUTOINDEX_START);
+ dir_list.append(client->assigned_location->path);
+ dir_list.append(AUTOINDEX_MID1);
+ dir_list.append(client->assigned_location->path);
+ dir_list.append(AUTOINDEX_MID2);
+ while ((ent = readdir (dir)) != NULL)
+ {
+ if (strcmp(".", ent->d_name) == 0)
+ continue ;
+ dir_list.append("assigned_location->path.c_str());
+ dir_list.append(ent->d_name);
+ dir_list.append("\">");
+ dir_list.append(ent->d_name);
+ dir_list.append("");
+ dir_list.append("\r\n"); // is this right?
+ }
+
+// nginx.org.
+// index1.html
+
+// apparently this is more than good enough!
+// ..
+
+ dir_list.append(AUTOINDEX_END);
+// std::cout << "\n\n" << dir_list << '\n';
+ closedir (dir);
+ _append_body(client, dir_list, "html");
+ }
+ else
+ {
+ // in theory not possible cuz we already checked...
+ /* could not open directory */
+// perror ("");
+ std::cout << "could not open dir\n";
+ return ;
+ }
+}
\ No newline at end of file
diff --git a/srcs/webserv/method_post.cpp b/srcs/webserv/method_post.cpp
new file mode 100644
index 0000000..2c011b4
--- /dev/null
+++ b/srcs/webserv/method_post.cpp
@@ -0,0 +1,66 @@
+
+#include "Webserv.hpp"
+
+
+void Webserv::_post(Client *client)
+{
+/*
+ WIP
+ https://www.rfc-editor.org/rfc/rfc9110.html#name-post
+*/
+ std::string path = client->get_path();
+ path.insert(0, client->assigned_location->root);
+
+ /* CGI Here ? */
+
+ _post_file(client, path);
+}
+
+void Webserv::_post_file(Client *client, const std::string &path)
+{
+ std::ofstream ofd;
+
+ bool file_existed;
+ if (access(path.c_str(), F_OK) == -1)
+ file_existed = false;
+ else
+ file_existed = true;
+
+ // How to determine status 403 for file that dont already exist ?
+ if (file_existed && access(path.c_str(), W_OK) == -1)
+ {
+ std::perror("err access()");
+ client->status = 403;
+ return ;
+ }
+
+ ofd.open(path.c_str(), std::ios::trunc);
+ if (!ofd)
+ {
+ std::cerr << path << ": ofd.open fail" << '\n';
+ client->status = 500;
+ }
+ else
+ {
+ // Content-Length useless at this point ?
+ // Maybe usefull in _read_request() for rejecting too big content.
+ // Need to _determine_process_server() as soon as possible,
+ // like in _read_request() for stopping read if body is too big ?
+ ofd << client->get_body();
+ if (!ofd)
+ {
+ std::cerr << path << ": ofd.write fail" << '\n';
+ client->status = 500;
+ }
+ else if (file_existed)
+ {
+ client->status = 200;
+ // WIP https://www.rfc-editor.org/rfc/rfc9110.html#name-200-ok
+ }
+ else
+ {
+ client->status = 201;
+ // WIP https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.3-4
+ }
+ }
+}
diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp
index 2fbeea9..c288388 100644
--- a/srcs/webserv/response.cpp
+++ b/srcs/webserv/response.cpp
@@ -64,15 +64,13 @@ void Webserv::_construct_response(Client *client)
void Webserv::_process_method(Client *client)
{
- unsigned int allow_methods = ANY_METHODS; // TEMP VARIABLE
- // after update in ConfigParser, use the "allow_methods" of location.
- // TODO in ConfigParser : by default if no field in config file, "allow_methods" must be set to ANY_METHODS
-
+ std::cerr << "assigned_location->path = " << client->assigned_location->path << "\n"; // debug
+ std::cerr << "allow_methods = " << client->assigned_location->allow_methods << "\n"; // debug
if (client->get_method() == UNKNOWN)
{
client->status = 501;
}
- else if (allow_methods & client->get_method())
+ else if (client->assigned_location->allow_methods & client->get_method())
{
switch (client->get_method())
{
@@ -90,7 +88,7 @@ void Webserv::_process_method(Client *client)
{
client->status = 405;
client->response.append("Allow: ");
- client->response.append(::http_methods_to_str(allow_methods));
+ client->response.append(::http_methods_to_str(client->assigned_location->allow_methods));
client->response.append(CRLF);
}
}
@@ -117,202 +115,6 @@ void Webserv::_error_html_response(Client *client)
_get_file(client, client->assigned_server->error_pages[client->status]);
}
-//#define INDEX "index.html" // temp wip
-void Webserv::_get(Client *client)
-{
-/* RULES **
-
-if path is a valid dir check if index is specified and serve that
-if no index and autoindex, server that
-if file, server that!
-
-WHere does cgi fit in in all this ???
-
-
-*/
- std::string path = client->get_path();
-
- // this might not be the best thing, a voir
- path.insert(0, client->assigned_location->root);
-
- std::cerr << "path = " << path << "\n";
-
- // path = root + location.path
- // we will tack on an index if there is a valid one
- // or autoindex if allowed
- // or let _get_file sort out the error otherwise.
-
- if (path_is_valid(path) == 1)
- {
- // std::cout << "path is valid\n";
- if (path[path.size() - 1] != '/')
- path.push_back('/');
- for (size_t i = 0; i < client->assigned_location->index.size(); i++)
- {
-// std::cout << "location path: " << client->assigned_location->path << '\n';
-// std::cout << "location index: " << client->assigned_location->index[i] << '\n';
-// std::cout << "path with index: " << path + assigned_location->index[i] << '\n';
- if (path_is_valid(path + client->assigned_location->index[i]) == 2)
- {
- // std::cout << "found a valid index\n";
- path.append(client->assigned_location->index[i]);
- break ; // what if index and autoindex in a single location?
- // does this completely fail?
- // do this instead of break?
- //_get_file(client, path);
- }
- }
- if (client->assigned_location->autoindex == true)
- {
- // _autoindex(client, client->assigned_location, path);
- _autoindex(client, path);
- return ;
- }
- }
-// else
-// _get_file(client, path);
- // what about cgi ???
-
-
-
- // TMP HUGO
- //
- if (_is_cgi(client))
- {
- _exec_cgi(client);
- return;
- }
- //
- // END TMP HUGO
-
- _get_file(client, path);
-}
-
-
-// i only sort of need &path...
-// def can improve but works for now...
-//void Webserv::_autoindex(Client *client, LocationConfig &location, std::string &path)
-void Webserv::_autoindex(Client *client, std::string &path)
-{
-// std::cout << "made it to _autoindex\n";
-
- (void)path;
- std::string dir_list;
- DIR *dir;
- struct dirent *ent;
-
-// std::cout << "location root: " << client->assigned_location->root << " location path: "
-// << client->assigned_location->path << '\n';
-
-// if ((dir = opendir (path.c_str())) != NULL)
- if ((dir = opendir ((client->assigned_location->root + client->assigned_location->path).c_str())) != NULL)
- {
- /* print all the files and directories within directory */
- dir_list.append(AUTOINDEX_START);
- dir_list.append(client->assigned_location->path);
- dir_list.append(AUTOINDEX_MID1);
- dir_list.append(client->assigned_location->path);
- dir_list.append(AUTOINDEX_MID2);
- while ((ent = readdir (dir)) != NULL)
- {
- if (strcmp(".", ent->d_name) == 0)
- continue ;
- dir_list.append("assigned_location->path.c_str());
- dir_list.append(ent->d_name);
- dir_list.append("\">");
- dir_list.append(ent->d_name);
- dir_list.append("");
- dir_list.append("\r\n"); // is this right?
- }
-
-// nginx.org.
-// index1.html
-
-// apparently this is more than good enough!
-// ..
-
- dir_list.append(AUTOINDEX_END);
-// std::cout << "\n\n" << dir_list << '\n';
- closedir (dir);
- _append_body(client, dir_list, "html");
- }
- else
- {
- // in theory not possible cuz we already checked...
- /* could not open directory */
-// perror ("");
- std::cout << "could not open dir\n";
- return ;
- }
-}
-
-
-
-# define MAX_FILESIZE 1000000 // (1Mo)
-void Webserv::_get_file(Client *client, const std::string &path)
-{
-/*
- std::ios::binary
- https://gcc.gnu.org/onlinedocs/libstdc++/manual/fstreams.html#std.io.filestreams.binary
- tldr : its seems to not be so simple to do read/write of binary file in a portable way.
-*/
- std::ifstream ifd; // For chunk, ifstream directly in struct CLient for multiples read without close() ?
- std::stringstream buf;
-
- std::cout << "made it to get_file\n";
-
- if (access(path.c_str(), F_OK) == -1)
- {
- std::perror("err access()");
- client->status = 404;
- return ;
- }
-
- if (access(path.c_str(), R_OK) == -1)
- {
- std::perror("err access()");
- client->status = 403;
- return ;
- }
-
- ifd.open(path.c_str(), std::ios::ate);
- if (!ifd)
- {
- std::cerr << path << ": ifd.open fail" << '\n';
- client->status = 500;
- }
- else
- {
- std::streampos size = ifd.tellg();
-
- // WIP : Chunk or not chunk (if filesize too big)
- if (size > MAX_FILESIZE)
- {
- // Then chunk
- client->status = 500; // WIP temp
- std::cerr << "File too large for non chunk body\n";
- return ;
- }
-
- ifd.seekg(0, std::ios::beg);
- buf << ifd.rdbuf();
- if (!ifd || !buf)
- {
- std::cerr << path << ": ifd.read fail" << '\n';
- client->status = 500;
- }
- else
- {
- client->status = 200;
- std::string file_ext = _determine_file_extension(path);
- _append_body(client, buf.str(), file_ext);
- }
- }
-}
-
-
-//void Webserv::_append_body(Client *client, const char *body, size_t body_size, const std::string &file_extension)
void Webserv::_append_body(Client *client, const std::string &body, const std::string &file_extension)
{
const std::string &mime_type = _mime_types[file_extension];
@@ -337,107 +139,6 @@ void Webserv::_append_body(Client *client, const std::string &body, const std::s
client->response.append(body);
}
-void Webserv::_post(Client *client)
-{
-/*
- WIP
- https://www.rfc-editor.org/rfc/rfc9110.html#name-post
-*/
- std::string path = client->get_path();
- path.insert(0, client->assigned_location->root);
-
- /* CGI Here ? */
-
- _post_file(client, path);
-}
-
-void Webserv::_post_file(Client *client, const std::string &path)
-{
- std::ofstream ofd;
-
- bool file_existed;
- if (access(path.c_str(), F_OK) == -1)
- file_existed = false;
- else
- file_existed = true;
-
- // How to determine status 403 for file that dont already exist ?
- if (file_existed && access(path.c_str(), W_OK) == -1)
- {
- std::perror("err access()");
- client->status = 403;
- return ;
- }
-
- ofd.open(path.c_str(), std::ios::trunc);
- if (!ofd)
- {
- std::cerr << path << ": ofd.open fail" << '\n';
- client->status = 500;
- }
- else
- {
- // Content-Length useless at this point ?
- // Maybe usefull in _read_request() for rejecting too big content.
- // Need to _determine_process_server() as soon as possible,
- // like in _read_request() for stopping read if body is too big ?
- ofd << client->get_body();
- if (!ofd)
- {
- std::cerr << path << ": ofd.write fail" << '\n';
- client->status = 500;
- }
- else if (file_existed)
- {
- client->status = 200;
- // WIP https://www.rfc-editor.org/rfc/rfc9110.html#name-200-ok
- }
- else
- {
- client->status = 201;
- // WIP https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.3-4
- }
- }
-}
-
-void Webserv::_delete(Client *client)
-{
-/*
- WIP
- https://www.rfc-editor.org/rfc/rfc9110.html#name-delete
-*/
- std::string path = client->get_path();
- path.insert(0, client->assigned_location->root);
-
- /* CGI Here ? */
-
- _delete_file(client, path);
-}
-
-void Webserv::_delete_file(Client *client, const std::string &path)
-{
- if (access(path.c_str(), F_OK) == -1)
- {
- std::perror("err access()");
- client->status = 404;
- return ;
- }
-
- if (access(path.c_str(), W_OK) == -1)
- {
- std::perror("err access()");
- client->status = 403;
- return ;
- }
-
- if (remove(path.c_str()) == -1)
- {
- std::perror("err remove()");
- client->status = 500;
- return ;
- }
-}
-
ServerConfig *Webserv::_determine_process_server(Client *client)
{
/*
@@ -488,7 +189,7 @@ const LocationConfig *Webserv::_determine_location(const ServerConfig &server, c
if (it != server.locations.end())
return (&(*it));
else
- return (&(server.locations.front()));
+ return (&(server.locations.back()));
}
std::string Webserv::_determine_file_extension(const std::string &path) const