added multipart upload file,

it works, but need some adjustements,
refactoring and testing
This commit is contained in:
LuckyLaszlo
2022-08-14 06:25:06 +02:00
parent b0949615c8
commit 84babec82b
19 changed files with 398 additions and 86 deletions

View File

@@ -97,7 +97,7 @@ class Webserv
void _autoindex(Client *client, const std::string &path);
// method_post.cpp
void _post(Client *client, const std::string &path);
void _post_file(Client *client, const std::string &path);
void _upload_files(Client *client);
// method_delete.cpp
void _delete(Client *client, const std::string &path);
void _delete_file(Client *client, const std::string &path);

View File

@@ -112,9 +112,11 @@ void Webserv::_init_http_status_map()
_http_status.insert(status_pair(405, S405));
_http_status.insert(status_pair(408, S408));
_http_status.insert(status_pair(413, S413));
_http_status.insert(status_pair(415, S415));
_http_status.insert(status_pair(500, S500));
_http_status.insert(status_pair(501, S501));
_http_status.insert(status_pair(505, S505));
}
void Webserv::_init_mime_types_map()

View File

@@ -8,51 +8,119 @@ void Webserv::_post(Client *client, const std::string &path)
WIP
https://www.rfc-editor.org/rfc/rfc9110.html#name-post
*/
_post_file(client, path);
(void)path;
std::cout << "_post()\n";
std::cerr << "upload_dir = " << client->assigned_location->upload_dir << "\n";
if (client->get_rq_abs_path() != client->assigned_location->path)
client->status = 404; // 404 ? J'ai un doute.
else if (client->assigned_location->upload_dir.empty())
client->status = 404; // 404 ? J'ai un doute.
else if (client->get_rq_multi_bodys().empty())
{
client->status = 415;
client->response.append("Accept: multipart/form-data"); // empty, no encoding accepted
client->response.append(CRLF);
}
else
_upload_file(client);
}
void Webserv::_post_file(Client *client, const std::string &path)
#define DEFAULT_NAME "unnamed_file"
// TODO : Loop for multi body
void Webserv::_upload_files(Client *client)
{
std::ofstream ofd;
std::vector<MultipartBody>::const_iterator body_it = client->get_rq_multi_bodys().begin();
std::string path;
std::string filename;
size_t pos;
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)
while (body_it != client->get_rq_multi_bodys().end())
{
std::perror("err access()");
client->status = 403;
return ;
}
if (body_it->body.empty())
{
++body_it;
continue;
}
// Content-Disposition: form-data; name="upload_file"; filename="camion.jpg"
::print_map(body_it->headers);
filename = client->get_rq_multi_bodys_headers("Content-Disposition", body_it);
std::cerr << "filename ="<< filename << "\n";
pos = filename.find("filename=");
if (pos != NPOS)
{
filename = filename.substr(pos + sizeof("filename=")-1);
std::cerr << "filename ="<< filename << "\n";
// A l'arrache pour enlever les "
filename.erase(0, 1);
std::cerr << "filename ="<< filename << "\n";
filename.erase(filename.size()-1, 1);
std::cerr << "filename ="<< filename << "\n";
std::cerr << "filename ="<< filename << "\n";
if (filename.empty())
filename = DEFAULT_NAME;
}
else
{
filename = DEFAULT_NAME;
}
std::cerr << "filename ="<< filename << "\n";
path = client->assigned_location->upload_dir; // Assume there a final '/'
path.append(filename);
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 ?
ofd << client->get_rq_body();
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 ? access() on the upload_dir ?
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;
return;
}
ofd << body_it->body;
if (!ofd)
{
std::cerr << path << ": ofd.write fail" << '\n';
client->status = 500;
return;
}
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
}
++body_it;
ofd.close();
}
if (file_existed) // with multi body it doesn't make much sense
{
// client->status = 200;
client->status = 204; // DEBUG 204
client->response.append("Location: ");
client->response.append("/index.html"); // WIP
client->response.append(CRLF);
client->response.append(CRLF);
// WIP https://www.rfc-editor.org/rfc/rfc9110.html#name-200-ok
}
else
{
// client->status = 201;
client->status = 204; // DEBUG 204
client->response.append("Location: ");
client->response.append("/index.html"); // WIP
client->response.append(CRLF);
client->response.append(CRLF);
// WIP https://www.rfc-editor.org/rfc/rfc9110.html#section-9.3.3-4
}
}

View File

@@ -25,7 +25,7 @@ void Webserv::_request(Client *client)
}
else if (ret == READ_COMPLETE)
{
if (client->body_complete)
if (client->body_complete && client->get_rq_multi_bodys().empty()) // DEBUG
std::cerr << "______BODY\n" << client->get_rq_body() << "\n______\n"; // DEBUG
_epoll_update(client->get_cl_fd(), EPOLLOUT, EPOLL_CTL_MOD);
client->request_complete = true;

View File

@@ -21,7 +21,10 @@ void Webserv::_response(Client *client)
}
else if (ret == SEND_COMPLETE)
{
if (client->get_rq_headers("Connection") == "close" || client->status == 408)
if (client->get_rq_headers("Connection") == "close"
|| client->status == 400 // TODO: Refactoring
|| client->status == 408
|| client->status == 413)
_close_client(client->get_cl_fd());
else
{
@@ -61,7 +64,10 @@ void Webserv::_append_base_headers(Client *client)
{
client->response.append("Server: Webserv/0.1" CRLF);
if (client->get_rq_headers("Connection") == "close")
if (client->get_rq_headers("Connection") == "close"
|| client->status == 400 // TODO: Refactoring
|| client->status == 408
|| client->status == 413)
client->response.append("Connection: close" CRLF);
else
client->response.append("Connection: keep-alive" CRLF);

View File

@@ -12,7 +12,12 @@ void Webserv::_timeout()
std::cerr << "timeout request fd " << it->get_cl_fd() << "\n";
it->status = 408;
_epoll_update(it->get_cl_fd(), EPOLLOUT, EPOLL_CTL_MOD);
// DEBUG, close without repsonse 408
/* _close_client(it->get_cl_fd());
it = _clients.begin(); */
}
// else // DEBUG
++it;
}
}