add extern function for http message parsing
+ wip compare fields server and script + g tout cassey
This commit is contained in:
@@ -70,22 +70,15 @@ Client & Client::operator=( Client const & rhs )
|
||||
// https://www.tutorialspoint.com/http/http_requests.htm
|
||||
void Client::parse_request()
|
||||
{
|
||||
std::string sub;
|
||||
std::vector<std::string> list;
|
||||
size_t pos;
|
||||
std::map<std::string, std::string> headers;
|
||||
std::string body;
|
||||
|
||||
// DEBUG
|
||||
std::cout << "\nREQUEST _____________________\n"
|
||||
<< raw_request
|
||||
<< "\n\n";
|
||||
std::cout << "\nREQUEST ____________\n" << raw_request << "\n_____________\n";
|
||||
|
||||
pos = (raw_request).find(CRLF CRLF);
|
||||
sub = (raw_request).substr(0, pos);
|
||||
list = split(sub, '\n');
|
||||
_parse_request_line(*list.begin());
|
||||
list.erase(list.begin());
|
||||
_parse_request_headers(list);
|
||||
_parse_request_body(pos + 4);
|
||||
_parse_request_line();
|
||||
_parse_request_headers();
|
||||
_parse_request_body();
|
||||
_parse_port_hostname(this->get_rq_headers("Host"));
|
||||
raw_request.clear();
|
||||
}
|
||||
@@ -176,30 +169,24 @@ std::string Client::get_rq_headers(const std::string & key) const
|
||||
* PRIVATE MEMBER FUNCTIONS
|
||||
*********************************************/
|
||||
|
||||
void Client::_parse_request_line( std::string rline )
|
||||
void Client::_parse_request_line()
|
||||
{
|
||||
std::vector<std::string> sline;
|
||||
std::string tmp;
|
||||
std::vector<std::string> line;
|
||||
int ret;
|
||||
|
||||
sline = split(rline, ' ');
|
||||
if (sline.size() != 3)
|
||||
ret = ::parse_http_first_line(raw_request, line);
|
||||
if (ret != 3)
|
||||
{
|
||||
std::cerr << "err _parse_request_line(): ";
|
||||
throw std::runtime_error("bad request-line header");
|
||||
std::cerr << "err _parse_first_line(): wrong number of elements (" << ret << " instead of 3)\n";
|
||||
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 )
|
||||
@@ -214,32 +201,16 @@ void Client::_parse_request_uri( std::string uri )
|
||||
_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;
|
||||
std::string val;
|
||||
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) );
|
||||
}
|
||||
// TODO: check error and adjust status
|
||||
_request.headers = ::parse_http_headers(raw_request);
|
||||
}
|
||||
|
||||
void Client::_parse_request_body( size_t pos )
|
||||
void Client::_parse_request_body()
|
||||
{
|
||||
std::string body = &raw_request[pos];
|
||||
|
||||
_request.body = body;
|
||||
// TODO: check error and adjust status
|
||||
_request.body = ::parse_http_body(raw_request);
|
||||
}
|
||||
|
||||
void Client::_parse_port_hostname(std::string host)
|
||||
@@ -247,10 +218,7 @@ void Client::_parse_port_hostname(std::string host)
|
||||
size_t pos;
|
||||
|
||||
if (host == "")
|
||||
{
|
||||
std::cerr << "no host\n";
|
||||
throw std::runtime_error("no host in request");
|
||||
}
|
||||
|
||||
pos = host.find(':');
|
||||
// port :
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
# include <map>
|
||||
# include <vector>
|
||||
# include <string.h> // strdup
|
||||
# include "utils.hpp"
|
||||
# include <netinet/in.h> // sockaddr_in, struct in_addr
|
||||
# include <arpa/inet.h> // htonl, htons, ntohl, ntohs, inet_addr, inet_ntoa
|
||||
# include "utils.hpp"
|
||||
# include "parsing_message_http.hpp"
|
||||
|
||||
struct Script
|
||||
{
|
||||
@@ -78,12 +79,12 @@ class Client
|
||||
std::string _port;
|
||||
std::string _ip;
|
||||
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_headers( std::vector<std::string> list );
|
||||
void _parse_request_body( size_t pos );
|
||||
void _parse_port_hostname(std::string host);
|
||||
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#! /usr/bin/php
|
||||
|
||||
<?php
|
||||
echo "Status: 200\r\n";
|
||||
echo "\r\n";
|
||||
echo "BEGIN PHP-CGI\n-----------\n\n";
|
||||
//phpinfo();
|
||||
|
||||
echo "AUTH_TYPE: " . getenv("AUTH_TYPE");
|
||||
echo "\nCONTENT_LENGTH: " . getenv("CONTENT_LENGTH");
|
||||
echo "\nCONTENT_TYPE: " . getenv("CONTENT_TYPE");
|
||||
|
||||
@@ -15,6 +15,7 @@ std::vector<std::string> split(std::string input, char delimiter)
|
||||
|
||||
std::string trim(std::string str, char c)
|
||||
{
|
||||
// TODO: protect substr
|
||||
str = str.substr(str.find_first_not_of(c));
|
||||
str = str.substr(0, str.find_last_not_of(c) + 1);
|
||||
|
||||
@@ -100,15 +101,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::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||
return str;
|
||||
}
|
||||
|
||||
void delete_line_in_string(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);
|
||||
void replace_all_substr(std::string &str, const std::string &ori_substr, const std::string &new_substr);
|
||||
std::string str_tolower(std::string str);
|
||||
void delete_line_in_string(std::string * str, size_t pos, std::string delim);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
extern bool g_run;
|
||||
extern int g_last_signal;
|
||||
void signal_handler(int signum);
|
||||
void signal_handler(int signum);
|
||||
|
||||
// these might only be TMP
|
||||
# define FAILURE -1
|
||||
@@ -93,7 +93,6 @@ class Webserv
|
||||
|
||||
ServerConfig &_determine_process_server(Client *client);
|
||||
LocationConfig &_determine_location(ServerConfig &server, std::string const &path);
|
||||
void _response_correction(Client *client);
|
||||
// cgi_script.cpp
|
||||
bool _is_cgi(Client *client);
|
||||
std::string _exec_cgi(Client *client);
|
||||
@@ -101,6 +100,9 @@ class Webserv
|
||||
char* _dup_env(std::string var, std::string val);
|
||||
char* _dup_env(std::string var, int i);
|
||||
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
|
||||
int _epoll_update(int fd, uint32_t events, int op);
|
||||
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 _init_http_status_map();
|
||||
void _init_mime_types_map();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -102,7 +102,8 @@ std::string Webserv::_exec_script(Client *client, char **env)
|
||||
close(FD_RD_FR_CHLD);
|
||||
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);
|
||||
execve("truc", nll, env);
|
||||
std::cerr << "execve crashed.\n";
|
||||
}
|
||||
else
|
||||
@@ -119,13 +120,42 @@ std::string Webserv::_exec_script(Client *client, char **env)
|
||||
script_output += buf;
|
||||
memset(buf, '\0', CGI_BUF_SIZE);
|
||||
}
|
||||
close(FD_RD_FR_CHLD);
|
||||
}
|
||||
if (script_output.empty())
|
||||
script_output = "Status: 500\r\n\r\n";
|
||||
|
||||
// DEBUG
|
||||
std::cout << "\n______response______\n" << script_output << "\n____end response____\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);
|
||||
::delete_line_in_string(&output, pos, CRLF);
|
||||
}
|
||||
client->status = 200;
|
||||
}
|
||||
|
||||
void Webserv::_check_script_fields(Client *client, std::string output)
|
||||
{
|
||||
std::map<std::string, std::string> server_fields;
|
||||
std::map<std::string, std::string> script_fields;
|
||||
|
||||
server_fields = parse_http_headers(client->response);
|
||||
script_fields = parse_http_headers(output);
|
||||
// TODO: compare both map to supress duplicates
|
||||
}
|
||||
|
||||
|
||||
75
srcs/webserv/parsing_message_http.cpp
Normal file
75
srcs/webserv/parsing_message_http.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
|
||||
#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[0], ' ');
|
||||
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');
|
||||
// TODO: if (list.begin() is "first line")
|
||||
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;
|
||||
}
|
||||
|
||||
33
srcs/webserv/parsing_message_http.hpp
Normal file
33
srcs/webserv/parsing_message_http.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
|
||||
#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);
|
||||
|
||||
// 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,12 @@ void Webserv::_get(Client *client, ServerConfig &server, LocationConfig &locatio
|
||||
|
||||
// TMP HUGO
|
||||
//
|
||||
std::string script_output;
|
||||
if (_is_cgi(client))
|
||||
{
|
||||
_exec_cgi(client);
|
||||
_response_correction(client);
|
||||
script_output = _exec_cgi(client);
|
||||
_check_script_output(client, script_output);
|
||||
std::cout << "_____________status:" << client->status << "\n";
|
||||
return;
|
||||
}
|
||||
//
|
||||
@@ -224,12 +226,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)
|
||||
{
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user