This commit is contained in:
Adam
2025-04-25 12:58:43 +02:00
committed by GitHub
13 changed files with 330 additions and 43 deletions

View File

@ -1,5 +1,5 @@
[server] [server]
host = "localhost" host = "0.0.0.0"
port = 8080 port = 8080
[server.location./] [server.location./]

View File

@ -25,7 +25,7 @@ cgi.go = "/bin/go"
[server.location./redir] [server.location./redir]
redirect = "https://kanel.ovh" redirect = "https://kanel.ovh"
[server3] [serverr]
server_names = { "ptnnnn.local"} server_names = { "ptnnnn.local"}
host = "127.0.0.2" host = "127.0.0.2"
port = 9090 port = 9090

View File

@ -6,7 +6,7 @@
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/22 12:17:48 by adjoly #+# #+# */ /* Created: 2025/04/22 12:17:48 by adjoly #+# #+# */
/* Updated: 2025/04/22 12:42:21 by adjoly ### ########.fr */ /* Updated: 2025/04/24 14:01:15 by adjoly ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -30,11 +30,13 @@ class URL {
std::vector<std::string> getSegments(void) { return _path_segments; } std::vector<std::string> getSegments(void) { return _path_segments; }
std::string getFullUrl(void) { return _full_url; } std::string getFullUrl(void) { return _full_url; }
std::string getQueryString(void) const { return _query_string; }
private: private:
void parse() { void parse() {
size_t scheme_pos = _full_url.find("://"); size_t scheme_pos = _full_url.find("://");
size_t path_start = 0; size_t path_start = 0;
size_t query_start = _full_url.find('?');
if (scheme_pos != std::string::npos) { if (scheme_pos != std::string::npos) {
path_start = _full_url.find('/', scheme_pos + 3); path_start = _full_url.find('/', scheme_pos + 3);
@ -42,11 +44,19 @@ class URL {
path_start = 0; path_start = 0;
} }
if (query_start != std::string::npos) {
_query_string = _full_url.substr(query_start + 1);
if (path_start != std::string::npos) {
std::string path = _full_url.substr(path_start, query_start - path_start);
splitPath(path, _path_segments);
}
} else {
if (path_start != std::string::npos) { if (path_start != std::string::npos) {
std::string path = _full_url.substr(path_start); std::string path = _full_url.substr(path_start);
splitPath(path, _path_segments); splitPath(path, _path_segments);
} }
} }
}
void splitPath(const std::string &path, void splitPath(const std::string &path,
std::vector<std::string> &segments) const { std::vector<std::string> &segments) const {
@ -72,4 +82,5 @@ class URL {
std::string _full_url; std::string _full_url;
std::vector<std::string> _path_segments; std::vector<std::string> _path_segments;
std::string _query_string;
}; };

View File

@ -1,24 +1,41 @@
/* ************************************************************************** */ /* ************************************************************************** */
/* */ /* */
/* ::: :::::::: */ /* ::: :::::::: */
/* cgi.hpp :+: :+: :+: */ /* Cgi.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/24 14:17:34 by adjoly #+# #+# */ /* Created: 2025/03/24 14:17:34 by adjoly #+# #+# */
/* Updated: 2025/04/22 11:51:33 by mmoussou ### ########.fr */ /* Updated: 2025/04/24 14:24:09 by adjoly ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
#pragma once #pragma once
#include <sstream> #include "requests/HttpIMessage.hpp"
#include "requests/HttpRequest.hpp"
#include <config/default.hpp>
#include <map>
#include <string>
class cgi { namespace webserv {
class Cgi {
public: public:
cgi(); Cgi(http::IRequest *, config::Server *);
~cgi(void); ~Cgi(void);
std::string getEnv(std::string &);
void setEnv(std::string &, std::string);
void process(void);
protected: protected:
private: private:
std::string _request; void _initEnvp(void);
std::map<std::string, std::string> _envp;
config::Server *_conf;
http::IMessage *_request;
}; };
}; // namespace webserv

View File

@ -6,7 +6,7 @@
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */ /* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/16 17:51:46 by mmoussou #+# #+# */ /* Created: 2025/03/16 17:51:46 by mmoussou #+# #+# */
/* Updated: 2025/04/22 11:52:00 by mmoussou ### ########.fr */ /* Updated: 2025/04/24 14:56:08 by mmoussou ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -26,6 +26,7 @@ public:
static void setEntries(const std::map<int, std::string>); static void setEntries(const std::map<int, std::string>);
static std::map<int, std::string> message; static std::map<int, std::string> message;
private: private:
static std::map<int, std::string> populateMessages(); static std::map<int, std::string> populateMessages();

View File

@ -6,7 +6,7 @@
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */ /* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/03 17:23:00 by mmoussou #+# #+# */ /* Created: 2025/02/03 17:23:00 by mmoussou #+# #+# */
/* Updated: 2025/04/22 15:07:02 by adjoly ### ########.fr */ /* Updated: 2025/04/24 15:09:52 by mmoussou ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -19,6 +19,7 @@
#include <requests/HttpIMessage.hpp> #include <requests/HttpIMessage.hpp>
#include <requests/HttpResponse.hpp> #include <requests/HttpResponse.hpp>
#include <requests/Mime.hpp>
#include <config/default.hpp> #include <config/default.hpp>

View File

@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Mime.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/24 14:53:25 by mmoussou #+# #+# */
/* Updated: 2025/04/24 15:10:32 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
#include <string>
#include <map>
namespace webserv {
namespace http {
class Mime {
public:
static std::string getType(const std::string &filename);
private:
static std::map<std::string, std::string> initMimeTypes();
static std::map<std::string, std::string> mimeTypes;
};
} // -namespace http
} // -namespace webserv

View File

@ -6,7 +6,7 @@
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */ /* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/03 15:48:22 by mmoussou #+# #+# */ /* Created: 2025/02/03 15:48:22 by mmoussou #+# #+# */
/* Updated: 2025/04/22 11:51:54 by mmoussou ### ########.fr */ /* Updated: 2025/04/24 13:48:09 by adjoly ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -15,5 +15,6 @@
#include <requests/Errors.hpp> #include <requests/Errors.hpp>
#include <requests/HttpRequest.hpp> #include <requests/HttpRequest.hpp>
#include <requests/HttpResponse.hpp> #include <requests/HttpResponse.hpp>
#include <requests/Cgi.hpp>
using namespace webserv; using namespace webserv;

View File

@ -6,7 +6,7 @@
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */ /* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/14 14:14:39 by adjoly #+# #+# */ /* Created: 2025/04/14 14:14:39 by adjoly #+# #+# */
/* Updated: 2025/04/23 14:39:16 by mmoussou ### ########.fr */ /* Updated: 2025/04/25 12:43:54 by mmoussou ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -23,7 +23,9 @@ namespace server {
class Client { class Client {
public: public:
Client(int, sockaddr_in, config::Config *); Client();
Client(struct pollfd, sockaddr_in, config::Config *);
void parse(struct pollfd, sockaddr_in, config::Config *);
virtual ~Client(void); virtual ~Client(void);
void answer(void); void answer(void);
@ -31,7 +33,7 @@ class Client {
private: private:
void _getRequest(std::string); void _getRequest(std::string);
int _fd; struct pollfd _fd;
struct sockaddr_in _client_addr; struct sockaddr_in _client_addr;
http::IRequest *_request; http::IRequest *_request;
//http::Response *_response; //http::Response *_response;

View File

@ -0,0 +1,50 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Cgi.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/24 13:46:34 by adjoly #+# #+# */
/* Updated: 2025/04/24 14:38:20 by adjoly ### ########.fr */
/* */
/* ************************************************************************** */
#include "requests/HttpIMessage.hpp"
#include "requests/HttpRequest.hpp"
#include "requests/HttpResponse.hpp"
#include "requests/default.hpp"
Cgi::Cgi(http::IRequest *req, config::Server *conf) : _conf(conf), _request(req) {
_initEnvp();
}
void Cgi::_initEnvp(void) {
_envp[] = "";
}
std::string Cgi::getEnv(std::string &key) {
auto it = _envp.find(key);
if (it != _envp.end()) {
return it->second;
}
return "";
}
void Cgi::setEnv(std::string &key, std::string value) {
_envp[key] = value;
}
void Cgi::process() {
int pipefd[2];
int forkPid;
if (pipe(pipefd) <= -1) {
//throw error
}
forkPid = fork();
if (forkPid == 0) {
// in fork
}
}

View File

@ -6,7 +6,7 @@
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */ /* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/02/03 16:07:01 by mmoussou #+# #+# */ /* Created: 2025/02/03 16:07:01 by mmoussou #+# #+# */
/* Updated: 2025/04/22 15:03:46 by adjoly ### ########.fr */ /* Updated: 2025/04/25 12:36:17 by mmoussou ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -18,6 +18,8 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <dirent.h> #include <dirent.h>
#include <log.hpp>
using namespace webserv; using namespace webserv;
http::IRequest::~IRequest(void) { http::IRequest::~IRequest(void) {
@ -174,7 +176,30 @@ http::Response http::Get::execute(void)
std::sort(files.begin(), files.end()); std::sort(files.begin(), files.end());
std::string body = "<html><body><ul>\n"; std::string body = "<html>";
body += "<head><style>\n\
:root {\n\
background-color: -moz-dialog;\n\
color: -moz-dialogtext;\n\
font: message-box;\n\
padding-inline: 2em;\n\
color-scheme: light dark;\n\
}\n\
\n\
body {\n\
border: 1px solid ThreeDShadow;\n\
border-radius: 10px;\n\
padding: 3em;\n\
min-width: 30em;\n\
max-width: 65em;\n\
margin: 4em auto;\n\
background-color: Field;\n\
color: FieldText;\n\
}\n\
</style></head>";
body += "<body><ul>\n";
for (size_t i = 0; i < files.size(); i++) for (size_t i = 0; i < files.size(); i++)
body += "<li><a href=\"" + files[i] + "\">" + files[i] + "</a></li>\n"; body += "<li><a href=\"" + files[i] + "\">" + files[i] + "</a></li>\n";
body += "</ul></body></html>"; body += "</ul></body></html>";
@ -199,13 +224,9 @@ http::Response http::Get::execute(void)
response.setProtocol(this->_protocol); response.setProtocol(this->_protocol);
response.setStatusCode(200); response.setStatusCode(200);
response.addHeader("Content-Type", "text/html"); // TODO: change it to check the file extension and set it to the corresponding MIME or text/plain if unkown. we will only implement the important MIME types in the Mozilla documentation because https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types response.addHeader("Content-Type", http::Mime::getType(this->_target));
//std::ifstream file_end(this->_target.c_str(), std::ios::binary | std::ios::ate); _log->debug(response.str().c_str());
//std::stringstream length;
//length << (file_end.tellg() - file.tellg());
//std::cout << length.str() << std::endl;
//response.addHeader("Content-Length", length.str());
} }
} }
catch (...) catch (...)

View File

@ -0,0 +1,113 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Mime.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/24 14:50:37 by mmoussou #+# #+# */
/* Updated: 2025/04/24 15:24:08 by mmoussou ### ########.fr */
/* */
/* ************************************************************************** */
#include <requests/Mime.hpp>
using namespace webserv;
std::map<std::string, std::string> http::Mime::initMimeTypes() {
std::map<std::string, std::string> types;
types["aac"] = "audio/aac";
types["abw"] = "application/x-abiword";
types["apng"] = "image/apng";
types["arc"] = "application/x-freearc";
types["avif"] = "image/avif";
types["avi"] = "video/x-msvideo";
types["azw"] = "application/vnd.amazon.ebook";
types["bin"] = "application/octet-stream";
types["bmp"] = "image/bmp";
types["bz"] = "application/x-bzip";
types["bz2"] = "application/x-bzip2";
types["cda"] = "application/x-cdf";
types["csh"] = "application/x-csh";
types["css"] = "text/css";
types["csv"] = "text/csv";
types["doc"] = "application/msword";
types["docx"] = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
types["eot"] = "application/vnd.ms-fontobject";
types["epub"] = "application/epub+zip";
types["gz"] = "application/gzip";
types["gif"] = "image/gif";
types["htm"] = "text/html";
types["html"] = "text/html";
types["ico"] = "image/vnd.microsoft.icon";
types["ics"] = "text/calendar";
types["jar"] = "application/java-archive";
types["jpeg,"] = "image/jpeg";
types["js"] = "text/javascript";
types["json"] = "application/json";
types["jsonld"] = "application/ld+json";
types["md"] = "text/plain";
types["mid"] = "audio/midi";
types["midi"] = "audio/midi";
types["mjs"] = "text/javascript";
types["mp3"] = "audio/mpeg";
types["mp4"] = "video/mp4";
types["mpeg"] = "video/mpeg";
types["mpkg"] = "application/vnd.apple.installer+xml";
types["odp"] = "application/vnd.oasis.opendocument.presentation";
types["ods"] = "application/vnd.oasis.opendocument.spreadsheet";
types["odt"] = "application/vnd.oasis.opendocument.text";
types["oga"] = "audio/ogg";
types["ogv"] = "video/ogg";
types["ogx"] = "application/ogg";
types["opus"] = "audio/ogg";
types["otf"] = "font/otf";
types["png"] = "image/png";
types["pdf"] = "application/pdf";
types["php"] = "application/x-httpd-php";
types["ppt"] = "application/vnd.ms-powerpoint";
types["pptx"] = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
types["rar"] = "application/vnd.rar";
types["rtf"] = "application/rtf";
types["sh"] = "application/x-sh";
types["svg"] = "image/svg+xml";
types["tar"] = "application/x-tar";
types["tif,"] = "image/tiff";
types["ts"] = "video/mp2t";
types["ttf"] = "font/ttf";
types["txt"] = "text/plain";
types["vsd"] = "application/vnd.visio";
types["wav"] = "audio/wav";
types["weba"] = "audio/webm";
types["webm"] = "video/webm";
types["webp"] = "image/webp";
types["woff"] = "font/woff";
types["woff2"] = "font/woff2";
types["xhtml"] = "application/xhtml+xml";
types["xls"] = "application/vnd.ms-excel";
types["xlsx"] = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
types["xml"] = "application/xml";
types["xul"] = "application/vnd.mozilla.xul+xml";
types["zip"] = "application/zip";
types["3gp"] = "video/3gpp";
types["3g2"] = "video/3gpp2";
types["7z"] = "application/x-7z-compressed";
types["nix"] = "text/plain";
return types;
}
std::map<std::string, std::string> http::Mime::mimeTypes = Mime::initMimeTypes();
std::string http::Mime::getType(const std::string &filename) {
size_t dot_pos = filename.find_last_of('.');
if (dot_pos == std::string::npos)
return "text/plain"; //default
std::string ext = filename.substr(dot_pos + 1);
std::map<std::string, std::string>::const_iterator it = mimeTypes.find(ext);
if (it != mimeTypes.end())
return it->second;
return "application/octet-stream"; //unknown extension so default
}

View File

@ -6,7 +6,7 @@
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */ /* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/17 11:12:41 by mmoussou #+# #+# */ /* Created: 2025/04/17 11:12:41 by mmoussou #+# #+# */
/* Updated: 2025/04/23 14:40:06 by mmoussou ### ########.fr */ /* Updated: 2025/04/25 12:44:12 by mmoussou ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -15,14 +15,17 @@
using namespace server; using namespace server;
Client::Client(int fd, sockaddr_in socket, config::Config *conf) Client::Client(void) {}
: _fd(fd), _client_addr(socket) {
Client::Client(struct pollfd fd, sockaddr_in socket, config::Config *conf)
: _fd(fd), _client_addr(socket)
{
std::string received_data; std::string received_data;
char buffer[BUFFER_SIZE]; char buffer[BUFFER_SIZE];
ssize_t bytes_received; ssize_t bytes_received;
do { do {
std::memset(buffer, 0, BUFFER_SIZE); std::memset(buffer, 0, BUFFER_SIZE);
bytes_received = recv(fd, buffer, BUFFER_SIZE - 1, 0); bytes_received = recv(this->_fd.fd, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received == -1) { if (bytes_received == -1) {
_log->error("failed to receive request"); _log->error("failed to receive request");
throw std::runtime_error("failed to receive request"); throw std::runtime_error("failed to receive request");
@ -34,6 +37,33 @@ Client::Client(int fd, sockaddr_in socket, config::Config *conf)
this->_conf = conf->getServer(this->_request->getHeaders()["Host"]); this->_conf = conf->getServer(this->_request->getHeaders()["Host"]);
// if (received_data.length > (get max_body_size from Route corresponding) )
// throw error
}
void Client::parse(struct pollfd fd, sockaddr_in socket, config::Config *conf)
{
this->_fd = fd;
this->_client_addr = socket;
std::string received_data;
char buffer[BUFFER_SIZE];
ssize_t bytes_received;
do {
std::memset(buffer, 0, BUFFER_SIZE);
bytes_received = recv(this->_fd.fd, buffer, BUFFER_SIZE - 1, 0);
if (bytes_received == -1) {
_log->error("failed to receive request");
throw std::runtime_error("failed to receive request");
}
received_data += std::string(buffer, bytes_received);
} while (buffer[bytes_received]);
this->_getRequest(received_data);
this->_conf = conf->getServer(this->_request->getHeaders()["Host"]);
// if (received_data.length > (get max_body_size from Route corresponding) ) // if (received_data.length > (get max_body_size from Route corresponding) )
// throw error // throw error
} }
@ -42,20 +72,28 @@ void Client::_getRequest(std::string request_str) {
std::string method = request_str.substr( std::string method = request_str.substr(
0, request_str.substr(0, 4).find_last_not_of(" ") + 1); 0, request_str.substr(0, 4).find_last_not_of(" ") + 1);
if (method == "GET") { if (method == "GET")
_log->info("get request received"); {
this->_request = new http::Get(request_str); this->_request = new http::Get(request_str);
} else if (method == "DELETE") { _log->info("get request received");
_log->info("delete request received"); }
else if (method == "DELETE")
{
this->_request = new http::Delete(request_str); this->_request = new http::Delete(request_str);
} else if (method == "POST") { _log->info("delete request received");
_log->info("post request received"); }
else if (method == "POST")
{
this->_request = new http::Post(request_str); this->_request = new http::Post(request_str);
} else { _log->info("post request received");
_log->info("unsupported request received"); }
else
{
this->_request = new http::Get(); this->_request = new http::Get();
this->_request->setMethod("501"); this->_request->setMethod("501");
_log->info("unsupported request received");
} }
// set target to correct target with the conf
} }
void Client::answer(void) { void Client::answer(void) {
@ -68,7 +106,7 @@ void Client::answer(void) {
response = this->_request->execute().str(); response = this->_request->execute().str();
else else
response = "HTTP/1.1 501 Not Implemented\r\nContent-Type: text/html\r\n\r\n<html><body><h1>501 Not Implemented</h1></body></html>"; response = "HTTP/1.1 501 Not Implemented\r\nContent-Type: text/html\r\n\r\n<html><body><h1>501 Not Implemented</h1></body></html>";
send(this->_fd, response.c_str(), response.length(), 0); send(this->_fd.fd, response.c_str(), response.length(), 0);
} }
Client::~Client(void) { Client::~Client(void) {