#include "Webserv.hpp" void Webserv::_response(Client *client) { _send_response(client); if (g_last_signal) _handle_last_signal(); } void Webserv::_send_response(Client *client) { ssize_t ret; std::cerr << "send()\n"; std::cerr << "RAW_REQUEST\n|\n" << client->raw_request << "|\n"; // DEBUG _construct_response(client); ret = ::send(client->fd, client->response.data(), client->response.size(), 0); if (ret == -1) { std::perror("err send()"); std::cerr << "client ptr =" << client << "\n"; // DEBUG std::cerr << "client.fd =" << client->fd << "\n"; // DEBUG _close_client(client->fd); return ; } if (client->raw_request.find("Connection: close") != std::string::npos) _close_client(client->fd); else { _epoll_update(client->fd, EPOLLIN, EPOLL_CTL_MOD); client->raw_request.clear(); client->response.clear(); } } void Webserv::_construct_response(Client *client) { client->status = 200; client->response.append("Server: Webserv/0.1\r\n"); if (client->raw_request.find("Connection: close") != std::string::npos) client->response.append("Connection: close\r\n"); else client->response.append("Connection: keep-alive\r\n"); _get_ressource(client); _insert_status_line(client); } #define E400 "\r\n
Le Webserv/0.1
" #define E404 "\r\nLe Webserv/0.1
" #define E500 "\r\nLe Webserv/0.1
" void Webserv::_insert_status_line(Client *client) { std::string status_line; status_line.append("HTTP/1.1 "); // WIP, maybe make a map for status response switch (client->status) { case (200): status_line.append("200 OK"); break; case (400): status_line.append("400 Not Found"); client->response.append(E400); break; case (404): status_line.append("404 Not Found"); client->response.append(E404); break; case (500): status_line.append("500 Internal Server Error"); client->response.append(E500); break; } status_line.append("\r\n"); client->response.insert(0, status_line); } #define ROOT "website" #define INDEX "index.html" #define MAX_FILESIZE 1000000 // (1Mo) void Webserv::_get_ressource(Client *client) { std::ifstream ifd; // For chunk, ifstream directly in struct CLient for multiples read without close() ? char buf[MAX_FILESIZE+1]; std::string tmp; // TMP HUGO // if (_is_cgi(client)) { _exec_cgi(client); return; } // // END TMP HUGO // Mini parsing à l'arrache du PATH std::string path; try { path = client->raw_request.substr(0, client->raw_request.find("\r\n")); path = path.substr(0, path.rfind(" ")); path = path.substr(path.find("/")); if (path == "/") path.append(INDEX); path.insert(0, ROOT); } catch (std::out_of_range& e) { std::cout << e.what() << '\n'; client->status = 400; return ; } if (access(path.data(), R_OK) == -1) { std::perror("err access()"); client->status = 404; return ; } ifd.open(path.data(), std::ios::binary | std::ios::ate); // std::ios::binary (binary for files like images ?) if (!ifd) { std::cerr << path << ": open fail" << '\n'; client->status = 500; } else { // WIP : Chunk or not chunk (if filesize too big) std::streampos size = ifd.tellg(); if (size > MAX_FILESIZE) { // Then chunk client->status = 500; // WIP temp std::cerr << "File too large for non chunk body\n"; ifd.close(); return ; } ifd.seekg(0, std::ios::beg); ifd.read(buf, size); buf[ifd.gcount()] = '\0'; client->response.append("Content-Type: text/html; charset=UTF-8\r\n"); client->response.append("Content-Length: "); tmp = ::itos(ifd.gcount()); client->response.append(tmp.c_str()); client->response.append("\r\n"); // Body client->response.append("\r\n"); client->response.append(buf); ifd.close(); } }