:: Enseignements :: Master :: Master TTT :: 2010-2011 :: Programmation réseau en Java ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Un aperçu du protocole HTTP |
Le protocole HTTP est un protocole applicatif client/serveur sans état permettant d'obtenir des ressources sur le World Wide Web. Nous jouons d'abord le rôle de client afin de récupérer des pages Web. Ensuite nous implantons en Java un serveur simple.
Client HTTP
Méthode GET
Nous utilisons le programme
netcat afin d'interroger des serveurs Web. La requête HTTP communiquée au serveur afin d'obtenir une ressource est de la forme suivante :
METHODE chemin_vers_la_ressource HTTP/numero_version
Champ1: Valeur1
Champ2: Valeur2
...
ligne vide
On pourra préparer préalablement les requêtes dans des fichiers fournis à netcat sur l'entrée standard (
netcat hote port < requete)
Ainsi pour obtenir la page de chemin d'URL
http://www.univ-mlv.fr/recherche/, on pourra envoyer la requête suivante sur le port 80 (il s'agit du port par défaut pour un serveur web) de la machine de nom d'hôte
www.univ-mlv.fr :
GET /recherche/ HTTP/1.1
Host: www.univ-mlv.fr
ligne vide
L'indication du champ hôte d'en-tête est obligatoire pour la version 1.1 de HTTP, un serveur pouvant gérer plusieurs hôtes à la fois (et tout spécialement un serveur proxy).
Réaliser quelques requêtes sur plusieurs sites afin d'obtenir des ressources. On pourra également utiliser un serveur proxy intermédiaire (essayer proxy.univ-mlv.fr sur le port 8080).
Méthode TRACE
L'usage de la méthode TRACE permet un renvoi par le serveur de la requête émise par le client : ceci permet de réaliser des tests. Réaliser une requête TRACE vers le serveur proxy de l'université.
Méthode HEAD et méthode GET avec en-têtes conditionnels
La méthode HEAD offre la possibilité d'obtenir uniquement l'en-tête d'une ressource et non son corps. Elle est utile si l'on souhaite vérifier certaines propriétés de la ressource (type mime, date de modification...) avant d'engager un téléchargement coûteux du corps.
On peut également adjoindre à la méthode GET des en-têtes de téléchargement conditionnel de corps. Si ces conditions ne sont pas remplies, l'effet sera identique à une méthode HEAD : on obtiendra uniquement l'en-tête de la ressource. Parmi les champs conditionnels, nous avons :
-
If-Modified-Since qui permet d'indiquer une date de modification au-delà de laquelle la ressource doit être récupérée.
-
If-None-Match qui permet de spécifier un entity tag qui, s'il ne correspond pas à la version actuelle de la ressource, entraînera la récupération complète de la ressource.
Récupérer une ressource sur un site, noter sa date de dernière modification et essayer l'en-tête If-Modified-Since avec une date antérieure et postérieure à la date de modification. Si la ressource possède un Etag, essayer également l'en-tête If-None-Match.
Connexions persistantes
La version 1.1 du protocole HTTP propose des connexions persistantes : la connexion avec le serveur n'est pas coupée systématiquement après l'envoi d'une requête. Il est possible également d'enchaîner les requêtes (pipelining) avant d'avoir obtenu une réponse du serveur. On peut forcer le serveur à couper la connexion en spécifiant l'en-tête Connection: close dans la requête.
Envoyer plusieurs requêtes vers un serveur et récupérer les données retournées. Ajouter maintenant Connection: close pour la première requête et vérifier que les requêtes suivantes ne peuvent être envoyées.
Serveur HTTP
Introduction
Nous souhaitons implanter un serveur HTTP assez simple qui nous permette de retourner des fichiers présents dans son répertoire de lancement.
Si l'on exécute le serveur depuis le répertoire /home/java/, l'envoi d'une requête GET /site/index.html HTTP/1.1\n... conduit à l'envoi par le serveur du fichier /home/java/site/index.html.
Un serveur simple
Implanter un serveur simple interprétant la première ligne de requête afin de retourner le fichier demandé. Si le fichier existe, on retourne le code 200 avec comme corps le contenu du fichier. Dans le cas contraire le code d'erreur 404 est envoyé au client. Dans un premier temps, nous indiquons au client par le champ Content-Type que le type MIME du fichier est application/octet-stream (ce qui conduit un navigateur à demander son enregistrement plutôt que son affichage direct).
Support des types MIME du contenu
Pour que le client adopte un comportement plus adapté au type de contenu, le serveur doit indiquer le type MIME réel du fichier envoyé. Deviner le format d'un fichier peut-être réalisé en utilisant certaines heuristiques tel que l'examen de ses premiers octets à la recherche de motifs spéciaux (ce que fait l'outil Unix
file). Une méthode plus simple (mais moins fiable) consiste à analyser l'extension de fichier. On essaiera ainsi de deviner le type MIME selon l'extension.
On pourra trouver sur le site de l'IANA
une liste complètes de des types MIME enregistrés (naturellement on ne cherchera qu'à supporter que quelques types parmi les plus courants : fichiers textes, HTML, PDF...).
Un peu de dynamicité
Nous souhaitons introduire un système de templates. Il s'agit de pouvoir remplacer certaines chaînes de caractères par des valeurs spécifiées par le client. Celles-ci sont communiquées par des couples
clé=valeur ajouté à la ressource demandée. Considérons comme exemple le fichier
/helloworld.txt de contenu suivant :
Hello World! Your firstname is $firstname whereas your name is $name.
La requête
GET /helloworld.txt?firstname=Java&lastname=Web retourne le résultat personnalisé suivant :
Hello World! Your firstname is Java whereas your name is Web.
Tester le serveur sur un fichier template avec des requêtes émises depuis un client netcat. Créer un formulaire HTML qui servira à émettre la requête depuis un navigateur.
Socket TLS
On souhaite maintenant modifier notre serveur pour supporter des sockets TLS. Le protocole TLS est une surcouche applicative de TCP assurant le chiffrement des échanges. L'API Java propose une classe SSLServerSocketFactory permet de créer des sockets serveurs sécurisées. Après initialisation, le fonctionnement d'une SSLServerSocket est similaire à celle d'une ServerSocket classique.
Créer un couple clé publique/clé privée pour le serveur dans un fichier
keyStore. On utilise la commande suivante (qui nous questionnera pour obtenir des éléments sur notre identité qui accompagneront notre clé publique) :
keytool -genkey -keystore keyStore -keyalg RSA
Lorsque l'on lancera le serveur, on n'oubliera pas d'indiquer le chemin vers le fichier de clés afin qu'il soit utilisé par la factory :
java -Djavax.net.ssl.keyStore=keyStore -Djavax.net.ssl.keyStorePassword=mot_de_passe ServeurHTTPSecurise
Le navigateur utilisé comme client nous signalera probablement que la clé publique (certificat) de notre serveur n'est pas signée par une autorité de confiance.
© Université de Marne-la-Vallée