Table of Contents

Devoir 4 - Rustywebserver

Le but de ce devoir est de créer un serveur Web qui doit servir des fichiers et exécuter des scripts.

Informations générales

Date limite: Le 25 mai, 23h59
Note: 2 points de la note
Lien: Devoir 4
Télécharger en retard: 2 points / jour (maximum 4 jours)

Connaissances évaluées

Regles

  1. Le devoir doit contenir un fichier Readme.md ou vous allez expliquer votre solution (-0.1p)
  2. Un devoir qui est implémenté seulement pour passer les tests ne sera pas noté pour ces tests-la

Tricher

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.

Questions

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.

NE PUBLIEZ PAS DE CODE SOURCE. Cela est considéré comme copiage et vous aller recevoir 0p pour le devoir.

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.

Server

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é.

Messages HTTP

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:

Retour des fichiers

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.

Le serveur retournera seulement des fichiers qui se trouvent en root_folder ou ses sous-dossiers.

Demande HTTP

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.

Réponse HTTP

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:

Exécution d'un script

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.

Le résultat de l'exécution correspond à ce que le script a écrit à l'écran (indice : utilisez un pipe)

Variables

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é.

Query String

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.

Demande HTTP

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.

Réponse HTTP

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:

Le serveur doit s'assurer que les fichiers d'un répertoire autre que celui mentionné dans le ROOT_FOLDER ne peuvent pas être telecharge ou exécutés.

Log

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)

Bonus

Mettre en œuvre la liste des dossiers pour le serveur Web. Si le chemin demandé est un dossier, générez une réponse html au format suivant.

<html>
  <h1>$Request</h1>
  <ul>
    <li><a href="/..">..</a></li>
    <li><a href="/file1">file1</a></li>
    <li><a href="/file2">file2</a></li>
    ...
  </ul>
</html>