:: Enseignements :: Master :: M1 :: 2015-2016 :: Programmation d'applications réseaux ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) |
Client HTTP
|
Exercice 1 - Client HTTP
Le but de cet exercice est de commencer la réalisation d'un petit client
HTTP. Notre client permettra de faire des requêtes GET et d'en afficher
le corps de la réponse si c'est du HTML décodé dans le Charset spécifié dans l'entête.
Une requête
GET en HTTP 1.1 est de la forme:
GET / HTTP/1.1
Host: www.w3.org
Chaque ligne est encodée en ASCII et se termine par CRLF (Carriage Return,
Line Feed; "\r\n" en java). La requête se termine par une ligne vide.
La requête ci-dessus est faite au serveur
www.w3.org sur le port 80
et demande la ressource racine
/ qui est en général la page d'accueil du site.
La réponse du serveur est quelque chose du genre:
HTTP/1.1 200 OK
Date: Thu, 05 Mar 2015 20:03:16 GMT
Server: Apache/2
Content-Location: Home.html
Vary: negotiate,accept
TCN: choice
Last-Modified: Thu, 05 Mar 2015 14:35:13 GMT
ETag: "96fb-5108b79c4ea40;89-3f26bd17a2f00"
Accept-Ranges: bytes
Content-Length: 38651
Cache-Control: max-age=600
Expires: Thu, 05 Mar 2015 20:13:16 GMT
P3P: policyref="http://www.w3.org/2014/08/p3p.xml"
Content-Type: text/html; charset=utf-8
...
Chaque ligne de l'entête est encodée en ASCII et est terminée par CRLF.
L'entête se termine par une ligne vide. La première ligne:
HTTP/1.1 200 OK
donne la version du protocole utilisée pour la réponse (ici
HTTP/1.1),
le code de la réponse (
200) et un message décrivant le code de retour (
OK).
Les lignes suivantes de l'entête sont de la forme:
clé: valeur
Parmi les informations pertinentes,
Content-Length indique que le contenu
(c'est à dire le "corps" de la réponse, qui débute après l'en-tête qui se termine
par une line vide) fait 38651 octets. Cette information est
nécessaire car en HTTP/1.1 le serveur ne ferme pas la connection après avoir répondu.
Le champ
Content-Type indique que la ressource est du HTML et est encodée en UTF-8.
Il existe un autre mode de transfert appelé
chunked. Ce mode est signalé par
le champ suivant:
Transfer-Encoding: chunked
Le principe est décrit
ici.
Pour l'instant, il n'est pas nécessaire de regarder ce mode de fonctionnement.
Le traitement de la réponse se fera au moyen d'une classe HTTPReader
que vous allez implémenter. Un objet de cette classe contient deux champs : la
SocketChannel sur laquelle la réponse est lue et son buffer de lecture.
Toutes les méthodes de la classe doivent respecter le comportement suivant:
- Le buffer de lecture est en mode écriture avant et après l'appel à la méthode
(son contenu n'est pas "prêt" à être lu, mais prêt à être complété s'il reste de la place).
- Aucune lecture sur la socket ne peut être effectuée tant que le buffer de lecture
contient des éléments (on doit donc "consommer" tout le contenu du buffer avant de lire
à nouveau des données).
- Récupérez les fichiers HTTPReader.java
et HTTPException.java qui vous serviront
de base.
- Ecrivez la méthode readLineCRLF. Vous pouvez dans un premier temps la tester
avec l'exemple du main. Ensuite vous vérifirez que votre fonction passe les tests JUnit du
fichier HTTPReaderTest.java (il vous
faudra aussi le fichier FakeHTTPServer.java).
- Ecrivez la méthode readHeader. Vous devez renvoyer un objet de la classe
HTTPHeader. Pour créer l'objet, vous utiliserez
la factory create qui prend en paramètre:
- une String contenant la première ligne de la réponse,
- une map associant à chaque champ sa valeur.
Attention, le header
peut contenir plusieurs fois le même champs.
Par exemple,
Set-cookie: x-wl-uid=1smBggFQdYEUGLgg29x3Qr/zAwfq42jdGu0mYszL1+mrt/ABZ8xw43Ise90maJaHGuGvUKVQ+0gM=; path=/; domain=.amazon.fr; expires=Mon, 31-Dec-2035 23:00:01 GMT
Set-cookie: session-id-time=2082754801l; path=/; domain=.amazon.fr; expires=Mon, 31-Dec-2035 23:00:01 GMT
Set-cookie: session-id=276-2784413-9232431; path=/; domain=.amazon.fr; expires=Mon, 31-Dec-2035 23:00:01 GMT
C'est équivalent à ne mettre qu'un seul champ Set-Cokie avec la concatenation
des 3 chaînes séparées par des point-virgules.
- Compléter la méthode readBytes.
- Ecrivez un client HTTPClient qui prend en argument l'adresse
d'un serveur et une ressource. Le client demande la ressource au serveur sur
son port 80, il affiche la ressource si c'est du HTML.
Pour l'instant, vous ne traiterez que le cas où la réponse contient un champ
Content-Length.
- Faire en sorte de pouvoir traiter les réponses dans le mode de transfert
chunked. Pour cela implémentez, la methode readChunks dans la classe
HTTPReader.
- Modifiez votre client pour prendre en compte les codes de réponse 301
et 302.
© Université de Marne-la-Vallée