cgi exec compare with file method
This commit is contained in:
16
README.md
16
README.md
@@ -4,16 +4,24 @@
|
|||||||
- 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 ?
|
||||||
- timeout server but still works ?
|
- timeout server but still works ?
|
||||||
- path contains double "//" from `Webserv::_get()` in response.cpp
|
- path contains double "//" from `Webserv::_get()` in response.cpp
|
||||||
- how do we deal with cgi config default folder path or anything ?
|
- cgi path ? defined in config ? and root path ? :
|
||||||
|
- `Client.cpp : fill_script_path()`
|
||||||
|
- `cgi.cpp : is_cgi()`
|
||||||
|
- `cgi.cpp : set_env()`
|
||||||
|
- what if the uri contains a php file, and the config said php must be handled by cgi, but the path to this php in the uri is wrong ?
|
||||||
|
- is it ok ? `http://my_site.com/cgi-bin/php-cgi` (real path)
|
||||||
|
- is it ok ? `http://my_site.com/php-cgi` (reconstruct path ?)
|
||||||
|
- is it ok ? `http://my_site.com/something/php-cgi` (what about 'something' ?)
|
||||||
|
- is it ok ? `http://my_site.com/something/cgi-bin/php-cgi` (real path with 'something' before ? )
|
||||||
|
|
||||||
#### notifications
|
#### notifications
|
||||||
- i changed the Client getters in two categories :
|
- i changed the Client getters in two categories :
|
||||||
- getters for requests infos : `get_rq_<info>`
|
- getters for requests infos : `get_rq_<info>`
|
||||||
- getters for client sides infos : `get_cl_<info>` (such as ip of client)
|
- getters for client sides infos : `get_cl_<info>` (such as ip of client)
|
||||||
- i changed the variables in request struct in Client :
|
- i changed the variables in request struct in Client :
|
||||||
- `path` become `uri`....>(ex. `/path/to/file?var=val`)
|
- `path` become `uri` (ex. `/path/to/file?var=val`)
|
||||||
- add `abs_path`............>(ex. `/path/to/file `)
|
- add `abs_path` (ex. `/path/to/file` )
|
||||||
- add `query`................>(ex. ` var=val`)
|
- add `query` (ex. `var=val`)
|
||||||
- the header fields names, as key in map, are stored in lowercase, and getters are case-insensitives
|
- the header fields names, as key in map, are stored in lowercase, and getters are case-insensitives
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Client::Client( Client const & src )
|
|||||||
{
|
{
|
||||||
raw_request = src.raw_request;
|
raw_request = src.raw_request;
|
||||||
response = src.response;
|
response = src.response;
|
||||||
// buf = strdup(src.buf);
|
// buf = strdup(src.buf); // TODO: this doesn't work
|
||||||
body_size = src.body_size;
|
body_size = src.body_size;
|
||||||
status = src.status;
|
status = src.status;
|
||||||
return;
|
return;
|
||||||
@@ -75,14 +75,9 @@ void Client::parse_request()
|
|||||||
size_t pos;
|
size_t pos;
|
||||||
|
|
||||||
// DEBUG
|
// DEBUG
|
||||||
std::cout << "\n"
|
std::cout << "\nREQUEST _____________________\n"
|
||||||
<< "request:\n" << raw_request
|
|
||||||
<< "START _______________________\n\n"
|
|
||||||
<< raw_request
|
<< raw_request
|
||||||
<< "\nSCRIPT PATH _________________\n"
|
<< "\n\n";
|
||||||
<< "\npath:" << _request.script.path
|
|
||||||
<< "\npath_info:" << _request.script.info
|
|
||||||
<< "\n END _______________________\n";
|
|
||||||
|
|
||||||
pos = (raw_request).find(CRLF CRLF);
|
pos = (raw_request).find(CRLF CRLF);
|
||||||
sub = (raw_request).substr(0, pos);
|
sub = (raw_request).substr(0, pos);
|
||||||
@@ -92,7 +87,7 @@ std::cout << "\n"
|
|||||||
_parse_request_headers(list);
|
_parse_request_headers(list);
|
||||||
_parse_request_body(pos + 4);
|
_parse_request_body(pos + 4);
|
||||||
_parse_port_hostname(this->get_rq_headers("Host"));
|
_parse_port_hostname(this->get_rq_headers("Host"));
|
||||||
// add "raw_request.clear()" after parsing ? for little less memory usage ?
|
raw_request.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Client::fill_script_path(std::string script)
|
bool Client::fill_script_path(std::string script)
|
||||||
@@ -103,10 +98,10 @@ bool Client::fill_script_path(std::string script)
|
|||||||
std::string tmp;
|
std::string tmp;
|
||||||
|
|
||||||
pos = path.find(script);
|
pos = path.find(script);
|
||||||
if (pos != std::string::npos)
|
if (pos == 0)
|
||||||
{
|
{
|
||||||
tmp = path.substr(0, pos + len);
|
tmp = path.substr(0, pos + len);
|
||||||
_request.script.path = "./srcs/cgi-bin" + tmp; // TODO: deal with cgi path
|
_request.script.path = "./srcs" + tmp; // TODO: root path ?
|
||||||
_request.script.info = path.substr(pos + len);
|
_request.script.info = path.substr(pos + len);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,9 +74,9 @@ class Client
|
|||||||
bool fill_script_path(std::string script);
|
bool fill_script_path(std::string script);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _fd;
|
const int _fd;
|
||||||
std::string _port;
|
const std::string _port;
|
||||||
std::string _ip;
|
const std::string _ip;
|
||||||
listen_socket * _lsocket;
|
listen_socket * _lsocket;
|
||||||
struct Request _request;
|
struct Request _request;
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
bool Webserv::_is_cgi(Client *client)
|
bool Webserv::_is_cgi(Client *client)
|
||||||
{
|
{
|
||||||
// TODO see how it works with config
|
// TODO see how it works with config
|
||||||
if (client->fill_script_path("php-cgi"))
|
if (client->fill_script_path("/cgi-bin/php-cgi"))
|
||||||
return true;
|
return true;
|
||||||
if (client->fill_script_path("cgi_cpp.cgi"))
|
if (client->fill_script_path("/cgi-bin/cgi_cpp.cgi"))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,10 @@ void Webserv::_exec_cgi(Client *client)
|
|||||||
env = _set_env(client);
|
env = _set_env(client);
|
||||||
_exec_script(client, env);
|
_exec_script(client, env);
|
||||||
// _construct_response(client);
|
// _construct_response(client);
|
||||||
|
|
||||||
|
for (size_t i = 0; env[i]; i++)
|
||||||
|
delete[] env[i];
|
||||||
|
delete[] env;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* Webserv::_dup_env(std::string var, std::string val = "")
|
char* Webserv::_dup_env(std::string var, std::string val = "")
|
||||||
@@ -54,8 +58,7 @@ char** Webserv::_set_env(Client *client)
|
|||||||
env[9] = _dup_env("REMOTE_IDENT"); // authentification not supported
|
env[9] = _dup_env("REMOTE_IDENT"); // authentification not supported
|
||||||
env[10] = _dup_env("REMOTE_USER"); // authentification not supported
|
env[10] = _dup_env("REMOTE_USER"); // authentification not supported
|
||||||
env[11] = _dup_env("REQUEST_METHOD" , client->get_rq_method_str());
|
env[11] = _dup_env("REQUEST_METHOD" , client->get_rq_method_str());
|
||||||
env[12] = _dup_env("SCRIPT_NAME"); // TODO: define (https://www.rfc-editor.org/rfc/rfc3875#section-4.1.13
|
env[12] = _dup_env("SCRIPT_NAME" , client->get_rq_script_path());
|
||||||
// ,https://www.rfc-editor.org/rfc/rfc3875#section-8.2)
|
|
||||||
env[13] = _dup_env("SERVER_NAME" , client->get_rq_hostname());
|
env[13] = _dup_env("SERVER_NAME" , client->get_rq_hostname());
|
||||||
env[14] = _dup_env("SERVER_PORT" , client->get_rq_port());
|
env[14] = _dup_env("SERVER_PORT" , client->get_rq_port());
|
||||||
env[15] = _dup_env("SERVER_PROTOCOL" , client->get_rq_version());
|
env[15] = _dup_env("SERVER_PROTOCOL" , client->get_rq_version());
|
||||||
@@ -70,45 +73,82 @@ void Webserv::_exec_script(Client *client, char **env)
|
|||||||
{
|
{
|
||||||
#define RD 0
|
#define RD 0
|
||||||
#define WR 1
|
#define WR 1
|
||||||
#define BUF_SIZE 10
|
#define CGI_BUF_SIZE 10
|
||||||
|
|
||||||
char buf[BUF_SIZE];
|
/*1*/ #define FD_WR_TO_CHLD fd_in[WR]
|
||||||
int fd_in[2];
|
/* */ #define FD_WR_TO_PRNT fd_out[WR]
|
||||||
int fd_out[2];
|
/* */ #define FD_RD_FR_CHLD fd_out[RD]
|
||||||
char * const * nll = NULL;
|
/* */ #define FD_RD_FR_PRNT fd_in[RD]
|
||||||
std::string response;
|
/*2*/// #define FD_WR_TO_CHLD fdIn
|
||||||
std::string body = client->get_rq_body();
|
/* */// #define FD_WR_TO_PRNT fdOut
|
||||||
|
/* */// #define FD_RD_FR_CHLD fdOut
|
||||||
|
/* */// #define FD_RD_FR_PRNT fdIn
|
||||||
|
|
||||||
pipe(fd_in);
|
pid_t pid;
|
||||||
pipe(fd_out);
|
char buf[CGI_BUF_SIZE]; // WIP define buffer
|
||||||
if (fork() == 0)
|
char * const * nll = NULL;
|
||||||
|
std::string response;
|
||||||
|
std::string body = client->get_rq_body();
|
||||||
|
|
||||||
|
/*1*/ int fd_in[2];
|
||||||
|
/* */ int fd_out[2];
|
||||||
|
/*2*/// FILE *fIn;
|
||||||
|
/* */// FILE *fOut;
|
||||||
|
/* */// long fdIn;
|
||||||
|
/* */// long fdOut;
|
||||||
|
|
||||||
|
/*1*/ pipe(fd_in);
|
||||||
|
/* */ pipe(fd_out);
|
||||||
|
/*2*/// fIn = tmpfile();
|
||||||
|
/* */// fOut = tmpfile();
|
||||||
|
/* */// fdIn = fileno(fIn);
|
||||||
|
/* */// fdOut = fileno(fOut);
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid == -1)
|
||||||
|
std::cerr << "fork crashed" << std::endl;
|
||||||
|
else if (pid == 0)
|
||||||
{
|
{
|
||||||
close(fd_in[WR]);
|
|
||||||
close(fd_out[RD]);
|
/*1*/ close(FD_WR_TO_CHLD);
|
||||||
dup2(fd_in[RD], STDIN_FILENO);
|
/* */ close(FD_RD_FR_CHLD);
|
||||||
dup2(fd_out[WR], STDOUT_FILENO);
|
/*2*/
|
||||||
|
|
||||||
|
dup2(FD_RD_FR_PRNT, STDIN_FILENO);
|
||||||
|
dup2(FD_WR_TO_PRNT, STDOUT_FILENO);
|
||||||
execve(client->get_rq_script_path().c_str(), nll, env);
|
execve(client->get_rq_script_path().c_str(), nll, env);
|
||||||
std::cerr << "execve crashed\n";
|
std::cerr << "execve crashed.\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
close(fd_in[RD]);
|
/*1*/ close(FD_RD_FR_PRNT);
|
||||||
close(fd_out[WR]);
|
/* */ close(FD_WR_TO_PRNT);
|
||||||
// write to stdin of child programm
|
/*2*/
|
||||||
write(fd_in[WR], body.c_str(), body.size());
|
|
||||||
close(fd_in[WR]);
|
|
||||||
waitpid(-1, NULL, 0);
|
|
||||||
|
|
||||||
// read stdout of child programm
|
write(FD_WR_TO_CHLD, body.c_str(), body.size());
|
||||||
memset(buf, '\0', BUF_SIZE);
|
close(FD_WR_TO_CHLD);
|
||||||
while (read(fd_out[RD], buf, BUF_SIZE) > 0)
|
waitpid(-1, NULL, 0);
|
||||||
|
/*1*/
|
||||||
|
/*2*/// lseek(fdOut, 0, SEEK_SET);
|
||||||
|
|
||||||
|
memset(buf, '\0', CGI_BUF_SIZE);
|
||||||
|
while (read(FD_RD_FR_CHLD, buf, CGI_BUF_SIZE - 1) > 0)
|
||||||
{
|
{
|
||||||
response += buf;
|
response += buf;
|
||||||
memset(buf, '\0', BUF_SIZE);
|
memset(buf, '\0', CGI_BUF_SIZE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (response.empty())
|
if (response.empty())
|
||||||
response += "Status: 500\r\n\r\n";
|
response = "Status: 500\r\n\r\n";
|
||||||
|
|
||||||
|
/*1*/
|
||||||
|
/*2*/// fclose(fIn);
|
||||||
|
/* */// fclose(fOut);
|
||||||
|
/* */// close(fdIn);
|
||||||
|
/* */// close(fdOut);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
std::cout << "\n______response________\n" << response << "\n________________________\n";
|
||||||
// TODO: see how this must be handled
|
// TODO: see how this must be handled
|
||||||
client->response += response;
|
client->response += response;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,6 +147,12 @@ void Webserv::_get(Client *client, ServerConfig &server, LocationConfig &locatio
|
|||||||
//
|
//
|
||||||
if (_is_cgi(client))
|
if (_is_cgi(client))
|
||||||
{
|
{
|
||||||
|
// DEBUG
|
||||||
|
std::cout << "\nSCRIPT PATH _________________"
|
||||||
|
<< "\npath:" << client->get_rq_script_path()
|
||||||
|
<< "\npath_info:" << client->get_rq_script_info()
|
||||||
|
<< "\n\n";
|
||||||
|
|
||||||
_exec_cgi(client);
|
_exec_cgi(client);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user