mirror of
https://github.com/KeyZox71/webserv.git
synced 2025-05-10 23:48:46 +02:00
「✨」 feat(main loop): added a main loop so the server serve
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ obj/
|
||||
.direnv/
|
||||
compile_commands.json
|
||||
.cache
|
||||
*.log
|
||||
|
18
Dockerfile
18
Dockerfile
@ -1,11 +1,13 @@
|
||||
FROM alpine:3.21
|
||||
FROM alpine:3.21
|
||||
|
||||
COPY ./ /build
|
||||
COPY ./ /build
|
||||
|
||||
RUN apk add --no-cache clang make \
|
||||
&& cd /build \
|
||||
&& make \
|
||||
&& chmod +x webserv \
|
||||
&& cp webserv /bin/webserv
|
||||
RUN apk add --no-cache clang make \
|
||||
&& cd /build \
|
||||
&& make \
|
||||
&& chmod +x webserv \
|
||||
&& cp webserv /bin/webserv
|
||||
|
||||
RUN [ "/bin/webserv", "$WEBSERV-CONF"]
|
||||
STOPSIGNAL SIGINT
|
||||
|
||||
RUN [ "/bin/webserv", "$WEBSERV-CONF"]
|
||||
|
5
Makefile
5
Makefile
@ -6,8 +6,7 @@
|
||||
# By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/10/25 16:09:27 by adjoly #+# #+# #
|
||||
# Updated: 2025/04/10 11:52:13 by mmoussou ### ########.fr #
|
||||
# Updated: 2025/03/25 18:13:53 by adjoly ### ########.fr #
|
||||
# Updated: 2025/04/22 14:32:50 by adjoly ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
@ -15,7 +14,7 @@ SHELL = bash
|
||||
|
||||
NAME = webserv
|
||||
|
||||
CC = c++
|
||||
CC = clang++
|
||||
|
||||
OBJSDIR = obj/
|
||||
|
||||
|
@ -2,7 +2,7 @@ log_file = "test.log"
|
||||
|
||||
[server]
|
||||
server_names = { "localhost", "2B5.local" }
|
||||
host = "localhost"
|
||||
host = "0.0.0.0"
|
||||
port = 8080
|
||||
|
||||
[server.error_pages]
|
||||
|
@ -6,13 +6,14 @@
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/24 14:17:34 by adjoly #+# #+# */
|
||||
/* Updated: 2025/03/24 14:20:00 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 11:51:33 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
|
||||
class cgi {
|
||||
public:
|
||||
cgi();
|
||||
|
35
includes/config/Config.hpp
Normal file
35
includes/config/Config.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Config.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/14 12:20:06 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/22 15:25:39 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <config/Server.hpp>
|
||||
|
||||
namespace webserv {
|
||||
namespace config {
|
||||
|
||||
class Config {
|
||||
public:
|
||||
Config(std::string &);
|
||||
~Config();
|
||||
|
||||
Logger *getLogger(void) { return _log; }
|
||||
|
||||
std::vector<Server *> getServers(void) { return _servers; }
|
||||
Server *getServer(const std::string &);
|
||||
|
||||
private:
|
||||
std::vector<Server *> _servers;
|
||||
};
|
||||
|
||||
}; // namespace config
|
||||
}; // namespace webserv
|
@ -6,15 +6,15 @@
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/19 14:59:41 by adjoly #+# #+# */
|
||||
/* Updated: 2025/03/26 08:31:41 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 12:34:00 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cppeleven.hpp"
|
||||
#include "log.hpp"
|
||||
#include "node/default.hpp"
|
||||
#include <cppeleven.hpp>
|
||||
#include <log.hpp>
|
||||
#include <node/default.hpp>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <map>
|
||||
@ -26,9 +26,22 @@ namespace config {
|
||||
|
||||
class Route {
|
||||
public:
|
||||
Route(toml::ANode *, Logger *);
|
||||
Route(toml::ANode *);
|
||||
~Route(void);
|
||||
|
||||
bool getDirList(void) { return _dirlist; }
|
||||
bool getCookies(void) { return _cookies; }
|
||||
bool getRedirect(void) { return _redirect; }
|
||||
|
||||
int32_t getMaxBody(void) { return _max_body; }
|
||||
|
||||
std::string getRootDir(void) { return _root; }
|
||||
std::string getUpRoot(void) { return _up_root; }
|
||||
std::string getIndex(void) { return _index; }
|
||||
std::map<std::string, std::string> *getCgi(void) { return _cgi; }
|
||||
|
||||
bool *getMethods(void) { return _methods; }
|
||||
|
||||
protected:
|
||||
private:
|
||||
bool _dirlist;
|
||||
@ -42,8 +55,6 @@ class Route {
|
||||
std::string _index;
|
||||
std::map<std::string, std::string> *_cgi;
|
||||
|
||||
Logger *_log;
|
||||
|
||||
bool _methods[3]; ///> A methods boolean array which correspond to - 0: GET,
|
||||
///1: POST, 2: DELETE
|
||||
toml::ANode *_table;
|
||||
|
@ -6,22 +6,25 @@
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/19 14:11:28 by adjoly #+# #+# */
|
||||
/* Updated: 2025/03/25 17:56:34 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 15:25:58 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config/default.hpp"
|
||||
#include "cppeleven.hpp"
|
||||
#include "node/ANode.hpp"
|
||||
#include <webserv.hpp>
|
||||
#include <config/Route.hpp>
|
||||
#include <cppeleven.hpp>
|
||||
#include <node/ANode.hpp>
|
||||
#include <webserv.hpp>
|
||||
#include <config/URL.hpp>
|
||||
|
||||
namespace webserv {
|
||||
namespace config {
|
||||
|
||||
class Server {
|
||||
public:
|
||||
Server(std::string);
|
||||
Server(toml::ANode *);
|
||||
~Server();
|
||||
|
||||
/**
|
||||
@ -48,11 +51,6 @@ class Server {
|
||||
return not_nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Can be used to get the Logger pointer
|
||||
*/
|
||||
Logger *getLogger(void) { return _log; }
|
||||
|
||||
// @brief Can be used to get a server name
|
||||
std::vector<std::string> *getServerNames(void) { return _server_names; }
|
||||
// @brief Can be used to get the host specified in the config file
|
||||
@ -60,9 +58,14 @@ class Server {
|
||||
// @brief Can be used to get the port specified in the config file
|
||||
int getPort(void) { return _port; }
|
||||
|
||||
// @brief Can be used to check if a servername is present in this config
|
||||
bool isServerName(const std::string &);
|
||||
|
||||
Route *whatRoute(const URL &);
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::map<std::string, Route *>
|
||||
std::map<URL, Route *>
|
||||
*_routes; ///> A map of all the route present in the config file
|
||||
std::map<int, std::string> *_err_pages; ///> An error pages map to map error
|
||||
/// specified in the config file
|
||||
@ -75,17 +78,11 @@ class Server {
|
||||
|
||||
toml::ANode *_table; ///> The table used for the parsing (is deleted at the
|
||||
/// end of the constructor)
|
||||
Logger *_log; ///> A pointer to the logger class
|
||||
|
||||
std::map<int, std::string> *
|
||||
_parseErrPages(std::map<std::string, toml::ANode *> *table);
|
||||
|
||||
/**
|
||||
* @brief Can be used to get the [server] table in _table
|
||||
*
|
||||
* @return A pointer to the [server] table as an ANode
|
||||
*/
|
||||
toml::ANode *_getServerTable(void);
|
||||
|
||||
};
|
||||
|
||||
} // namespace config
|
||||
|
75
includes/config/URL.hpp
Normal file
75
includes/config/URL.hpp
Normal file
@ -0,0 +1,75 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* URL.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/22 12:17:48 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/22 12:42:21 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <webserv.hpp>
|
||||
|
||||
class URL {
|
||||
public:
|
||||
URL(const std::string &url) : _full_url(url) { parse(); }
|
||||
|
||||
bool operator==(const URL &other) const {
|
||||
return comparePathSegments(other);
|
||||
}
|
||||
|
||||
bool operator<(const URL &other) const { return _full_url < other._full_url; }
|
||||
|
||||
std::vector<std::string> getSegments(void) { return _path_segments; }
|
||||
std::string getFullUrl(void) { return _full_url; }
|
||||
|
||||
private:
|
||||
void parse() {
|
||||
size_t scheme_pos = _full_url.find("://");
|
||||
size_t path_start = 0;
|
||||
|
||||
if (scheme_pos != std::string::npos) {
|
||||
path_start = _full_url.find('/', scheme_pos + 3);
|
||||
} else {
|
||||
path_start = 0;
|
||||
}
|
||||
|
||||
if (path_start != std::string::npos) {
|
||||
std::string path = _full_url.substr(path_start);
|
||||
splitPath(path, _path_segments);
|
||||
}
|
||||
}
|
||||
|
||||
void splitPath(const std::string &path,
|
||||
std::vector<std::string> &segments) const {
|
||||
std::stringstream ss(path);
|
||||
std::string segment;
|
||||
while (std::getline(ss, segment, '/')) {
|
||||
if (!segment.empty()) {
|
||||
segments.push_back(segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool comparePathSegments(const URL &other) const {
|
||||
size_t min_size =
|
||||
std::min(_path_segments.size(), other._path_segments.size());
|
||||
for (size_t i = 0; i < min_size; ++i) {
|
||||
if (_path_segments[i] != other._path_segments[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string _full_url;
|
||||
std::vector<std::string> _path_segments;
|
||||
};
|
@ -6,17 +6,18 @@
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/19 14:15:51 by adjoly #+# #+# */
|
||||
/* Updated: 2025/03/26 08:39:08 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 15:28:31 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Route.hpp"
|
||||
#include "Server.hpp"
|
||||
#include "cppeleven.hpp"
|
||||
#include "node/Table.hpp"
|
||||
#include "node/default.hpp"
|
||||
#include <config/Config.hpp>
|
||||
#include <config/Route.hpp>
|
||||
#include <config/Server.hpp>
|
||||
#include <cppeleven.hpp>
|
||||
#include <node/Table.hpp>
|
||||
#include <node/default.hpp>
|
||||
#include <tomlpp.hpp>
|
||||
|
||||
namespace webserv {
|
||||
@ -34,13 +35,13 @@ namespace config {
|
||||
* @return The value got or not_nullptr
|
||||
*/
|
||||
static inline void *accessValue(const std::string &name, toml::nodeType type,
|
||||
toml::ANode *table, Logger *log) {
|
||||
toml::ANode *table, Logger *log) {
|
||||
void *val;
|
||||
bool found = false;
|
||||
|
||||
if (table == not_nullptr)
|
||||
return not_nullptr;
|
||||
val = dynamic_cast<toml::Table *>(table)->access(name, type, found);
|
||||
val = dynamic_cast<toml::ANode *>(table)->access(name, type, found);
|
||||
if (found == true && val != not_nullptr) {
|
||||
return val;
|
||||
} else {
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/10 13:43:54 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/10 13:58:52 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/11 11:36:22 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -14,3 +14,5 @@
|
||||
|
||||
#define SAMPLE_CONF_PATH "./sample.conf"
|
||||
#define WEBSRV_VERSION "v0.1"
|
||||
|
||||
bool help(int, char **);
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/20 09:28:27 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/10 14:21:46 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 16:14:25 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -19,22 +19,41 @@
|
||||
#include <string>
|
||||
|
||||
namespace webserv {
|
||||
|
||||
/**
|
||||
* @brief Used to log debug message
|
||||
*
|
||||
* @note Only work if VERBOSE mode is active
|
||||
*/
|
||||
static inline void log(std::string emoji, std::string who, std::string str) {
|
||||
#ifdef VERBOSE
|
||||
if (who.empty())
|
||||
std::cout << "「" << emoji << "」debug: " << str << std::endl;
|
||||
else
|
||||
std::cout << "「" << emoji << "」debug(" << who << "): " << str
|
||||
<< std::endl;
|
||||
#else
|
||||
(void)emoji, (void)who, (void)str;
|
||||
#endif
|
||||
}
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
Logger(void) : _ttyOnly(true) {
|
||||
log("➕", "Logger", "default constructor called");
|
||||
}
|
||||
Logger(const std::string &fileName) : _fileName(fileName) {
|
||||
if (fileName.empty())
|
||||
_ttyOnly = true;
|
||||
else {
|
||||
_file.open(fileName.c_str(), std::ios::app);
|
||||
_ttyOnly = false;
|
||||
}
|
||||
log("➕", "Logger", "filename constructor called");
|
||||
_file.open(fileName.c_str(), std::ios::app);
|
||||
if (!_file.is_open() && !_ttyOnly) {
|
||||
_ttyOnly = true;
|
||||
warn("could not open log file, going tty only");
|
||||
}
|
||||
} else
|
||||
_ttyOnly = false;
|
||||
}
|
||||
|
||||
Logger(const Logger &other) : _ttyOnly(other._ttyOnly) {
|
||||
log("➕", "Logger", "copy constructor called");
|
||||
if (!other._ttyOnly) {
|
||||
_file.open(other._fileName.c_str(), std::ios::app);
|
||||
if (!_file.is_open()) {
|
||||
@ -46,6 +65,7 @@ class Logger {
|
||||
|
||||
// Copy assignment operator
|
||||
Logger &operator=(const Logger &other) {
|
||||
log("➕", "Logger", "copy assignment constructor called");
|
||||
if (this != &other) {
|
||||
if (_file.is_open()) {
|
||||
_file.close();
|
||||
@ -62,6 +82,7 @@ class Logger {
|
||||
return *this;
|
||||
}
|
||||
~Logger(void) {
|
||||
log("➖", "Logger", "destructor called");
|
||||
if (_file.is_open())
|
||||
_file.close();
|
||||
}
|
||||
@ -88,12 +109,23 @@ class Logger {
|
||||
}
|
||||
}
|
||||
|
||||
void debug(const std::string &msg) {
|
||||
#ifdef VERBOSE
|
||||
std::string ss = printPogitMsg("🏗️", "webserv", "debug", msg);
|
||||
std::cerr << ss << std::endl;
|
||||
if (!_ttyOnly) {
|
||||
_file << ss << std::endl;
|
||||
}
|
||||
#else
|
||||
(void)msg;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::string printPogitMsg(const std::string &emoji,
|
||||
const std::string &type,
|
||||
const std::string &what,
|
||||
const std::string &msg) {
|
||||
std::string printPogitMsg(const std::string &emoji, const std::string &type,
|
||||
const std::string &what, const std::string &msg) {
|
||||
std::stringstream os;
|
||||
#ifdef TTY
|
||||
(void)emoji;
|
||||
@ -103,9 +135,9 @@ class Logger {
|
||||
os << type << "(" << what << "):" << msg;
|
||||
#else
|
||||
if (what.empty())
|
||||
os << "「" << emoji << "」" << type << ":" << msg;
|
||||
os << "「" << emoji << "」" << type << ": " << msg;
|
||||
else
|
||||
os << "「" << emoji << "」" << type << "(" << what << "):" << msg;
|
||||
os << "「" << emoji << "」" << type << "(" << what << "): " << msg;
|
||||
#endif
|
||||
return os.str();
|
||||
}
|
||||
@ -115,4 +147,6 @@ class Logger {
|
||||
std::ofstream _file;
|
||||
};
|
||||
|
||||
extern Logger *_log;
|
||||
|
||||
}; // namespace webserv
|
||||
|
@ -6,13 +6,11 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/16 17:51:46 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/03/24 15:05:53 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/04/22 11:52:00 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
#ifndef __WEBSERV_REQUESTS_ERRORS_HPP__
|
||||
# define __WEBSERV_REQUESTS_ERRORS_HPP__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@ -22,16 +20,10 @@
|
||||
namespace webserv {
|
||||
namespace http {
|
||||
|
||||
/*
|
||||
* DOES NOT WORK
|
||||
* still need to do uh things but base is done at least :D
|
||||
*/
|
||||
|
||||
class Errors {
|
||||
public:
|
||||
//static http::Response &getRequest(int error_code);
|
||||
static std::string getResponseBody(int error_code);
|
||||
static void setEntry(const std::string &key, int value);
|
||||
static void setEntries(const std::map<int, std::string>);
|
||||
|
||||
static std::map<int, std::string> message;
|
||||
private:
|
||||
@ -43,5 +35,3 @@ private:
|
||||
|
||||
} // -namespace http
|
||||
} // -namespace webserv
|
||||
|
||||
#endif // __WEBSERV_REQUESTS_ERRORS_HPP__
|
||||
|
@ -6,13 +6,11 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/11 22:13:38 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/04/02 01:47:24 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/04/23 14:38:55 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
#ifndef __WEBSERV_REQUESTS_HTTP_IMESSAGE_HPP__
|
||||
# define __WEBSERV_REQUESTS_HTTP_IMESSAGE_HPP__
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
@ -25,6 +23,8 @@ public:
|
||||
virtual std::map<std::string, std::string> getHeaders(void) const;
|
||||
virtual std::string getBody(void) const;
|
||||
|
||||
virtual ~IMessage() {}
|
||||
|
||||
virtual void setHeaders(std::map<std::string, std::string> const headers);
|
||||
virtual void setBody(std::string const body);
|
||||
|
||||
@ -43,5 +43,3 @@ protected:
|
||||
|
||||
} // -namespace http
|
||||
} // -namespace webserv
|
||||
|
||||
#endif // __WEBSERV_REQUESTS_HTTP_IMESSAGE_HPP__
|
||||
|
@ -6,13 +6,11 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/03 17:23:00 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/02/14 15:43:32 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/04/22 15:07:02 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
#ifndef __WEBSERV_REQUESTS_HTTP_REQUEST_HPP__
|
||||
# define __WEBSERV_REQUESTS_HTTP_REQUEST_HPP__
|
||||
|
||||
#include <ctime>
|
||||
#include <fstream>
|
||||
@ -22,11 +20,15 @@
|
||||
#include <requests/HttpIMessage.hpp>
|
||||
#include <requests/HttpResponse.hpp>
|
||||
|
||||
#include <config/default.hpp>
|
||||
|
||||
namespace webserv {
|
||||
namespace http {
|
||||
|
||||
class IRequest: public http::IMessage {
|
||||
public:
|
||||
virtual ~IRequest(void);
|
||||
|
||||
virtual void parse(std::string const &data) = 0;
|
||||
virtual http::Response execute(void) = 0;
|
||||
|
||||
@ -35,21 +37,25 @@ public:
|
||||
std::string getMethod(void) const;
|
||||
std::string getTarget(void) const;
|
||||
std::string getProtocol(void) const;
|
||||
config::Server *getConfig(void) const;
|
||||
|
||||
void setMethod(std::string const method);
|
||||
void setTarget(std::string const target);
|
||||
void setProtocol(std::string const protocol);
|
||||
void setServer(std::string const protocol);
|
||||
|
||||
protected:
|
||||
std::string _method;
|
||||
std::string _target;
|
||||
std::string _protocol;
|
||||
config::Server *_conf;
|
||||
|
||||
};
|
||||
|
||||
class Get: public http::IRequest {
|
||||
public:
|
||||
Get(void);
|
||||
~Get(void);
|
||||
Get(std::string &data);
|
||||
|
||||
void parse(std::string const &data);
|
||||
@ -61,6 +67,7 @@ public:
|
||||
class Post: public http::IRequest {
|
||||
public:
|
||||
Post(void);
|
||||
~Post(void);
|
||||
Post(std::string &data);
|
||||
|
||||
void parse(std::string const &data);
|
||||
@ -72,6 +79,7 @@ public:
|
||||
class Delete: public http::IRequest {
|
||||
public:
|
||||
Delete(void);
|
||||
~Delete(void);
|
||||
Delete(std::string &data);
|
||||
|
||||
void parse(std::string const &data);
|
||||
@ -82,5 +90,3 @@ public:
|
||||
|
||||
} // -namespace http
|
||||
} // -namespace webserv
|
||||
|
||||
#endif // __WEBSERV_REQUESTS_HTTP_REQUEST_HPP__
|
||||
|
@ -6,13 +6,11 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/03 17:21:20 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/03/24 15:16:39 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/04/23 14:36:47 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
#ifndef __WEBSERV_REQUESTS_HTTP_RESPONSE_HPP__
|
||||
# define __WEBSERV_REQUESTS_HTTP_RESPONSE_HPP__
|
||||
|
||||
#include <sstream>
|
||||
|
||||
@ -26,6 +24,7 @@ namespace http {
|
||||
class Response: public http::IMessage {
|
||||
public:
|
||||
Response(void);
|
||||
~Response(void);
|
||||
|
||||
std::string getProtocol(void) const;
|
||||
uint getStatusCode(void) const;
|
||||
@ -45,5 +44,3 @@ private:
|
||||
|
||||
} // -namespace http
|
||||
} // -namespace webserv
|
||||
|
||||
#endif // __WEBSERV_REQUESTS_HTTP_RESPONSE_HPP__
|
||||
|
@ -6,18 +6,14 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/03 15:48:22 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/03/17 14:08:50 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/04/22 11:51:54 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
#ifndef __WEBSERV_REQUESTS_DEFAULT_HPP__
|
||||
# define __WEBSERV_REQUESTS_DEFAULT_HPP__
|
||||
|
||||
#include <requests/Errors.hpp>
|
||||
#include <requests/HttpRequest.hpp>
|
||||
#include <requests/HttpResponse.hpp>
|
||||
|
||||
using namespace webserv;
|
||||
|
||||
#endif // __WEBSERV_REQUESTS_DEFAULT_HPP__
|
||||
|
42
includes/server/Client.hpp
Normal file
42
includes/server/Client.hpp
Normal file
@ -0,0 +1,42 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Client.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/14 14:14:39 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/23 14:39:16 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <config/default.hpp>
|
||||
#include <netinet/in.h>
|
||||
#include <requests/default.hpp>
|
||||
#include <server/default.hpp>
|
||||
#include <webserv.hpp>
|
||||
|
||||
namespace webserv {
|
||||
namespace server {
|
||||
|
||||
class Client {
|
||||
public:
|
||||
Client(int, sockaddr_in, config::Config *);
|
||||
virtual ~Client(void);
|
||||
|
||||
void answer(void);
|
||||
|
||||
private:
|
||||
void _getRequest(std::string);
|
||||
|
||||
int _fd;
|
||||
struct sockaddr_in _client_addr;
|
||||
http::IRequest *_request;
|
||||
//http::Response *_response;
|
||||
config::Server *_conf;
|
||||
};
|
||||
|
||||
} // namespace server
|
||||
} // namespace webserv
|
92
includes/server/Server.hpp
Normal file
92
includes/server/Server.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Server.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/11 17:45:43 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/22 11:51:27 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <log.hpp>
|
||||
#include <config/default.hpp>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdexcept>
|
||||
#include <sys/poll.h>
|
||||
#include <vector>
|
||||
|
||||
namespace webserv {
|
||||
|
||||
struct client_data {
|
||||
sockaddr_in sock_data;
|
||||
pollfd poll_fd;
|
||||
};
|
||||
|
||||
class Server {
|
||||
public:
|
||||
Server(config::Config *);
|
||||
~Server(void);
|
||||
|
||||
protected:
|
||||
private:
|
||||
/**
|
||||
* @brief Used to setup the webserver (primarly socket)
|
||||
*/
|
||||
void _setup(void);
|
||||
/**
|
||||
* @brief Used to run the webserver
|
||||
*/
|
||||
void _run(void);
|
||||
|
||||
/**
|
||||
* @brief Used to handle client request
|
||||
*
|
||||
* @param The fd of the client
|
||||
*/
|
||||
bool _handle_client(struct pollfd &, sockaddr_in *);
|
||||
|
||||
/**
|
||||
* @brief Can be used to fill the vector passed as parameters with all the
|
||||
* port and host in the config
|
||||
* @param The vector of host
|
||||
* @param The vector of port
|
||||
*/
|
||||
int _fillHostsPorts(std::vector<std::string> &, std::vector<int> &);
|
||||
|
||||
/**
|
||||
* @brief Can be used to open a socket with a specific port and host
|
||||
* @param The host
|
||||
* @param The port
|
||||
*/
|
||||
int _createSocket(std::string, int);
|
||||
|
||||
/**
|
||||
* @brief Can be used to check if an fd is one of the socket or not
|
||||
*
|
||||
* @param the fd to check
|
||||
*/
|
||||
bool _isServerSocket(int fd) {
|
||||
for (std::vector<int>::iterator it = _fds_server.begin();
|
||||
it != _fds_server.end(); it++) {
|
||||
if (fd == *it) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
config::Config
|
||||
*_conf; // Pointer to the configuration class (with all config in)
|
||||
Logger *_log; // Pointer to the log class
|
||||
std::vector<int> _fds_server; // The fds of the sockets
|
||||
std::vector<struct pollfd> _client_fds; // A vector of all the poll fd
|
||||
std::vector<sockaddr_in *>
|
||||
_client_data; // vector of all the client sockaddr_in
|
||||
};
|
||||
|
||||
}; // namespace webserv
|
@ -6,20 +6,19 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/11 13:29:05 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/02/12 00:14:11 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/04/22 12:04:53 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
#ifndef __WEBSERV_SERVER_DEFAULT_HPP__
|
||||
# define __WEBSERV_SERVER_DEFAULT_HPP__
|
||||
|
||||
#include <server/Server.hpp>
|
||||
#include <server/Client.hpp>
|
||||
|
||||
namespace webserv {
|
||||
namespace server {
|
||||
|
||||
} // -namespace server
|
||||
|
||||
|
||||
} // -namespace webserv
|
||||
|
||||
using namespace webserv;
|
||||
|
||||
#endif // __WEBSERV_SERVER_DEFAULT_HPP__
|
||||
|
@ -6,26 +6,40 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/11 13:29:21 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/04/10 13:58:56 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 14:27:31 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#pragma once
|
||||
#ifndef __WEBSERV_WEBSERV_HPP__
|
||||
# define __WEBSERV_WEBSERV_HPP__
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#define auto __auto_type
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
#define range(x) \
|
||||
x.begin(); \
|
||||
it != x.end(); \
|
||||
it++
|
||||
#define prange(x) \
|
||||
x->begin(); \
|
||||
it != x->end(); \
|
||||
it++
|
||||
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
namespace webserv {
|
||||
|
||||
} //-namespace webserv
|
||||
} // namespace webserv
|
||||
|
||||
#endif // __WEBSERV_WEBSERV_HPP__
|
||||
|
9
sample.conf
Normal file
9
sample.conf
Normal file
@ -0,0 +1,9 @@
|
||||
[server]
|
||||
host = "localhost"
|
||||
port = 8080
|
||||
|
||||
[server.location./]
|
||||
methods = { "GET" }
|
||||
root = "/var/www/html"
|
||||
dirlist = true
|
||||
client_max_body_size = "10M"
|
60
src/config/Config.cpp
Normal file
60
src/config/Config.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Config.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/14 12:53:54 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/22 15:35:52 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "node/default.hpp"
|
||||
#include "webserv.hpp"
|
||||
#include "cppeleven.hpp"
|
||||
#include "node/ANode.hpp"
|
||||
#include <config/default.hpp>
|
||||
|
||||
using namespace webserv::config;
|
||||
|
||||
Config::Config(std::string &filename) {
|
||||
toml::Toml *file = new toml::Toml(filename);
|
||||
|
||||
file->parse();
|
||||
toml::ANode *table = file->getParsedFile();
|
||||
|
||||
bool found = false;
|
||||
void *logFile = table->access("log_file", toml::STRING, found);
|
||||
if (found == true && logFile != not_nullptr) {
|
||||
_log = new Logger(*static_cast<std::string *>(logFile));
|
||||
} else {
|
||||
_log = new Logger();
|
||||
}
|
||||
|
||||
std::map<std::string, toml::ANode *> *node = table->getTable();
|
||||
for (auto it = prange(node)) {
|
||||
if (it->second->type() == toml::TABLE) {
|
||||
_log->info("taking server from table : " + it->first);
|
||||
Server *srv = new Server(it->second);
|
||||
_servers.push_back(srv);
|
||||
}
|
||||
}
|
||||
delete table;
|
||||
delete file;
|
||||
}
|
||||
|
||||
Config::~Config(void) {
|
||||
for (auto it = range(_servers)) {
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
|
||||
Server *Config::getServer(const std::string &server_name) {
|
||||
for (auto it = range(_servers)) {
|
||||
if ((*it)->isServerName(server_name)) {
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
return (not_nullptr);
|
||||
}
|
@ -9,12 +9,13 @@
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "cppeleven.hpp"
|
||||
#include "log.hpp"
|
||||
#include <log.hpp>
|
||||
#include "node/default.hpp"
|
||||
#include <config/default.hpp>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
using namespace webserv::config;
|
||||
|
||||
std::map<std::string, std::string> *Route::_parseCGI(toml::ANode *table) {
|
||||
@ -57,12 +58,11 @@ void Route::_parseMethods(std::vector<toml::ANode *> *table) {
|
||||
}
|
||||
}
|
||||
|
||||
Route::Route(toml::ANode *table, Logger *logger)
|
||||
: _max_body(10485760), _log(logger) {
|
||||
Route::Route(toml::ANode *table)
|
||||
: _max_body(10485760) {
|
||||
void *val;
|
||||
bool found;
|
||||
|
||||
_log = logger;
|
||||
_table = table;
|
||||
if (_table->type() != toml::TABLE) {
|
||||
_log->warn("location need to be a table and not a :" +
|
||||
|
@ -6,71 +6,37 @@
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/03/24 15:10:07 by adjoly #+# #+# */
|
||||
/* Updated: 2025/03/26 08:47:50 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 15:36:30 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "config/Server.hpp"
|
||||
#include "config/Route.hpp"
|
||||
#include "cppeleven.hpp"
|
||||
#include "log.hpp"
|
||||
#include "node/ANode.hpp"
|
||||
#include "node/Table.hpp"
|
||||
#include "node/default.hpp"
|
||||
#include "tomlpp.hpp"
|
||||
#include <config/default.hpp>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sys/types.h>
|
||||
#include <webserv.hpp>
|
||||
|
||||
using namespace webserv::config;
|
||||
|
||||
toml::ANode *Server::_getServerTable(void) {
|
||||
toml::ANode *serverT;
|
||||
|
||||
std::map<std::string, toml::ANode *>::iterator table =
|
||||
_table->getTable()->find("server");
|
||||
if (table == _table->getTable()->end())
|
||||
throw std::runtime_error(
|
||||
"could not find any [server] table in config file :(");
|
||||
else
|
||||
serverT = table->second;
|
||||
return serverT;
|
||||
}
|
||||
|
||||
Server::Server(std::string file_name) {
|
||||
toml::Toml *tomlFile = new toml::Toml(file_name);
|
||||
|
||||
try {
|
||||
tomlFile->parse();
|
||||
} catch (std::runtime_error &e) {
|
||||
throw e;
|
||||
}
|
||||
Server::Server(toml::ANode *node) : _table(node) {
|
||||
bool found;
|
||||
|
||||
std::map<std::string, toml::ANode *> *map;
|
||||
_table = tomlFile->getParsedFile();
|
||||
if (_table == not_nullptr)
|
||||
return;
|
||||
|
||||
void *val = _table->access("log_file", toml::STRING, found);
|
||||
std::string log_file = "";
|
||||
if (found == true && val != not_nullptr) {
|
||||
std::string log_file = *static_cast<std::string *>(val);
|
||||
}
|
||||
_log = new Logger(log_file);
|
||||
_table = _getServerTable();
|
||||
|
||||
// host and port parsing
|
||||
// host parsing
|
||||
void *host = accessValue("host", toml::STRING, _table, _log);
|
||||
if (host != not_nullptr) {
|
||||
_host = *static_cast<std::string *>(host);
|
||||
} else {
|
||||
delete _table;
|
||||
throw std::runtime_error(
|
||||
"no host specified - please specify one in server.host");
|
||||
}
|
||||
// port parsing
|
||||
void *port = accessValue("port", toml::INT, _table, _log);
|
||||
if (host != not_nullptr) {
|
||||
if (port != not_nullptr) {
|
||||
_port = *static_cast<unsigned short *>(port);
|
||||
} else {
|
||||
delete _table;
|
||||
throw std::runtime_error(
|
||||
"no port specified - please specify one in server.port");
|
||||
}
|
||||
@ -86,13 +52,16 @@ Server::Server(std::string file_name) {
|
||||
std::string str = *static_cast<std::string *>((*vecIt)->getValue());
|
||||
_server_names->push_back(str);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
_log->warn(
|
||||
"no server_names all request will be accepted from any hostname");
|
||||
_server_names = not_nullptr;
|
||||
}
|
||||
|
||||
// error_pages parsing
|
||||
map = static_cast<std::map<std::string, toml::ANode *> *>(
|
||||
accessValue("error_pages", toml::TABLE, _table, _log));
|
||||
std::map<std::string, toml::ANode *> *map =
|
||||
static_cast<std::map<std::string, toml::ANode *> *>(
|
||||
accessValue("error_pages", toml::TABLE, _table, _log));
|
||||
if (map != not_nullptr) {
|
||||
_err_pages = _parseErrPages(map);
|
||||
} else
|
||||
@ -101,27 +70,26 @@ Server::Server(std::string file_name) {
|
||||
// location parsing
|
||||
it = _table->accessIt("location", toml::TABLE, found);
|
||||
if (found == true && it != _table->getTable()->end()) {
|
||||
_routes = new std::map<std::string, Route *>;
|
||||
std::map<std::string, toml::ANode *> *location_table = it->second->getTable();
|
||||
_routes = new std::map<URL, Route *>;
|
||||
std::map<std::string, toml::ANode *> *location_table =
|
||||
it->second->getTable();
|
||||
for (it = location_table->begin(); it != location_table->end(); it++) {
|
||||
if (_routes->find(it->first) != _routes->end())
|
||||
if (_routes->find(URL(it->first)) != _routes->end())
|
||||
continue;
|
||||
(*_routes)[it->first] = new Route(it->second, _log);
|
||||
(*_routes)[URL(it->first)] = new Route(it->second);
|
||||
}
|
||||
}
|
||||
delete tomlFile->getParsedFile();
|
||||
delete tomlFile;
|
||||
//delete _table;
|
||||
}
|
||||
|
||||
Server::~Server(void) {
|
||||
std::map<std::string, Route *>::iterator it = _routes->begin();
|
||||
for (; it != _routes->end(); it++) {
|
||||
for (auto it = prange(_routes)) {
|
||||
delete it->second;
|
||||
}
|
||||
delete _routes;
|
||||
delete _err_pages;
|
||||
delete _server_names;
|
||||
delete _log; // to see if nessecary
|
||||
if (_server_names != not_nullptr)
|
||||
delete _server_names;
|
||||
}
|
||||
|
||||
std::map<int, std::string> *
|
||||
@ -143,3 +111,21 @@ Server::_parseErrPages(std::map<std::string, toml::ANode *> *table) {
|
||||
}
|
||||
return errPages;
|
||||
}
|
||||
|
||||
bool Server::isServerName(const std::string &server_name) {
|
||||
for (auto it = prange(_server_names)) {
|
||||
if (*it == server_name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Route *Server::whatRoute(const URL &url) {
|
||||
for (auto it = prange(_routes)) {
|
||||
if (it->first == url) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return not_nullptr;
|
||||
}
|
||||
|
24
src/help.cpp
24
src/help.cpp
@ -6,11 +6,11 @@
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/10 13:08:36 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/10 14:20:36 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 11:47:39 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "log.hpp"
|
||||
#include <log.hpp>
|
||||
#include <fstream>
|
||||
#include <help.hpp>
|
||||
#include <sys/stat.h>
|
||||
@ -37,7 +37,7 @@ void _generateConf(void) {
|
||||
file << "[server]\nhost = \"localhost\"\nport = "
|
||||
"8080\n\n[server.location./]\nmethods = { \"GET\" }\nroot "
|
||||
"= \"/var/www/html\"\ndirlist = true\nclient_max_body_size "
|
||||
"= \"10M\"";
|
||||
"= \"10M\"\n";
|
||||
file.close();
|
||||
_log.info("config file successfully generated");
|
||||
} else {
|
||||
@ -50,16 +50,24 @@ void _printVersion(void) {
|
||||
std::cout << "You are running : Webserv " << WEBSRV_VERSION << std::endl;
|
||||
}
|
||||
|
||||
void help(int ac, char **av) {
|
||||
bool help(int ac, char **av) {
|
||||
if (ac < 2) {
|
||||
_printHelp();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
std::string option = av[1];
|
||||
if (option == "--help" || option == "-v")
|
||||
if (option == "--help" || option == "-v") {
|
||||
_printHelp();
|
||||
else if (option == "--generate" || option == "-g")
|
||||
return true;
|
||||
}
|
||||
else if (option == "--generate" || option == "-g") {
|
||||
_generateConf();
|
||||
else if (option == "--version" || option == "-v")
|
||||
return true;
|
||||
}
|
||||
else if (option == "--version" || option == "-v") {
|
||||
_printVersion();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
165
src/main.cpp
165
src/main.cpp
@ -6,134 +6,65 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/03 15:45:07 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/04/10 12:18:39 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/03/25 17:10:29 by adjoly ### ########.fr */
|
||||
/* Updated: 2025/04/22 15:43:21 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include <config/Server.hpp>
|
||||
#include <tomlpp.hpp>
|
||||
#include <webserv.hpp>
|
||||
#include <config/default.hpp>
|
||||
#include <csignal>
|
||||
#include <server/default.hpp>
|
||||
#include <config/Config.hpp>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <help.hpp>
|
||||
#include <requests/default.hpp>
|
||||
#include <sstream>
|
||||
#include <tomlpp.hpp>
|
||||
#include <unistd.h>
|
||||
#include <log.hpp>
|
||||
#include <webserv.hpp>
|
||||
|
||||
#define PORT 8080
|
||||
#define BUFFER_SIZE 4096
|
||||
|
||||
int server_socket;
|
||||
int client_socket;
|
||||
|
||||
void close_socket(int signal)
|
||||
{
|
||||
std::cerr << std::endl << "closing..." << std::endl;
|
||||
close(client_socket);
|
||||
close(server_socket);
|
||||
exit(signal);
|
||||
namespace webserv {
|
||||
Logger *_log = not_nullptr;
|
||||
}
|
||||
|
||||
std::string getMethod(std::string &data)
|
||||
{
|
||||
return (data.substr(0, data.substr(0, 4).find_last_not_of(" ") + 1));
|
||||
int _sig = 0;
|
||||
|
||||
void ft_sig(int sig) {
|
||||
_sig = sig;
|
||||
std::stringstream str;
|
||||
str << "sig hitted = ";
|
||||
str << sig;
|
||||
_log->info(str.str());
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
// handle ctrl-C to close server socket
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR || signal(SIGINT, close_socket) == SIG_ERR || signal(SIGQUIT, close_socket) == SIG_ERR)
|
||||
{
|
||||
std::cerr << "Error registering signal handlers!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
int main(int ac, char **av) {
|
||||
if (help(ac, av)) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
std::cout << "Starting server..." << std::endl;
|
||||
if (access(av[1], F_OK) < 0) {
|
||||
std::cout << "File : " << av[1] << " could not be opened" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// create a socket
|
||||
server_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (server_socket == -1)
|
||||
{
|
||||
std::cerr << "Failed to create socket" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// prepare the server address
|
||||
sockaddr_in server_address;
|
||||
std::memset(&server_address, 0, sizeof(server_address));
|
||||
server_address.sin_family = AF_INET;
|
||||
server_address.sin_addr.s_addr = INADDR_ANY;
|
||||
server_address.sin_port = htons(PORT);
|
||||
config::Config *conf;
|
||||
try {
|
||||
std::string str = av[1];
|
||||
conf = new config::Config(str);
|
||||
} catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (signal(SIGINT, &ft_sig) == SIG_ERR) {
|
||||
conf->getLogger()->error("could not bind sigint :(");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (bind(server_socket, (sockaddr*)&server_address, sizeof(server_address)) == -1)
|
||||
{
|
||||
std::cerr << "Failed to bind socket" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
if (listen(server_socket, 5) == -1)
|
||||
{
|
||||
std::cerr << "Failed to listen on socket" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
webserv::Server *serv = new webserv::Server(conf);
|
||||
|
||||
std::cout << "Server is listening on port " << PORT << std::endl;
|
||||
|
||||
while (true)
|
||||
{
|
||||
// accept an incoming connection
|
||||
sockaddr_in client_address;
|
||||
socklen_t client_address_len = sizeof(client_address);
|
||||
//int client_socket = accept(server_socket, (sockaddr*)&client_address, &client_address_len);
|
||||
client_socket = accept(server_socket, (sockaddr*)&client_address, &client_address_len);
|
||||
if (client_socket == -1) {
|
||||
std::cerr << "Failed to accept connection" << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
// receive the HTTP request
|
||||
std::string received_data;
|
||||
char buffer[BUFFER_SIZE];
|
||||
ssize_t bytes_received;
|
||||
do
|
||||
{
|
||||
std::memset(buffer, 0, BUFFER_SIZE);
|
||||
bytes_received = recv(client_socket, buffer, BUFFER_SIZE - 1, 0);
|
||||
if (bytes_received == -1)
|
||||
{
|
||||
std::cerr << "Failed to receive request" << std::endl;
|
||||
close(client_socket);
|
||||
continue;
|
||||
}
|
||||
received_data += std::string(buffer, bytes_received);
|
||||
}
|
||||
while (buffer[bytes_received]);
|
||||
|
||||
// parse the request
|
||||
|
||||
// handle the request
|
||||
std::string response;
|
||||
|
||||
//std::cout << received_data << std::endl;
|
||||
std::cout << getMethod(received_data) << std::endl;
|
||||
|
||||
if (getMethod(received_data) == "GET")
|
||||
{
|
||||
std::cout << "------------ GET REQUEST ------------" << std::endl;
|
||||
http::Get request(received_data);
|
||||
|
||||
response = request.execute().str();
|
||||
}
|
||||
else if (getMethod(received_data) == "POST")
|
||||
{
|
||||
std::cout << "------------ POST REQUEST ------------" << std::endl;
|
||||
http::Post request(received_data);
|
||||
|
||||
response = request.execute().str();
|
||||
//std::cout << "worked" << std::endl;
|
||||
}
|
||||
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>";
|
||||
}
|
||||
|
||||
send(client_socket, response.c_str(), response.length(), 0);
|
||||
//close(client_socket);
|
||||
}
|
||||
|
||||
close(server_socket);
|
||||
return 0;
|
||||
delete serv;
|
||||
delete _log;
|
||||
delete conf;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/03 16:07:01 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/04/10 11:50:48 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/04/22 15:03:46 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -20,6 +20,10 @@
|
||||
|
||||
using namespace webserv;
|
||||
|
||||
http::IRequest::~IRequest(void) {
|
||||
|
||||
}
|
||||
|
||||
std::string http::IRequest::str(void) const
|
||||
{
|
||||
std::ostringstream response;
|
||||
@ -75,6 +79,10 @@ http::Get::Get(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Get::~Get(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Get::Get(std::string &data)
|
||||
{
|
||||
this->parse(data);
|
||||
@ -218,6 +226,10 @@ http::Delete::Delete(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Delete::~Delete(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Delete::Delete(std::string &data)
|
||||
{
|
||||
this->parse(data);
|
||||
@ -297,6 +309,10 @@ http::Post::Post(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Post::~Post(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Post::Post(std::string &data)
|
||||
{
|
||||
this->parse(data);
|
||||
|
@ -6,7 +6,7 @@
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/02/03 17:28:31 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/04/08 01:11:40 by mmoussou ### ########.fr */
|
||||
/* Updated: 2025/04/23 14:30:28 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -27,6 +27,10 @@ http::Response::Response(void)
|
||||
{
|
||||
}
|
||||
|
||||
http::Response::~Response(void)
|
||||
{
|
||||
}
|
||||
|
||||
std::string http::Response::str(void) const
|
||||
{
|
||||
std::ostringstream response;
|
||||
|
76
src/server/Client.cpp
Normal file
76
src/server/Client.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Client.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: mmoussou <mmoussou@student.42angouleme.fr +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/17 11:12:41 by mmoussou #+# #+# */
|
||||
/* Updated: 2025/04/23 14:40:06 by mmoussou ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include <log.hpp>
|
||||
#include <server/Client.hpp>
|
||||
|
||||
using namespace server;
|
||||
|
||||
Client::Client(int fd, sockaddr_in socket, config::Config *conf)
|
||||
: _fd(fd), _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(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) )
|
||||
// throw error
|
||||
}
|
||||
|
||||
void Client::_getRequest(std::string request_str) {
|
||||
std::string method = request_str.substr(
|
||||
0, request_str.substr(0, 4).find_last_not_of(" ") + 1);
|
||||
|
||||
if (method == "GET") {
|
||||
_log->info("get request received");
|
||||
this->_request = new http::Get(request_str);
|
||||
} else if (method == "DELETE") {
|
||||
_log->info("delete request received");
|
||||
this->_request = new http::Delete(request_str);
|
||||
} else if (method == "POST") {
|
||||
_log->info("post request received");
|
||||
this->_request = new http::Post(request_str);
|
||||
} else {
|
||||
_log->info("unsupported request received");
|
||||
this->_request = new http::Get();
|
||||
this->_request->setMethod("501");
|
||||
}
|
||||
}
|
||||
|
||||
void Client::answer(void) {
|
||||
(void) _client_addr;
|
||||
std::string response;
|
||||
|
||||
if (this->_request->getMethod() == "GET" ||
|
||||
this->_request->getMethod() == "DELETE" ||
|
||||
this->_request->getMethod() == "POST")
|
||||
response = this->_request->execute().str();
|
||||
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>";
|
||||
send(this->_fd, response.c_str(), response.length(), 0);
|
||||
}
|
||||
|
||||
Client::~Client(void) {
|
||||
delete (http::Get *)(this->_request);
|
||||
}
|
166
src/server/Server.cpp
Normal file
166
src/server/Server.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Server.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/11 16:11:40 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/23 16:22:22 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <fcntl.h>
|
||||
#include <iterator>
|
||||
#include <log.hpp>
|
||||
#include <netinet/in.h>
|
||||
#include <poll.h>
|
||||
#include <requests/default.hpp>
|
||||
#include <server/default.hpp>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <webserv.hpp>
|
||||
|
||||
using namespace webserv;
|
||||
|
||||
extern int _sig;
|
||||
|
||||
std::string convertIPToString(const struct in_addr *addr) {
|
||||
unsigned int ip = ntohl(addr->s_addr);
|
||||
std::stringstream ss;
|
||||
ss << ((ip >> 24) & 0xFF) << "." << ((ip >> 16) & 0xFF) << "."
|
||||
<< ((ip >> 8) & 0xFF) << "." << (ip & 0xFF);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string convertPortToString(const struct sockaddr_in *sa) {
|
||||
int port = ntohs(sa->sin_port);
|
||||
std::stringstream ss;
|
||||
ss << port;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string getMethod(std::string &data) {
|
||||
return (data.substr(0, data.substr(0, 4).find_last_not_of(" ") + 1));
|
||||
}
|
||||
|
||||
int Server::_fillHostsPorts(std::vector<std::string> &hosts,
|
||||
std::vector<int> &ports) {
|
||||
std::vector<config::Server *> config = _conf->getServers();
|
||||
|
||||
for (auto it = range(config)) {
|
||||
hosts.push_back((*it)->getHost());
|
||||
ports.push_back((*it)->getPort());
|
||||
}
|
||||
return config.size();
|
||||
}
|
||||
|
||||
void Server::_setup(void) {
|
||||
std::vector<std::string> hosts;
|
||||
std::vector<int> ports;
|
||||
|
||||
int size = _fillHostsPorts(hosts, ports);
|
||||
if (size < 1)
|
||||
throw std::runtime_error("no server present in the config file");
|
||||
|
||||
auto itH = hosts.begin();
|
||||
for (auto it = range(ports), itH++) {
|
||||
int fd = _createSocket(*itH, *it);
|
||||
_fds_server.push_back(fd);
|
||||
}
|
||||
}
|
||||
|
||||
short sigHandling(void) {
|
||||
if (_sig == SIGINT) {
|
||||
return 727;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Server::_run(void) {
|
||||
struct pollfd fd;
|
||||
|
||||
for (std::vector<int>::iterator it = _fds_server.begin();
|
||||
it != _fds_server.end(); it++) {
|
||||
fd.fd = *it;
|
||||
fd.events = POLLIN;
|
||||
_client_fds.push_back(fd);
|
||||
_client_data.push_back(NULL);
|
||||
_log->debug("new socket in poll");
|
||||
}
|
||||
|
||||
// to add signal instead of 727
|
||||
while (727 - sigHandling()) {
|
||||
if (poll(_client_fds.data(), _client_fds.size(), -1) < 0) {
|
||||
std::stringstream str;
|
||||
str << "poll failed : ";
|
||||
str << strerror(errno);
|
||||
_log->error(str.str());
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto it = range(_fds_server)) {
|
||||
struct sockaddr_in client_addr;
|
||||
socklen_t addrlen = sizeof(client_addr);
|
||||
int client_fd =
|
||||
accept((*it), (struct sockaddr *)&client_addr, &addrlen);
|
||||
|
||||
if (client_fd < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
continue;
|
||||
std::stringstream str;
|
||||
str << "Accept failed: ";
|
||||
str << strerror(errno);
|
||||
_log->error(str.str());
|
||||
continue;
|
||||
}
|
||||
|
||||
pollfd pfd;
|
||||
pfd.fd = client_fd;
|
||||
pfd.events = POLLIN | POLLOUT;
|
||||
pfd.revents = 0;
|
||||
_client_fds.push_back(pfd);
|
||||
struct sockaddr_in *new_client_sock = new sockaddr_in();
|
||||
std::memmove(new_client_sock, &client_addr,
|
||||
sizeof(struct sockaddr_in));
|
||||
_client_data.push_back(new_client_sock);
|
||||
}
|
||||
|
||||
for (size_t i = _fds_server.size(); i < _client_fds.size(); ++i) {
|
||||
if (_client_fds[i].revents & POLLIN) {
|
||||
if (_handle_client(_client_fds[i], _client_data[i])) {
|
||||
close(_client_fds[i].fd);
|
||||
_client_fds.erase(_client_fds.begin() + i);
|
||||
delete _client_data[i];
|
||||
_client_data.erase(_client_data.begin() + i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Server::Server(config::Config *conf) : _conf(conf) {
|
||||
log("➕", "Server::Server", "config constructor called");
|
||||
_log = conf->getLogger();
|
||||
try {
|
||||
_setup();
|
||||
_run();
|
||||
} catch (std::exception &e) {
|
||||
_log->error(e.what());
|
||||
}
|
||||
}
|
||||
|
||||
Server::~Server(void) {
|
||||
log("➖", "Server::Server", "destructor called");
|
||||
for (std::vector<struct pollfd>::iterator it = _client_fds.begin();
|
||||
it != _client_fds.end(); it++)
|
||||
close(it->fd);
|
||||
}
|
93
src/server/ServerUtils.cpp
Normal file
93
src/server/ServerUtils.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ServerUtils.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: adjoly <adjoly@student.42angouleme.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2025/04/17 11:58:42 by adjoly #+# #+# */
|
||||
/* Updated: 2025/04/23 16:00:14 by adjoly ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include <server/Client.hpp>
|
||||
#include <netinet/in.h>
|
||||
#include <server/default.hpp>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <sys/socket.h>
|
||||
|
||||
using namespace webserv::server;
|
||||
|
||||
bool convertStringToIP(const char *ip_str, struct in_addr *addr) {
|
||||
// Split the IP string into four octets
|
||||
unsigned int a, b, c, d;
|
||||
if (sscanf(ip_str, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if each octet is within the valid range
|
||||
if (a > 255 || b > 255 || c > 255 || d > 255) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Combine the octets into a single 32-bit address
|
||||
addr->s_addr = htonl((a << 24) | (b << 16) | (c << 8) | d);
|
||||
return true;
|
||||
}
|
||||
|
||||
int Server::_createSocket(std::string host, int port) {
|
||||
int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||
if (fd == -1) {
|
||||
std::ostringstream str;
|
||||
str << port;
|
||||
throw std::runtime_error("socket binding failed for : " + host + ":" +
|
||||
str.str());
|
||||
return -1;
|
||||
}
|
||||
|
||||
int opt = 1;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||
close(fd);
|
||||
throw std::runtime_error("setsockopt failed");
|
||||
}
|
||||
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
if (!convertStringToIP(host.c_str(), &addr.sin_addr)) {
|
||||
throw std::runtime_error("ip is not of the valid format : " + host);
|
||||
}
|
||||
std::stringstream str;
|
||||
str << port;
|
||||
_log->debug("port : " + str.str());
|
||||
addr.sin_port = htons(port);
|
||||
|
||||
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
close(fd);
|
||||
std::ostringstream str;
|
||||
str << port;
|
||||
throw std::runtime_error("bind failed for : " + host + ":" + str.str());
|
||||
}
|
||||
|
||||
if (listen(fd, SOMAXCONN) < 0) {
|
||||
close(fd);
|
||||
std::ostringstream str;
|
||||
str << port;
|
||||
throw std::runtime_error("listen failed for : " + host + ":" + str.str());
|
||||
}
|
||||
|
||||
return (fd);
|
||||
}
|
||||
|
||||
bool Server::_handle_client(struct pollfd &pollfd, sockaddr_in *sock_data) {
|
||||
try {
|
||||
Client client(pollfd.fd, *sock_data, _conf);
|
||||
client.answer();
|
||||
} catch (std::runtime_error &e) {
|
||||
_log->error(e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
90
upload.html
90
upload.html
@ -1,90 +0,0 @@
|
||||
<meta charset="utf-8">
|
||||
<html>
|
||||
<head>
|
||||
<title>upload</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- j'ai pas volé le code (c'est faux) -->
|
||||
<!-- putain les pubs spotify c'est chiant -->
|
||||
<!-- je m'en fous de leur bière -->
|
||||
<form id="upload_form" enctype="multipart/form-data" method="post">
|
||||
<input type="file" name="file1" id="file1" onchange="uploadFile()"><br>
|
||||
<progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
|
||||
<h3 id="status"></h3>
|
||||
<p id="loaded_n_total"></p>
|
||||
</form>
|
||||
<button id="abort" hidden>annuler le tranfert</button>
|
||||
<script>
|
||||
function _(el) {
|
||||
return document.getElementById(el);
|
||||
}
|
||||
|
||||
function uploadFile() {
|
||||
bouton = document.getElementById("abort")
|
||||
var file = _("file1").files[0];
|
||||
|
||||
// alert(file.name+" | "+file.size+" | "+file.type);
|
||||
var formdata = new FormData();
|
||||
formdata.append("file1", file);
|
||||
var ajax = new XMLHttpRequest();
|
||||
bouton.onclick = function(){
|
||||
ajax.abort()
|
||||
}
|
||||
bouton.removeAttribute("hidden")
|
||||
ajax.upload.addEventListener("progress", progressHandler, false);
|
||||
ajax.addEventListener("load", completeHandler, false);
|
||||
ajax.addEventListener("error", errorHandler, false);
|
||||
ajax.addEventListener("abort", abortHandler, false);
|
||||
ajax.open("POST", "/upload.html");
|
||||
ajax.send(formdata);
|
||||
startmillis = Date.now()
|
||||
}
|
||||
|
||||
function copy(){
|
||||
window.getSelection().removeAllRanges()
|
||||
range = document.createRange()
|
||||
range.selectNodeContents(_("addr"))
|
||||
window.getSelection().addRange(range)
|
||||
document.execCommand('copy')
|
||||
window.getSelection().removeAllRanges()
|
||||
temp = _("addr").innerHTML
|
||||
_("addr").innerHTML = "copié !"
|
||||
setTimeout(()=>{_("addr").innerHTML = temp},500)
|
||||
}
|
||||
|
||||
function progressHandler(event) {
|
||||
// console.log(Math.round((event.loaded/1024/1024)*100)/100)
|
||||
// console.log((Date.now()-startmillis)/1000+'s')
|
||||
//console.log((event.loaded/1024/1024) /((Date.now()-startmillis)*1000)+"Mo/s")
|
||||
// console.log((event.loaded/1024/1024))
|
||||
|
||||
console.log(`${(event.loaded/1024/1024)} / ${(Date.now()-startmillis)} / 1000`)
|
||||
console.log((event.loaded/1024/1024)/((Date.now()-startmillis)/1000))
|
||||
|
||||
|
||||
|
||||
|
||||
_("loaded_n_total").innerHTML = Math.round((event.loaded/1024/1024)*100)/100 + "Mo / " + Math.round((event.total/1024/1024)*100)/100+"Mo envoyé<br/>"+Math.round((event.loaded/1024/1024)/((Date.now()-startmillis)/1000)*100)/100+"Mo/s en moyenne";
|
||||
var percent = (event.loaded / event.total) * 100;
|
||||
_("progressBar").value = Math.round(percent);
|
||||
_("status").innerHTML = Math.round(percent * 100) / 100 + "% envoyé... veuillez patienter";
|
||||
}
|
||||
|
||||
function completeHandler(event) {
|
||||
_("status").innerHTML = event.target.responseText;
|
||||
_("progressBar").value = 0; //wil clear progress bar after successful upload
|
||||
console.log("fin de l'envoi")
|
||||
_("abort").setAttribute("hidden",true)
|
||||
}
|
||||
|
||||
function errorHandler(event) {
|
||||
_("status").innerHTML = "Upload Failed";
|
||||
}
|
||||
|
||||
function abortHandler(event) {
|
||||
_("status").innerHTML = "envoi annulé";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user