Code Monkey home page Code Monkey logo

webserv's Introduction

webserv

Simple http/1.1 (bis) server implemented in c++ for 42 school cursus

clang-format / clang-tidy

  1. Install llvm
  • Debian / Ubuntu : sudo apt update && sudo apt install clang-format clang-tidy
  • Fedora / centOS : sudo dnf upgrade && sudo dnf install llvm
  1. (Optional) Usage - automatic
  1. Usage - manual
  • Format all files : find . -name "*.cpp" -o -name "*.h" -o -name "*.hpp" -o -name "*.tpp" | xargs clang-format -i
  • Static analysis : find . -name "*.cpp" -o -name "*.h" -o -name "*.hpp" -o -name "*.tpp" | xargs clang-tidy -config=.clang-tidy

webserv's People

Contributors

unkn0wn107 avatar zedium-off avatar

Watchers

 avatar

webserv's Issues

Architecture logicielle

Image

Classes Principales

1. Server

  • Description: Gère les écoutes sur les ports spécifiés et accepte les connexions entrantes.
  • Associations: Utilise ConnectionHandler pour gérer les connexions individuelles.

2. ConnectionHandler

  • Description: Traite les données reçues des clients et utilise HTTPProtocol pour analyser et répondre aux requêtes.
  • Associations: Possède un pointeur vers HTTPProtocol pour déléguer le traitement des requêtes HTTP.

3. HTTPProtocol (classe abstraite)

  • Description: Définit une interface pour le traitement des requêtes et des réponses HTTP, permettant l'implémentation de différentes versions du protocole.
  • Implémentations: HTTP1_1, HTTP2

4. HTTP1_1

  • Description: Implémentation concrète de HTTPProtocol pour HTTP/1.1.

5. HTTP2

  • Description: Implémentation concrète de HTTPProtocol pour HTTP/2 (facultatif, pour extension future).

6. ConfigLoader

  • Description: Charge et analyse le fichier de configuration du serveur.

7. FileManager

  • Description: Gère les opérations de fichier comme lire des fichiers statiques ou stocker des fichiers téléversés.

8. Logger

  • Description: Enregistre les événements et les erreurs du serveur.

Classes pour les Fonctionnalités Bonus

9. SessionManager

  • Description: Gère les sessions utilisateur, en créant et en suivant les sessions avec des identifiants uniques.

10. CookieManager

  • Description: Gère la création, la suppression, et la validation des cookies.

11. CGIHandler

  • Description: Gère l'exécution de scripts CGI pour différents types de contenu.

Interactions et Relations

  • Server utilise ConnectionHandler pour gérer chaque connexion client.
  • ConnectionHandler dépend de HTTPProtocol pour traiter les requêtes selon la version du protocole HTTP.
  • HTTPProtocol est une classe abstraite implémentée par HTTP1_1 et potentiellement HTTP2, permettant une flexibilité dans le traitement des requêtes.
  • SessionManager et CookieManager sont utilisés par ConnectionHandler pour gérer les sessions et les cookies lors du traitement des requêtes et des réponses.
  • CGIHandler est appelé par ConnectionHandler lorsqu'une requête nécessite l'exécution d'un script CGI.

Requirements checklist

Mandatory Requirements:

  • The program takes a configuration file as an argument, or uses a default path
  • The server never blocks, and the client can be bounced properly if necessary
  • The server is non-blocking and uses only 1 poll() (or equivalent) for all the I/O operations between the client and the server (listen included)
  • Poll() (or equivalent) checks read and write at the same time
  • A read or write operation is never done without going through poll() (or equivalent)
  • Checking the value of errno is strictly forbidden after a read or write operation
  • A request to the server never hangs forever
  • The server is compatible with the web browser of your choice
  • The HTTP response status codes are accurate
  • The server has default error pages if none are provided
  • Fork is only used for CGI (like PHP, Python, etc.)
  • The server is able to serve a fully static website
  • Clients are able to upload files
  • The server has at least GET, POST, and DELETE methods
  • The server is able to listen to multiple ports (see Configuration file)

Configuration File:

  • The configuration file is able to:
    • Choose the port and host of each "server"
    • Setup the server_names or not
    • The first server for a host:port is the default for this host:port
    • Setup default error pages
    • Limit client body size
    • Setup routes with one or multiple of the following rules/configuration (routes won't be using regexp):
      • Define a list of accepted HTTP methods for the route
      • Define a HTTP redirection
      • Define a directory or a file from where the file should be searched
      • Turn on or off directory listing
      • Set a default file to answer if the request is a directory
      • Execute CGI based on certain file extension (for example .php)
      • Make it work with POST and GET methods
      • Make the route able to accept uploaded files and configure where they should be saved
  • You provide some configuration files and default basic files to test and demonstrate every feature works during evaluation
  1. Bonus Part:
    • Support cookies and session management (prepare quick examples)
    • Handle multiple CGI.

Choix / Ambiguités à lever

Choix

  • Implémentation de HTTP/1.1 dernière révision RFC7230 etc.
  • Possibilité d'ajouter un protocole HTTP/2 ou HTTP/3 ensuite (bonus ++)
  • Navigateur ? (Votre serveur doit être compatible avec le navigateur web de votre choix)
  • CGI : unique (mandatory) vs multi (bonus). On laisse aussi la une modularité possible pour pouvoir ajouter ce bonus si on veut ensuite ? Qu'est ce que ça implique ?

Ambiguités

  • Votre serveur ne doit jamais bloquer et le client doit être correctement renvoyé si nécessaire. "Correctement renvoyé" pour le client ?
  • Votre serveur doit avoir des pages d’erreur par défaut si aucune n’est fournie. Quelles pages d'erreur doivent être incluses par défaut dans le serveur ?
  • Le client devrait pouvoir téléverser des fichiers. Est-ce qu'il y a des types ou taille de fichiers qui peuvent poser des soucis ? Si oui, on se limite à quoi ?
  • Stress testez votre serveur, il doit rester disponible à tout prix. Quelles limites on donne à ça ? Surcharge de requêtes par un client, par n clients etc ?
  • Votre serveur doit pouvoir écouter sur plusieurs ports. En parallèle plusieurs instances ou n'importe quel port pour 1 serveur ? Cas d'erreur utilisation du même port par 2 instances ?

Se documenter et voir ce qui se fait

La doc de base, on peut déjà se dire de prendre connaissance de ca d'ici le début de la semaine prochaine.
Sans forcement rentrer dans tous les détails mais au moins d'avoir couvert ca en diagonale.

LE Sujet

Une bonne ref (MDN) : https://developer.mozilla.org/fr/docs/Web/HTTP

La norme : HTTP/1.1bis : Résumé des RFCs en FR. Doc originale : RFC7230, RFC7231, RFC7232, RFC7233, RFC7234 et RFC7235

Un bon article avec un petit MVP implémenté en c++ : Building an http server (Article)

Parsing

Design pattern

Multithreading pour gérer plusieurs connexions simultanément ?

Je pense que le multithreading est implicitement demandé dans le sujet. Sans on ne peux pas gérer simultanément l'écoute de plusieurs ports ou même des connections simultanées.

Image

J'ai donc testé l'utilisation des threads en c98 :
Image

#include "ConfigLoader.hpp"
#include "Server.hpp"
#include <thread>


int main(int argc, char* argv[]) {
  if (argc > 2)
    ErrorHandler::fatal("Too many arguments. usage : ./webserv [config_path]");

  std::map<std::string, std::string> config;
  try {
    ConfigLoader& config = ConfigLoader::getInstance();
    if (argc == 1)
      config.loadConfig(ConfigLoader::DEFAULT_FILE_NAME);
    else if (argc == 2)
      config.loadConfig(argv[1]);
    Server* server = new Server();
    server->start();
  } catch (const std::exception& e) {
    ErrorHandler::exception(e);
    return EXIT_FAILURE;
  }

  std::thread t1(callable);
 
    // Wait for t1 to finish
    t1.join();
 
    // t1 has finished do other stuff
    Statements;
  return EXIT_SUCCESS;
}
make    
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/Server.cpp -o obj/Server.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/ConfigLoader.cpp -o obj/ConfigLoader.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/FileManager.cpp -o obj/FileManager.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/ConnectionHandler.cpp -o obj/ConnectionHandler.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/ErrorHandler.cpp -o obj/ErrorHandler.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/Logger.cpp -o obj/Logger.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/Utils.cpp -o obj/Utils.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/HTTP1_1.cpp -o obj/HTTP1_1.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/HTTPRequest.cpp -o obj/HTTPRequest.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/HTTPResponse.cpp -o obj/HTTPResponse.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/CGIHandler.cpp -o obj/CGIHandler.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/FileHandler.cpp -o obj/FileHandler.o
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3 -c src/main.cpp -o obj/main.o
.log already in .gitignore
g++ -Wall -Wextra -Werror -MMD -std=c++98 -fsanitize=address -g3  obj/Server.o  obj/ConfigLoader.o  obj/FileManager.o  obj/ConnectionHandler.o  obj/ErrorHandler.o  obj/Logger.o  obj/Utils.o  obj/HTTP1_1.o  obj/HTTPRequest.o  obj/HTTPResponse.o  obj/CGIHandler.o  obj/FileHandler.o  obj/main.o -o webserv
mkdir -p ./logs

Tout compile en C98 je suppose donc que ce n'est pas interdit, dans le sujet il y a écrit External Functions et pas Authorized.

Il faudrait donc réfléchir a une implémentation multi-threadée du programme.
Comme je vous l'ai expliqué sur discord, un port peux écouter pour plusieurs virtual server. Il faut donc lancer un thread pour chaque écoute de port. Peut être même ensuite pour chaque virtual server (pour gérer les requêtes simultanées).

Pour cela j'ai pensé a une classe PortListener qui lancera un thread pour chaque instanciations, on donnera au thread une routine pour ecouter sur le port configuré.

Il faudrait donc une classe RequestBroker qui pourrait rediriger la requête pour le server name (host) en header.

Ensuite chaque virtual server répond en fonction de sa config.

Qu'en pensez vous ? D'autres idées ?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.