wip integration of client.request and ServerConfig
+ Client get return reference + wip binary flags for http_method + moved config parser files
This commit is contained in:
7
Makefile
7
Makefile
@@ -12,10 +12,13 @@ CXXFLAGS += -MMD -MP #header dependencie
|
||||
VPATH = $(SRCS_D)
|
||||
|
||||
HEADERS_D = srcs \
|
||||
srcs/webserv
|
||||
srcs/webserv \
|
||||
srcs/config
|
||||
|
||||
SRCS_D = srcs \
|
||||
srcs/webserv
|
||||
srcs/webserv \
|
||||
srcs/config
|
||||
|
||||
SRCS = main.cpp \
|
||||
base.cpp init.cpp close.cpp epoll_update.cpp signal.cpp \
|
||||
accept.cpp request.cpp response.cpp \
|
||||
|
||||
13
memo.txt
13
memo.txt
@@ -1,7 +1,14 @@
|
||||
- un thread par serveur présent dans le fichier de config ?
|
||||
|
||||
----------------
|
||||
|
||||
----------------
|
||||
- http_method en mode binary flags. "std::vector<http_method> allow_methods" -> "unsigned int allow_methods;"
|
||||
- Dans le parsing, trier les "locations" par ordre de precision.
|
||||
Compter les "/" dans le chemin, les locations avec le plus de "/" seront en premier dans le vector.
|
||||
- Il faut vérifier le path de la requête, voir si le serveur est bien censé délivrer cette ressource et si le client y a accès, avant d'appeler le CGI.
|
||||
|
||||
|
||||
__________________________
|
||||
--------------------------
|
||||
|
||||
----Discord 42------------
|
||||
Un truc cool et surtout bien utile ici c'est d'utiliser un proxy entre ton navigateur et ton serveur pour vérifier ce qui est envoyé en raw. Les navigateurs peuvent avoir des comportements différents.
|
||||
Vous avez des modules sur vos navigateur ou des logiciels externe. C'est assez rapide et gratuit.
|
||||
@@ -49,11 +49,11 @@ void Client::parse_request()
|
||||
|
||||
|
||||
|
||||
std::string Client::get_method() { return _request.method; }
|
||||
std::string Client::get_path() { return _request.path; }
|
||||
std::string Client::get_version() { return _request.version; }
|
||||
std::string Client::get_body() { return _request.body; }
|
||||
std::string Client::get_headers(std::string key) { return _request.headers[key]; }
|
||||
std::string &Client::get_method() { return _request.method; }
|
||||
std::string &Client::get_path() { return _request.path; }
|
||||
std::string &Client::get_version() { return _request.version; }
|
||||
std::string &Client::get_body() { return _request.body; }
|
||||
std::string &Client::get_headers(const std::string &key) { return _request.headers[key]; }
|
||||
|
||||
/*********************************************
|
||||
* PRIVATE MEMBER FUNCTIONS
|
||||
|
||||
@@ -30,11 +30,12 @@ class Client
|
||||
std::string response;
|
||||
unsigned int status;
|
||||
|
||||
std::string get_method();
|
||||
std::string get_path();
|
||||
std::string get_version();
|
||||
std::string get_body();
|
||||
std::string get_headers(std::string key);
|
||||
// const functions ?
|
||||
std::string &get_method();
|
||||
std::string &get_path();
|
||||
std::string &get_version();
|
||||
std::string &get_body();
|
||||
std::string &get_headers(const std::string &key);
|
||||
|
||||
void parse_request();
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2022/07/13 22:11:17 by me #+# #+# */
|
||||
/* Updated: 2022/08/02 14:05:03 by lperrey ### ########.fr */
|
||||
/* Updated: 2022/08/02 19:21:49 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -263,7 +263,7 @@ void ConfigParser::_set_server_values(ServerConfig *server, \
|
||||
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
||||
{
|
||||
http_method m = _str_to_method_type(tmp_val[i]);
|
||||
if (m == 3)
|
||||
if (m == INVALID)
|
||||
throw std::invalid_argument("not a valid method");
|
||||
server->allow_methods.push_back(m);
|
||||
}
|
||||
@@ -348,7 +348,7 @@ void ConfigParser::_set_location_values(LocationConfig *location, \
|
||||
for (unsigned long i = 0; i != tmp_val.size(); i++)
|
||||
{
|
||||
http_method m = _str_to_method_type(tmp_val[i]);
|
||||
if (m == 3)
|
||||
if (m == INVALID)
|
||||
throw std::invalid_argument("not a valid method");
|
||||
location->allow_methods.push_back(m);
|
||||
}
|
||||
@@ -7,12 +7,20 @@
|
||||
# include <sstream>
|
||||
# include <cstdlib> // atoi
|
||||
|
||||
// enum http_method
|
||||
// {
|
||||
// GET = 0b000001,
|
||||
// POST = 0b000010,
|
||||
// DELETE = 0b000100,
|
||||
// INVALID = 0b001000,
|
||||
// };
|
||||
|
||||
enum http_method
|
||||
{
|
||||
GET = 1,
|
||||
POST,
|
||||
DELETE,
|
||||
INVALID,
|
||||
POST = 1 << 1,
|
||||
DELETE = 1 << 2,
|
||||
INVALID = 1 << 3,
|
||||
};
|
||||
|
||||
std::vector<std::string> split(std::string input, char delimiter);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
// # include <netinet/ip.h> // usefull for what ? -> 'man (7) ip' says it's a superset of 'netinet/in.h'
|
||||
# include <algorithm> // find
|
||||
# include <string> // string
|
||||
# include <cstdio> // perror
|
||||
# include <cstdio> // perror, remove
|
||||
# include <cstdlib> // atoi (athough it's already cover by <string>)
|
||||
|
||||
# include "Client.hpp"
|
||||
@@ -68,10 +68,11 @@ class Webserv
|
||||
void _read_request(Client *client);
|
||||
// response.cpp
|
||||
void _response(Client *client);
|
||||
void _send_response(Client *client);
|
||||
void _construct_response(Client *client);
|
||||
void _insert_status_line(Client *client);
|
||||
void _get_ressource(Client *client);
|
||||
ServerConfig &_determine_process_server(Client *client);
|
||||
void _send_response(Client *client, ServerConfig &server);
|
||||
void _construct_response(Client *client, ServerConfig &server);
|
||||
void _insert_status_line(Client *client, ServerConfig &server);
|
||||
void _get_ressource(Client *client, ServerConfig &server);
|
||||
// cgi_script.cpp
|
||||
bool _is_cgi(Client *client);
|
||||
void _exec_cgi(Client *client);
|
||||
|
||||
@@ -6,7 +6,7 @@ void Webserv::_close_client(int fd)
|
||||
std::vector<Client>::iterator it = _clients.begin();
|
||||
while (it != _clients.end())
|
||||
{
|
||||
if (it->fd == fd)
|
||||
if (*it == fd)
|
||||
{
|
||||
// _epoll_update(fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG
|
||||
if (::close(fd) == -1)
|
||||
|
||||
@@ -3,25 +3,48 @@
|
||||
|
||||
void Webserv::_response(Client *client)
|
||||
{
|
||||
_send_response(client);
|
||||
ServerConfig &server = _determine_process_server(client);
|
||||
_send_response(client, server);
|
||||
if (g_last_signal)
|
||||
_handle_last_signal();
|
||||
}
|
||||
|
||||
void Webserv::_send_response(Client *client)
|
||||
ServerConfig &Webserv::_determine_process_server(Client *client)
|
||||
{
|
||||
/*
|
||||
TODO : determine virtual server based on ip_address::port and server_name
|
||||
Ior now its just based on server_name.
|
||||
(maybe with a map< string, std::vector<ServerConfig> > where the string is "ip_adress::port")
|
||||
http://nginx.org/en/docs/http/request_processing.html
|
||||
*/
|
||||
|
||||
std::string &server_name = client->get_headers("Host");
|
||||
std::vector<ServerConfig>::iterator it = _servers.begin();
|
||||
while (it != _servers.end())
|
||||
{
|
||||
if ( std::find(it->server_name.begin(), it->server_name.end(), server_name) != it->server_name.end() )
|
||||
break;
|
||||
++it;
|
||||
}
|
||||
if (it != _servers.end())
|
||||
return (*it);
|
||||
else
|
||||
return (_servers.front());
|
||||
}
|
||||
|
||||
void Webserv::_send_response(Client *client, ServerConfig &server)
|
||||
{
|
||||
ssize_t ret;
|
||||
|
||||
std::cerr << "send()\n";
|
||||
std::cerr << "RAW_REQUEST\n|\n" << client->raw_request << "|\n"; // DEBUG
|
||||
// std::cerr << "RAW_REQUEST\n|\n" << client->raw_request << "|\n"; // DEBUG
|
||||
|
||||
_construct_response(client);
|
||||
_construct_response(client, server);
|
||||
|
||||
ret = ::send(client->fd, client->response.data(), client->response.size(), 0);
|
||||
ret = ::send(client->fd, client->response.c_str(), 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 ;
|
||||
@@ -37,25 +60,29 @@ void Webserv::_send_response(Client *client)
|
||||
}
|
||||
}
|
||||
|
||||
void Webserv::_construct_response(Client *client)
|
||||
void Webserv::_construct_response(Client *client, ServerConfig &server)
|
||||
{
|
||||
client->status = 200;
|
||||
client->response.append("Server: Webserv/0.1\r\n");
|
||||
|
||||
if (client->raw_request.find("Connection: close") != std::string::npos)
|
||||
if (client->get_headers("Connection") == "close")
|
||||
client->response.append("Connection: close\r\n");
|
||||
else
|
||||
client->response.append("Connection: keep-alive\r\n");
|
||||
|
||||
_get_ressource(client);
|
||||
// TODO : Method switch (GET, POST, DELETE)
|
||||
_get_ressource(client, server);
|
||||
|
||||
_insert_status_line(client);
|
||||
_insert_status_line(client, server);
|
||||
}
|
||||
|
||||
#define E400 "\r\n<!DOCTYPE html><html><head><title>400 Bad Request</title></head><body><h1 style=\"text-align:center\">400 Bad Request</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>"
|
||||
#define E404 "\r\n<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1 style=\"text-align:center\">404 Not Found</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>"
|
||||
#define E500 "\r\n<!DOCTYPE html><html><head><title>500 Internal Server Error</title></head><body><h1 style=\"text-align:center\">500 Internal Server Error</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>"
|
||||
void Webserv::_insert_status_line(Client *client)
|
||||
// https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
|
||||
#define HTML_ERROR(STATUS) "\r\n<!DOCTYPE html><html><head><title>"STATUS"</title></head><body><h1 style=\"text-align:center\">"STATUS"</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>"
|
||||
#define S200 "200 OK"
|
||||
#define S400 "400 Bad Request"
|
||||
#define S404 "404 Not Found"
|
||||
#define S500 "500 Internal Server Error"
|
||||
void Webserv::_insert_status_line(Client *client, ServerConfig &server)
|
||||
{
|
||||
std::string status_line;
|
||||
|
||||
@@ -64,19 +91,19 @@ void Webserv::_insert_status_line(Client *client)
|
||||
switch (client->status)
|
||||
{
|
||||
case (200):
|
||||
status_line.append("200 OK");
|
||||
status_line.append(S200);
|
||||
break;
|
||||
case (400):
|
||||
status_line.append("400 Not Found");
|
||||
client->response.append(E400);
|
||||
status_line.append(S400);
|
||||
client->response.append(HTML_ERROR(S400));
|
||||
break;
|
||||
case (404):
|
||||
status_line.append("404 Not Found");
|
||||
client->response.append(E404);
|
||||
status_line.append(S404);
|
||||
client->response.append(HTML_ERROR(S404));
|
||||
break;
|
||||
case (500):
|
||||
status_line.append("500 Internal Server Error");
|
||||
client->response.append(E500);
|
||||
status_line.append(S500);
|
||||
client->response.append(HTML_ERROR(S500));
|
||||
break;
|
||||
}
|
||||
status_line.append("\r\n");
|
||||
@@ -87,11 +114,18 @@ void Webserv::_insert_status_line(Client *client)
|
||||
#define ROOT "www"
|
||||
#define INDEX "index.html"
|
||||
#define MAX_FILESIZE 1000000 // (1Mo)
|
||||
void Webserv::_get_ressource(Client *client)
|
||||
void Webserv::_get_ressource(Client *client, ServerConfig &server)
|
||||
{
|
||||
std::ifstream ifd; // For chunk, ifstream directly in struct CLient for multiples read without close() ?
|
||||
char buf[MAX_FILESIZE+1];
|
||||
std::string tmp;
|
||||
std::string path = client->get_path();
|
||||
|
||||
if (path == "/") // TODO ; With server config
|
||||
path.append(INDEX);
|
||||
path.insert(0, ROOT);
|
||||
|
||||
std::cerr << "path = " << path << "\n";
|
||||
|
||||
// TMP HUGO
|
||||
//
|
||||
@@ -103,32 +137,15 @@ void Webserv::_get_ressource(Client *client)
|
||||
//
|
||||
// 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)
|
||||
|
||||
if (access(path.c_str(), 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 ?)
|
||||
ifd.open(path.c_str(), std::ios::binary | std::ios::ate); // std::ios::binary (binary for files like images ?)
|
||||
if (!ifd)
|
||||
{
|
||||
std::cerr << path << ": open fail" << '\n';
|
||||
@@ -151,7 +168,7 @@ void Webserv::_get_ressource(Client *client)
|
||||
ifd.read(buf, size);
|
||||
buf[ifd.gcount()] = '\0';
|
||||
|
||||
client->response.append("Content-Type: text/html; charset=UTF-8\r\n");
|
||||
client->response.append("Content-Type: text/html; charset=UTF-8\r\n"); // TODO : determine Content-Type
|
||||
|
||||
client->response.append("Content-Length: ");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user