Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53a548e314 | ||
|
|
3dad938e3c | ||
|
|
ae9a9b37f1 | ||
|
|
e1a68bc3e4 |
3
Makefile
3
Makefile
@@ -5,7 +5,7 @@ CXX = c++
|
|||||||
CXXFLAGS = -Wall -Wextra #-Werror
|
CXXFLAGS = -Wall -Wextra #-Werror
|
||||||
CXXFLAGS += $(HEADERS_D:%=-I%)
|
CXXFLAGS += $(HEADERS_D:%=-I%)
|
||||||
CXXFLAGS += -std=c++98
|
CXXFLAGS += -std=c++98
|
||||||
CXXFLAGS += -g
|
CXXFLAGS += -g3
|
||||||
CXXFLAGS += -MMD -MP #header dependencie
|
CXXFLAGS += -MMD -MP #header dependencie
|
||||||
#CXXFLAGS += -O3
|
#CXXFLAGS += -O3
|
||||||
|
|
||||||
@@ -29,6 +29,7 @@ SRCS = main.cpp \
|
|||||||
utils.cpp \
|
utils.cpp \
|
||||||
cgi_script.cpp \
|
cgi_script.cpp \
|
||||||
Client.cpp \
|
Client.cpp \
|
||||||
|
parsing_message_http.cpp \
|
||||||
|
|
||||||
OBJS_D = builds
|
OBJS_D = builds
|
||||||
OBJS = $(SRCS:%.cpp=$(OBJS_D)/%.o)
|
OBJS = $(SRCS:%.cpp=$(OBJS_D)/%.o)
|
||||||
|
|||||||
24
README.md
24
README.md
@@ -1,23 +1,33 @@
|
|||||||
|
|
||||||
## work together
|
## work together
|
||||||
|
|
||||||
|
#### message
|
||||||
|
- err access line response.cpp:169
|
||||||
|
- g pas fini la gestion de sortie du cgi (comparaison des headers fields pour supprimer les doublons)
|
||||||
|
- g rendu independantes les fonctions qui parses un message http (requete ou response) dans `parsing_http_message.cpp`
|
||||||
|
- il y a une erreur importante dans la fonction qui parse les headers d'un message http : ca ne verifie pas si la premier ligne est un header ou la "first line"
|
||||||
|
|
||||||
|
#### TODO
|
||||||
|
- `_is_cgi()` and `_fill_cgi_path()`
|
||||||
|
- `_cgi_output()` change status in `client->status`
|
||||||
|
- two cgi tests :
|
||||||
|
? - a basic form with "name" and "something", that return a html page with that
|
||||||
|
? - for GET and POST
|
||||||
|
? - a script called by a file extension in URI
|
||||||
|
|
||||||
#### output cgi script :
|
#### output cgi script :
|
||||||
! TODO : change all the '\n' by '\r\n'
|
! TODO : change all the '\n' by '\r\n'
|
||||||
! TODO : there is at least one header field followed by '\r\n\r\n' :
|
! TODO : there is at least one header field followed by '\r\n\r\n' :
|
||||||
- "Content-Type"
|
- "Content-Type"
|
||||||
- "Location"
|
- "Location"
|
||||||
- "Status"
|
- "Status"
|
||||||
-> TODO : there is no field duplicate (resolve conflicts)
|
|
||||||
-> TODO : if status field, change server status for this one
|
|
||||||
! TODO : there is no space between filed name and ":"
|
! TODO : there is no space between filed name and ":"
|
||||||
! TODO : if no Location field && no Status field -> status code = 200
|
|
||||||
! TODO?: handle Location field, either :
|
! TODO?: handle Location field, either :
|
||||||
- local : start with '/' --> rerun the request with new uri
|
- local : start with '/' --> rerun the request with new uri
|
||||||
- client : start with '<scheme>:' --> send back status code 302
|
- client : start with '<scheme>:' --> send back status code 302
|
||||||
|
-> TODO : there is no field duplicate (resolve conflicts)
|
||||||
#### what cgi ?
|
-> TODO : if status field, change server status for this one
|
||||||
- a basic form with "name" and "something", that return a html page with that
|
-> TODO : if no Location field && no Status field -> status code = 200
|
||||||
- a script called by a file extension in URI
|
|
||||||
|
|
||||||
#### questions
|
#### questions
|
||||||
- in client.cpp i fill the port, is there a default one in case it's not in the request ?
|
- in client.cpp i fill the port, is there a default one in case it's not in the request ?
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ server {
|
|||||||
location /board {
|
location /board {
|
||||||
allow_methods GET;
|
allow_methods GET;
|
||||||
root ./www/html;
|
root ./www/html;
|
||||||
|
cgi_ext php cgi
|
||||||
}
|
}
|
||||||
|
|
||||||
location /board/content {
|
location /board/content {
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ Client::~Client() {
|
|||||||
Client::Client( Client const & src )
|
Client::Client( Client const & src )
|
||||||
: body_size(0)
|
: body_size(0)
|
||||||
, status(0)
|
, status(0)
|
||||||
, _fd ( src.get_cl_fd() )
|
, _fd ( src._fd )
|
||||||
, _port ( src.get_cl_port() )
|
, _port ( src._port )
|
||||||
, _ip ( src.get_cl_ip() )
|
, _ip ( src._ip )
|
||||||
, _lsocket ( src.get_cl_lsocket() )
|
, _lsocket ( src._lsocket )
|
||||||
{
|
{
|
||||||
raw_request = src.raw_request;
|
raw_request = src.raw_request;
|
||||||
response = src.response;
|
response = src.response;
|
||||||
@@ -70,22 +70,15 @@ Client & Client::operator=( Client const & rhs )
|
|||||||
// https://www.tutorialspoint.com/http/http_requests.htm
|
// https://www.tutorialspoint.com/http/http_requests.htm
|
||||||
void Client::parse_request()
|
void Client::parse_request()
|
||||||
{
|
{
|
||||||
std::string sub;
|
std::map<std::string, std::string> headers;
|
||||||
std::vector<std::string> list;
|
std::string body;
|
||||||
size_t pos;
|
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
std::cout << "\nREQUEST _____________________\n"
|
std::cout << "\nREQUEST ____________\n" << raw_request << "\n_____________\n";
|
||||||
<< raw_request
|
|
||||||
<< "\n\n";
|
|
||||||
|
|
||||||
pos = (raw_request).find(CRLF CRLF);
|
_parse_request_line();
|
||||||
sub = (raw_request).substr(0, pos);
|
_parse_request_headers();
|
||||||
list = split(sub, '\n');
|
_parse_request_body();
|
||||||
_parse_request_line(*list.begin());
|
|
||||||
list.erase(list.begin());
|
|
||||||
_parse_request_headers(list);
|
|
||||||
_parse_request_body(pos + 4);
|
|
||||||
_parse_port_hostname(this->get_rq_headers("Host"));
|
_parse_port_hostname(this->get_rq_headers("Host"));
|
||||||
raw_request.clear();
|
raw_request.clear();
|
||||||
}
|
}
|
||||||
@@ -176,30 +169,24 @@ std::string Client::get_rq_headers(const std::string & key) const
|
|||||||
* PRIVATE MEMBER FUNCTIONS
|
* PRIVATE MEMBER FUNCTIONS
|
||||||
*********************************************/
|
*********************************************/
|
||||||
|
|
||||||
void Client::_parse_request_line( std::string rline )
|
void Client::_parse_request_line()
|
||||||
{
|
{
|
||||||
std::vector<std::string> sline;
|
std::vector<std::string> line;
|
||||||
std::string tmp;
|
int ret;
|
||||||
|
|
||||||
sline = split(rline, ' ');
|
ret = ::parse_http_first_line(raw_request, line);
|
||||||
if (sline.size() != 3)
|
if (ret != 3)
|
||||||
{
|
{
|
||||||
std::cerr << "err _parse_request_line(): ";
|
std::cerr << "err _parse_first_line(): wrong number of elements (" << ret << " instead of 3)\n";
|
||||||
throw std::runtime_error("bad request-line header");
|
status = 400; // "bad request"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_request.method = str_to_http_method(line[0]);
|
||||||
|
_request.uri = line[1];
|
||||||
|
_parse_request_uri(line[1]);
|
||||||
|
_request.version = line[2];
|
||||||
}
|
}
|
||||||
// method
|
|
||||||
tmp = ::trim(sline[0], ' ');
|
|
||||||
tmp = ::trim(tmp, '\r');
|
|
||||||
_request.method = str_to_http_method(tmp);
|
|
||||||
// uri
|
|
||||||
tmp = ::trim(sline[1], ' ');
|
|
||||||
tmp = ::trim(tmp, '\r');
|
|
||||||
_request.uri = tmp;
|
|
||||||
_parse_request_uri( tmp );
|
|
||||||
// http version
|
|
||||||
tmp = ::trim(sline[2], ' ');
|
|
||||||
tmp = ::trim(tmp, '\r');
|
|
||||||
_request.version = tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::_parse_request_uri( std::string uri )
|
void Client::_parse_request_uri( std::string uri )
|
||||||
@@ -214,32 +201,16 @@ void Client::_parse_request_uri( std::string uri )
|
|||||||
_request.abs_path = uri.substr(0, pos);
|
_request.abs_path = uri.substr(0, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::_parse_request_headers( std::vector<std::string> list )
|
void Client::_parse_request_headers()
|
||||||
{
|
{
|
||||||
std::string key;
|
// TODO: check error and adjust status
|
||||||
std::string val;
|
_request.headers = ::parse_http_headers(raw_request);
|
||||||
std::vector<std::string>::iterator it;
|
|
||||||
size_t pos;
|
|
||||||
|
|
||||||
for (it = list.begin(); it != list.end(); it++)
|
|
||||||
{
|
|
||||||
pos = (*it).find(':');
|
|
||||||
key = (*it).substr( 0, pos );
|
|
||||||
key = ::trim(key, ' ');
|
|
||||||
key = ::trim(key, '\r');
|
|
||||||
key = ::str_tolower(key);
|
|
||||||
val = (*it).substr( pos + 1 );
|
|
||||||
val = ::trim(val, ' ');
|
|
||||||
val = ::trim(val, '\r');
|
|
||||||
_request.headers.insert( std::pair<std::string, std::string>(key, val) );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::_parse_request_body( size_t pos )
|
void Client::_parse_request_body()
|
||||||
{
|
{
|
||||||
std::string body = &raw_request[pos];
|
// TODO: check error and adjust status
|
||||||
|
_request.body = ::parse_http_body(raw_request);
|
||||||
_request.body = body;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::_parse_port_hostname(std::string host)
|
void Client::_parse_port_hostname(std::string host)
|
||||||
@@ -247,10 +218,7 @@ void Client::_parse_port_hostname(std::string host)
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
|
|
||||||
if (host == "")
|
if (host == "")
|
||||||
{
|
|
||||||
std::cerr << "no host\n";
|
std::cerr << "no host\n";
|
||||||
throw std::runtime_error("no host in request");
|
|
||||||
}
|
|
||||||
|
|
||||||
pos = host.find(':');
|
pos = host.find(':');
|
||||||
// port :
|
// port :
|
||||||
|
|||||||
@@ -7,9 +7,10 @@
|
|||||||
# include <map>
|
# include <map>
|
||||||
# include <vector>
|
# include <vector>
|
||||||
# include <string.h> // strdup
|
# include <string.h> // strdup
|
||||||
# include "utils.hpp"
|
|
||||||
# include <netinet/in.h> // sockaddr_in, struct in_addr
|
# include <netinet/in.h> // sockaddr_in, struct in_addr
|
||||||
# include <arpa/inet.h> // htonl, htons, ntohl, ntohs, inet_addr, inet_ntoa
|
# include <arpa/inet.h> // htonl, htons, ntohl, ntohs, inet_addr, inet_ntoa
|
||||||
|
# include "utils.hpp"
|
||||||
|
# include "parsing_message_http.hpp"
|
||||||
|
|
||||||
struct Script
|
struct Script
|
||||||
{
|
{
|
||||||
@@ -74,16 +75,16 @@ class Client
|
|||||||
bool fill_script_path(std::string script);
|
bool fill_script_path(std::string script);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const int _fd;
|
int _fd;
|
||||||
const std::string _port;
|
std::string _port;
|
||||||
const std::string _ip;
|
std::string _ip;
|
||||||
const listen_socket * _lsocket;
|
listen_socket * _lsocket;
|
||||||
struct Request _request;
|
struct Request _request;
|
||||||
|
|
||||||
void _parse_request_line( std::string rline );
|
void _parse_request_line();
|
||||||
|
void _parse_request_headers();
|
||||||
|
void _parse_request_body();
|
||||||
void _parse_request_uri( std::string uri );
|
void _parse_request_uri( std::string uri );
|
||||||
void _parse_request_headers( std::vector<std::string> list );
|
|
||||||
void _parse_request_body( size_t pos );
|
|
||||||
void _parse_port_hostname(std::string host);
|
void _parse_port_hostname(std::string host);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#! /usr/bin/php
|
#! /usr/bin/php
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
|
echo "Status: 200\r\n";
|
||||||
|
echo "\r\n";
|
||||||
echo "BEGIN PHP-CGI\n-----------\n\n";
|
echo "BEGIN PHP-CGI\n-----------\n\n";
|
||||||
//phpinfo();
|
|
||||||
|
|
||||||
echo "AUTH_TYPE: " . getenv("AUTH_TYPE");
|
echo "AUTH_TYPE: " . getenv("AUTH_TYPE");
|
||||||
echo "\nCONTENT_LENGTH: " . getenv("CONTENT_LENGTH");
|
echo "\nCONTENT_LENGTH: " . getenv("CONTENT_LENGTH");
|
||||||
echo "\nCONTENT_TYPE: " . getenv("CONTENT_TYPE");
|
echo "\nCONTENT_TYPE: " . getenv("CONTENT_TYPE");
|
||||||
|
|||||||
@@ -15,8 +15,19 @@ std::vector<std::string> split(std::string input, char delimiter)
|
|||||||
|
|
||||||
std::string trim(std::string str, char c)
|
std::string trim(std::string str, char c)
|
||||||
{
|
{
|
||||||
str = str.substr(str.find_first_not_of(c));
|
size_t pos;
|
||||||
str = str.substr(0, str.find_last_not_of(c) + 1);
|
|
||||||
|
// delete leadings c
|
||||||
|
pos = str.find_first_not_of(c);
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
return str;
|
||||||
|
str = str.substr(pos);
|
||||||
|
|
||||||
|
// delete endings c
|
||||||
|
pos = str.find_last_not_of(c);
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
return str;
|
||||||
|
str = str.substr(0, pos + 1);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@@ -100,15 +111,37 @@ void replace_all_substr(std::string &str, const std::string &ori_substr, const s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const listen_socket& lhs, int fd)
|
|
||||||
{ return lhs.fd == fd; }
|
|
||||||
|
|
||||||
bool operator==(int fd, const listen_socket& rhs)
|
|
||||||
{ return fd == rhs.fd; }
|
|
||||||
|
|
||||||
std::string str_tolower(std::string str)
|
std::string str_tolower(std::string str)
|
||||||
{
|
{
|
||||||
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void del_line_in_str(std::string * str, size_t pos, std::string delim)
|
||||||
|
{
|
||||||
|
size_t begin;
|
||||||
|
size_t end;
|
||||||
|
|
||||||
|
begin = (*str).rfind(delim, pos);
|
||||||
|
if (begin == std::string::npos)
|
||||||
|
begin = 0;
|
||||||
|
else
|
||||||
|
begin += delim.size();
|
||||||
|
|
||||||
|
end = (*str).find(delim, pos);
|
||||||
|
if (end == std::string::npos)
|
||||||
|
end = 0;
|
||||||
|
else
|
||||||
|
end += delim.size();
|
||||||
|
|
||||||
|
(*str).erase(begin, end - begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool operator==(const listen_socket& lhs, int fd)
|
||||||
|
{ return lhs.fd == fd; }
|
||||||
|
|
||||||
|
bool operator==(int fd, const listen_socket& rhs)
|
||||||
|
{ return fd == rhs.fd; }
|
||||||
|
|
||||||
|
|||||||
@@ -49,5 +49,6 @@ http_method str_to_http_method(std::string &str);
|
|||||||
std::string http_methods_to_str(unsigned int methods);
|
std::string http_methods_to_str(unsigned int methods);
|
||||||
void replace_all_substr(std::string &str, const std::string &ori_substr, const std::string &new_substr);
|
void replace_all_substr(std::string &str, const std::string &ori_substr, const std::string &new_substr);
|
||||||
std::string str_tolower(std::string str);
|
std::string str_tolower(std::string str);
|
||||||
|
void del_line_in_str(std::string * str, size_t pos, std::string delim);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -93,14 +93,16 @@ class Webserv
|
|||||||
|
|
||||||
ServerConfig &_determine_process_server(Client *client);
|
ServerConfig &_determine_process_server(Client *client);
|
||||||
LocationConfig &_determine_location(ServerConfig &server, std::string const &path);
|
LocationConfig &_determine_location(ServerConfig &server, std::string const &path);
|
||||||
void _response_correction(Client *client);
|
|
||||||
// cgi_script.cpp
|
// cgi_script.cpp
|
||||||
bool _is_cgi(Client *client);
|
bool _is_cgi(Client *client);
|
||||||
void _exec_cgi(Client *client);
|
std::string _exec_cgi(Client *client);
|
||||||
char** _set_env(Client *client);
|
char** _set_env(Client *client);
|
||||||
char* _dup_env(std::string var, std::string val);
|
char* _dup_env(std::string var, std::string val);
|
||||||
char* _dup_env(std::string var, int i);
|
char* _dup_env(std::string var, int i);
|
||||||
void _exec_script(Client *client, char **env);
|
std::string _exec_script(Client *client, char **env);
|
||||||
|
void _check_script_output(Client *client, std::string output);
|
||||||
|
void _check_script_status(Client *client, std::string output);
|
||||||
|
void _check_script_fields(Client *client, std::string output);
|
||||||
// epoll_update.cpp
|
// epoll_update.cpp
|
||||||
int _epoll_update(int fd, uint32_t events, int op);
|
int _epoll_update(int fd, uint32_t events, int op);
|
||||||
int _epoll_update(int fd, uint32_t events, int op, void *ptr);
|
int _epoll_update(int fd, uint32_t events, int op, void *ptr);
|
||||||
@@ -115,6 +117,7 @@ class Webserv
|
|||||||
void _listen(int socket_fd, unsigned int max_connections);
|
void _listen(int socket_fd, unsigned int max_connections);
|
||||||
void _init_http_status_map();
|
void _init_http_status_map();
|
||||||
void _init_mime_types_map();
|
void _init_mime_types_map();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,16 +11,19 @@ bool Webserv::_is_cgi(Client *client)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Webserv::_exec_cgi(Client *client)
|
std::string Webserv::_exec_cgi(Client *client)
|
||||||
{
|
{
|
||||||
char** env;
|
char** env;
|
||||||
|
std::string script_output;
|
||||||
|
|
||||||
env = _set_env(client);
|
env = _set_env(client);
|
||||||
_exec_script(client, env);
|
script_output = _exec_script(client, env);
|
||||||
|
|
||||||
for (int i = 0; env[i]; i++)
|
for (int i = 0; env[i]; i++)
|
||||||
delete[] env[i];
|
delete[] env[i];
|
||||||
delete[] env;
|
delete[] env;
|
||||||
|
|
||||||
|
return script_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Webserv::_dup_env(std::string var, std::string val = "")
|
char* Webserv::_dup_env(std::string var, std::string val = "")
|
||||||
@@ -49,7 +52,7 @@ char** Webserv::_set_env(Client *client)
|
|||||||
env[0] = _dup_env("AUTH_TYPE"); // authentification not supported
|
env[0] = _dup_env("AUTH_TYPE"); // authentification not supported
|
||||||
env[1] = _dup_env("CONTENT_LENGTH" , client->get_rq_body().size());
|
env[1] = _dup_env("CONTENT_LENGTH" , client->get_rq_body().size());
|
||||||
env[2] = _dup_env("CONTENT_TYPE" , client->get_rq_headers("Content-Type"));
|
env[2] = _dup_env("CONTENT_TYPE" , client->get_rq_headers("Content-Type"));
|
||||||
env[3] = _dup_env("GATEWAY_INTERFACE" , "CGI/1.0");
|
env[3] = _dup_env("GATEWAY_INTERFACE" , "CGI/1.1"); // https://www.rfc-editor.org/rfc/rfc3875
|
||||||
env[4] = _dup_env("PATH_INFO" , client->get_rq_script_info());
|
env[4] = _dup_env("PATH_INFO" , client->get_rq_script_info());
|
||||||
env[5] = _dup_env("PATH_TRANSLATED"); // not supported
|
env[5] = _dup_env("PATH_TRANSLATED"); // not supported
|
||||||
env[6] = _dup_env("QUERY_STRING" , client->get_rq_query());
|
env[6] = _dup_env("QUERY_STRING" , client->get_rq_query());
|
||||||
@@ -69,7 +72,7 @@ char** Webserv::_set_env(Client *client)
|
|||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Webserv::_exec_script(Client *client, char **env)
|
std::string Webserv::_exec_script(Client *client, char **env)
|
||||||
{
|
{
|
||||||
#define RD 0
|
#define RD 0
|
||||||
#define WR 1
|
#define WR 1
|
||||||
@@ -82,7 +85,7 @@ void Webserv::_exec_script(Client *client, char **env)
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
char buf[CGI_BUF_SIZE]; // WIP define buffer
|
char buf[CGI_BUF_SIZE]; // WIP define buffer
|
||||||
char * const * nll = NULL;
|
char * const * nll = NULL;
|
||||||
std::string response;
|
std::string script_output;
|
||||||
std::string body = client->get_rq_body();
|
std::string body = client->get_rq_body();
|
||||||
int fd_in[2];
|
int fd_in[2];
|
||||||
int fd_out[2];
|
int fd_out[2];
|
||||||
@@ -99,7 +102,11 @@ void Webserv::_exec_script(Client *client, char **env)
|
|||||||
close(FD_RD_FR_CHLD);
|
close(FD_RD_FR_CHLD);
|
||||||
dup2(FD_RD_FR_PRNT, STDIN_FILENO);
|
dup2(FD_RD_FR_PRNT, STDIN_FILENO);
|
||||||
dup2(FD_WR_TO_PRNT, STDOUT_FILENO);
|
dup2(FD_WR_TO_PRNT, STDOUT_FILENO);
|
||||||
|
// DEBUG
|
||||||
|
std::cerr << "execve:\n";
|
||||||
execve(client->get_rq_script_path().c_str(), nll, env);
|
execve(client->get_rq_script_path().c_str(), nll, env);
|
||||||
|
// for tests execve crash :
|
||||||
|
//execve("wrong", nll, env);
|
||||||
std::cerr << "execve crashed.\n";
|
std::cerr << "execve crashed.\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -113,19 +120,59 @@ void Webserv::_exec_script(Client *client, char **env)
|
|||||||
memset(buf, '\0', CGI_BUF_SIZE);
|
memset(buf, '\0', CGI_BUF_SIZE);
|
||||||
while (read(FD_RD_FR_CHLD, buf, CGI_BUF_SIZE - 1) > 0)
|
while (read(FD_RD_FR_CHLD, buf, CGI_BUF_SIZE - 1) > 0)
|
||||||
{
|
{
|
||||||
response += buf;
|
script_output += buf;
|
||||||
memset(buf, '\0', CGI_BUF_SIZE);
|
memset(buf, '\0', CGI_BUF_SIZE);
|
||||||
}
|
}
|
||||||
|
close(FD_RD_FR_CHLD);
|
||||||
|
}
|
||||||
|
if (script_output.empty())
|
||||||
|
script_output = "Status: 500\r\n\r\n";
|
||||||
|
return script_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Webserv::_check_script_output(Client *client, std::string output)
|
||||||
|
{
|
||||||
|
// TODO: it doesn't work with execve error, i don't know why yet ?
|
||||||
|
_check_script_status(client, output);
|
||||||
|
_check_script_fields(client, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Webserv::_check_script_status(Client *client, std::string output)
|
||||||
|
{
|
||||||
|
size_t pos;
|
||||||
|
int status_pos;
|
||||||
|
|
||||||
|
pos = output.find("Status:");
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
status_pos = pos + std::string("Status:").size();
|
||||||
|
client->status = atoi(output.c_str() + status_pos);
|
||||||
|
::del_line_in_str(&output, pos, CRLF);
|
||||||
|
}
|
||||||
|
client->status = 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Webserv::_check_script_fields(Client *client, std::string output)
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string> srv_fld; // server_field
|
||||||
|
std::map<std::string, std::string> scr_fld; // script_field
|
||||||
|
std::map<std::string, std::string>::iterator it_srv;
|
||||||
|
std::map<std::string, std::string>::iterator it_scr;
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
srv_fld = parse_http_headers(client->response);
|
||||||
|
scr_fld = parse_http_headers(output);
|
||||||
|
// wip: compare both map to supress duplicates
|
||||||
|
for (it_srv = srv_fld.begin(); it_srv != srv_fld.end(); it_srv++)
|
||||||
|
{
|
||||||
|
for (it_scr = scr_fld.begin(); it_scr != scr_fld.end(); it_scr++)
|
||||||
|
{
|
||||||
|
if (it_srv->first == it_scr->first)
|
||||||
|
{
|
||||||
|
pos = client->response.find(it_srv->first);
|
||||||
|
::del_line_in_str(&client->response, pos, CRLF);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (response.empty())
|
|
||||||
response = "Status: 500\r\n\r\n";
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
std::cout << "\n_______response_______\n"
|
|
||||||
<< response
|
|
||||||
<< "\n_____end response_____\n";
|
|
||||||
|
|
||||||
// TODO: see how this must be handled
|
|
||||||
client->response += response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
90
srcs/webserv/parsing_message_http.cpp
Normal file
90
srcs/webserv/parsing_message_http.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
|
||||||
|
#include "parsing_message_http.hpp"
|
||||||
|
|
||||||
|
size_t
|
||||||
|
parse_http_first_line(std::string message, std::vector<std::string> &line)
|
||||||
|
{
|
||||||
|
std::vector<std::string> sline;
|
||||||
|
std::string sub;
|
||||||
|
std::string tmp;
|
||||||
|
size_t pos;
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
// TODO: check for err in substr
|
||||||
|
pos = message.find(CRLF);
|
||||||
|
sub = message.substr(0, pos);
|
||||||
|
sline = ::split(sub, ' ');
|
||||||
|
ret = sline.size();
|
||||||
|
if (ret != 3)
|
||||||
|
return ret;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
tmp = ::trim(sline[i], ' ');
|
||||||
|
tmp = ::trim(tmp, '\r');
|
||||||
|
line.push_back(tmp);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, std::string>
|
||||||
|
parse_http_headers(std::string message)
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string> headers;
|
||||||
|
std::vector<std::string> list;
|
||||||
|
std::vector<std::string>::iterator it;
|
||||||
|
std::string sub;
|
||||||
|
std::string key;
|
||||||
|
std::string val;
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
pos = (message).find(CRLF CRLF);
|
||||||
|
sub = (message).substr(0, pos);
|
||||||
|
list = ::split(sub, '\n');
|
||||||
|
if ( maybe_http_first_line( *list.begin() ) )
|
||||||
|
list.erase(list.begin());
|
||||||
|
|
||||||
|
for (it = list.begin(); it != list.end(); it++)
|
||||||
|
{
|
||||||
|
// TODO: if pattern is not "NAME: value" return error
|
||||||
|
pos = (*it).find(':');
|
||||||
|
key = (*it).substr( 0, pos );
|
||||||
|
key = ::trim(key, ' ');
|
||||||
|
key = ::trim(key, '\r');
|
||||||
|
key = ::str_tolower(key);
|
||||||
|
val = (*it).substr( pos + 1 );
|
||||||
|
val = ::trim(val, ' ');
|
||||||
|
val = ::trim(val, '\r');
|
||||||
|
headers.insert( std::pair<std::string, std::string>(key, val) );
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
parse_http_body(std::string message)
|
||||||
|
{
|
||||||
|
std::string body;
|
||||||
|
size_t pos;
|
||||||
|
|
||||||
|
pos = message.find(CRLF CRLF);
|
||||||
|
pos += std::string(CRLF CRLF).size();
|
||||||
|
// TODO: copying just like that might fail in case of binary or images
|
||||||
|
body = message.substr(pos);
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool maybe_http_first_line(std::string str)
|
||||||
|
{
|
||||||
|
// method SP target SP version https://www.rfc-editor.org/rfc/rfc7230.html#section-3.1.1
|
||||||
|
// version SP status SP reason https://www.rfc-editor.org/rfc/rfc7230.html#section-3.1.2
|
||||||
|
|
||||||
|
std::vector<std::string> sline;
|
||||||
|
|
||||||
|
sline = ::split(str, ' ');
|
||||||
|
if (sline.size() != 3)
|
||||||
|
return false;
|
||||||
|
if (sline[0].find(':') != std::string::npos)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
36
srcs/webserv/parsing_message_http.hpp
Normal file
36
srcs/webserv/parsing_message_http.hpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
#ifndef PARSING_MESSAGE_HTTP_HPP
|
||||||
|
# define PARSING_MESSAGE_HTTP_HPP
|
||||||
|
|
||||||
|
# include <iostream>
|
||||||
|
# include <string>
|
||||||
|
# include <vector>
|
||||||
|
# include <map>
|
||||||
|
# include "utils.hpp"
|
||||||
|
|
||||||
|
size_t
|
||||||
|
parse_http_first_line(std::string message, std::vector<std::string> &line);
|
||||||
|
|
||||||
|
std::map<std::string, std::string>
|
||||||
|
parse_http_headers(std::string message);
|
||||||
|
|
||||||
|
std::string
|
||||||
|
parse_http_body(std::string message);
|
||||||
|
|
||||||
|
bool
|
||||||
|
maybe_http_first_line(std::string);
|
||||||
|
|
||||||
|
// http message structure :
|
||||||
|
//
|
||||||
|
// start-line
|
||||||
|
// request-line
|
||||||
|
// method SP target SP version
|
||||||
|
// response-line
|
||||||
|
// version SP status SP reason
|
||||||
|
// header-fields
|
||||||
|
// name ":" SP value
|
||||||
|
// CRLF
|
||||||
|
// body
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
2
srcs/webserv/parsing_request.cpp
Normal file
2
srcs/webserv/parsing_request.cpp
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include "parsing_request.hpp"
|
||||||
|
|
||||||
@@ -145,10 +145,15 @@ void Webserv::_get(Client *client, ServerConfig &server, LocationConfig &locatio
|
|||||||
|
|
||||||
// TMP HUGO
|
// TMP HUGO
|
||||||
//
|
//
|
||||||
|
std::string script_output;
|
||||||
if (_is_cgi(client))
|
if (_is_cgi(client))
|
||||||
{
|
{
|
||||||
_exec_cgi(client);
|
script_output = _exec_cgi(client);
|
||||||
_response_correction(client);
|
// DEBUG
|
||||||
|
std::cout << "\n____script_output____\n" << script_output << "\n_______________\n";
|
||||||
|
// wip check output of script
|
||||||
|
_check_script_output(client, script_output);
|
||||||
|
client->response += script_output;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@@ -224,12 +229,6 @@ void Webserv::_get_file(Client *client, const std::string &path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WIP HUGO
|
|
||||||
void Webserv::_response_correction(Client *client)
|
|
||||||
{
|
|
||||||
(void)client;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 char *body, size_t body_size, const std::string &file_extension)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|||||||
13
www/form_get.html
Normal file
13
www/form_get.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form method="get">
|
||||||
|
<input type="submit" value="submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
13
www/form_post.html
Normal file
13
www/form_post.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form method="post">
|
||||||
|
<input type="submit" value="submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
Reference in New Issue
Block a user