Le but de ce devoir est de créer un serveur Web qui doit servir des fichiers et exécuter des scripts.
Le devoir doit etre résolu individuellement. Toute tentative de tricher entraînera 0p pour ce devoir. Nous utiliserons également des systèmes de détection de trichage automatique. Si nous avons des doutes, nous vous poserons des questions supplémentaires concernant le devoir.
Si vous avez des questions concernant le devoir, posez-les en publiant un issue sur le github https://github.com/UPB-FILS-SdE2/questions avec le format [webserver] <le titre de votre question> . Vous aurez besoin d'un compte github pour publier des questions.
Si vous voulez recevoir un e-mail lorsque des problèmes sont signalés ou lorsqu'il y a de nouveaux messages, accédez au site github repository et cliquez sur Watch.
Le serveur sera sera exécuté de la maniere suivante:
rustwebserver PORT ROOT_FOLDER
Pour résoudre le devoir, vous allez implémenter un serveur HTTP, qui peut traiter les demandes via des threads. Le serveur recevra des paquets HTTP des clients, effectuera diverses opérations et répondra avec des paquets HTTP (un format simplifié).
root_folder
est un chemin absolu vers le répertoire racine, par rapport auquel toutes les requêtes seront effectuées. Par exemple, si une demande a le chemin /images/sunny.png
et que le chemin racine est /home/server/root
, le fichier avec le chemin absolu /home/server/root/images/sunny.png
sera retourné.
Les messages HTTP reçus par le serveur auront le format générique suivant:
<request_type> <path> HTTP/1.1 <header_key>:<header_value> ... <header_key>:<header_value> <message>
Les messages HTTP envoyés par le serveur auront le format générique suivant:
HTTP/1.0 <status_code status> <header_key>:<header_value> ... Connection: close <message>
Les variables suivantes seront remplacées comme suit:
La première fonctionnalité du serveur est de renvoyer les fichiers demandés par les clients. Dans ce cas, le serveur recevra une demande GET vers un fichier et répondra avec le contenu du fichier.
root_folder
ou ses sous-dossiers.
Dans ce cas, la demande recue par le serveur aura le format suivant:
GET <file_path_relative_to_root> HTTP/1.1 Host: localhost:8000 <other header lines>
La première ligne de l'application spécifie le chemin d'accès au fichier demandé. L'en-tête peut contenir d'autres lignes en plus de celles spécifiées ci-dessus.
Pour répondre aux demandes de fichiers, le serveur renverra un message similaire a:
HTTP/1.1 <status_code status> Content-type: <file_type> Connection: close <file_contents>
Selon la demande reçue et l'état du fichier demandé, l'état de la réponse peut être:
La troisième ligne de l'application spécifie le type de fichier renvoyé. Selon le type de fichier, file_type
peut avoir les valeurs suivantes:
Certains des messages reçus des clients nécessiteront l'exécution de scripts. Ce type de demande est identifié par le chemin du fichier, et dans ce cas le chemin est un fichier du répertoire /scripts.
Tous les fichiers exécutables peuvent exister dans le répertoire /scripts. N'importe lequel de ces fichiers sera exécuté avec la commande ./script_name
. Après l'exécution, le serveur répondra avec le résultat de l'exécution.
Lorsque le script est exécuté, tous les en-têtes HTTP reçus du client sont envoyés en tant que variables d'environnement au script (astuce : utilisez execve).
Le script recevra deux variables d'environnement supplémentaires : Method et Path. Method a la valeur GET ou POST et Path a la valeur du chemin demandé.
Le moment de lire sur la définition de la query string.
Chaque variable de query string doit être envoyée au script en tant que variable d'environnement au format Query_title=value.
Dans ce cas, la demande recue par le serveur ressemblera a:
<request_type> <file_path_relative_to_root> HTTP/1.1 Host: localhost:8000 <other header lines> <message - optional>
Dans ce cas, les requêtes (request_type
) peuvent être de deux types: GET
et POST
.
Pour ces demandes, les lignes de l'en-tête, à l'exception des deux premières, sont transmises en tant que variables d'environnement pour le fichier à exécuter.
Si la demande est POST, il y aura également un corps de message. Ceci est transmis en entrée au script à exécuter.
Dans ce cas, le serveur renverra un message sous la forme:
HTTP/1.1 <status_code status> Connection: close <other_headers> <file_contents>
Le statut dans la réponse aura l'une des valeurs suivantes:
Au démarrage, le serveur imprimera ce qui suit:
Root folder: <ansolute path to root folder> Server listening on 0.0.0.0:PORT
Pour chaque requête, le serveur imprimera une ligne:
$Request request_source_ip_address $Path -> status_code (status_text)