|
|
@@ -1,6 +1,8 @@
|
|
|
-Revenons à notre Telnet. Tu vas émettre une requête au mini-serveur, en saisissant `GET / HTTP/1.1`, et en validant *deux fois* par entrée.
|
|
|
+##### Notre première requête !
|
|
|
|
|
|
-Tu dois voir s'afficher :
|
|
|
+Revenons à notre Telnet. Tu vas émettre une requête au mini-serveur, en saisissant `GET / HTTP/1.1`, et en validant *deux fois* par entrée : ceci équivaut à écrire une ligne vide après la rêquête, ce qui nous permet de signifier au serveur que notre requête est terminée et qu'il peut la traiter.
|
|
|
+
|
|
|
+Tu dois voir s'afficher la réponse brute du serveur :
|
|
|
```text
|
|
|
HTTP/1.0 200 OK
|
|
|
Server: BaseHTTP/0.6 Python/3.5.2
|
|
|
@@ -9,3 +11,96 @@ Content-type: text/html
|
|
|
|
|
|
Hello world!Connection closed by foreign host.
|
|
|
```
|
|
|
+
|
|
|
+Précision : la partie `Connection closed by foreign host.` à la fin ne fait pas partie de la réponse ! C'est simplement le texte affiché par Telnet quand il quitte parce que la connexion avec le serveur s'est rompue.
|
|
|
+
|
|
|
+En effet, à chaque requête, le client ouvre une nouvelle connexion vers le serveur, et celui-ci la rompt une fois qu'il a fini d'envoyer la réponse. Cela rejoint la notion de protocole sans état.
|
|
|
+
|
|
|
+Ce bout de texte se trouve sur la même ligne, tout simplement parce qu'on n'a pas mis de retour chariot dans la chaîne `"Hello world!"` envoyée par le mini-serveur.
|
|
|
+
|
|
|
+Que contient la réponse ?
|
|
|
+
|
|
|
+- Sur la première ligne : la version de HTTP utilisée par le serveur `HTTP/1.0`, suivie du *code de réponse* numérique 200, suivi de la traduction en langage intelligible par un humain de ce code : OK, tout s'est bien passé.
|
|
|
+- Sur les trois lignes suivantes : les *en-têtes de réponse* (*response headers*). Ce sont des paires clé-valeur. Le serveur nous dit qui il est, via l'en-tête `Server`, nous indique la `Date` précise à laquelle il a répondu, et nous indique quel type de contenu il a envoyé : du HTML (encore qu'ici ce soit du texte).
|
|
|
+- Puis une ligne vide, puis le *corps de la réponse* (*response body*).
|
|
|
+
|
|
|
+Remarque que :
|
|
|
+- le code 200 correspond à ce qui a été spécifié via la ligne `self.send_response(200)` dans le code du serveur.
|
|
|
+- l'en-tête `Content-type` correspond aussi à une ligne de code du serveur.
|
|
|
+- les autres en-têtes `Server` et `Date` ont été ajoutées automatiquement par le serveur.
|
|
|
+
|
|
|
+##### Une requête incorrecte !
|
|
|
+
|
|
|
+Relance `telnet 127.0.0.1 8081` puis saisis : `ABOULE / HTTP/1.1`, et valide deux fois. Voilà la réponse :
|
|
|
+```text
|
|
|
+HTTP/1.0 501 Unsupported method ('ABOULE')
|
|
|
+Server: BaseHTTP/0.6 Python/3.6.4
|
|
|
+Date: Mon, 12 Feb 2018 02:55:20 GMT
|
|
|
+Connection: close
|
|
|
+Content-Type: text/html;charset=utf-8
|
|
|
+Content-Length: 499
|
|
|
+
|
|
|
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
|
|
+ "http://www.w3.org/TR/html4/strict.dtd">
|
|
|
+<html>
|
|
|
+ <head>
|
|
|
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
|
|
+ <title>Error response</title>
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+ <h1>Error response</h1>
|
|
|
+ <p>Error code: 501</p>
|
|
|
+ <p>Message: Unsupported method ('ABOULE').</p>
|
|
|
+ <p>Error code explanation: HTTPStatus.NOT_IMPLEMENTED - Server does not support this operation.</p>
|
|
|
+ </body>
|
|
|
+</html>
|
|
|
+```
|
|
|
+
|
|
|
+Le serveur est beaucoup plus bavard ! Regarde la première ligne : tout code autre que 20x signifie une erreur. Ici c'est simplement une *méthode* HTTP qui n'existe pas. La méthode, c'est souvent un *verbe* qui indique la nature de notre requête au serveur (veut-on simplement retirer - `GET` - ou envoyer - `POST` - des données).
|
|
|
+
|
|
|
+Les *méthodes* sont standardisées, et c'est heureux, à moins de tenir spécialement à ce que le navigateur et le serveur parlent en argot (abouler viendrait de l'occitan *abolar* pour la petite histoire !).
|
|
|
+
|
|
|
+Pourquoi a-t-on plus de contenu ici, que dans la réponse à la requête correcte précédente ? Simplement parce que le serveur a des "modèles de page" tout prêts qu'il utilise dans certains cas d'erreur.
|
|
|
+
|
|
|
+Note qu'on a un nouvel en-tête, `Content-Length`, qui indique le nombre d'octets reçus, en comptant le *corps* de réponse uniquement et pas les en-têtes. Si tu copies/colles la réponse, y compris le retour chariot, dans un éditeur de texte, et que tu sauves dans un fichier, celui-ci fera la taille exacte indiquée par `Content-Length`.
|
|
|
+
|
|
|
+
|
|
|
+##### Une requête POST
|
|
|
+
|
|
|
+Utilisons maintenant une méthode standard : `POST`.
|
|
|
+
|
|
|
+Relance `telnet 127.0.0.1 8081` puis saisis :
|
|
|
+```text
|
|
|
+POST /bin/login HTTP/1.1
|
|
|
+Content-Length: 37
|
|
|
+
|
|
|
+User=Peter+Lee&pw=123456&action=login
|
|
|
+```
|
|
|
+
|
|
|
+À nouveau, valide deux fois. La réponse est presque la même qu'avant :
|
|
|
+
|
|
|
+```text
|
|
|
+HTTP/1.0 501 Unsupported method ('POST')
|
|
|
+Server: BaseHTTP/0.6 Python/3.6.4
|
|
|
+Date: Mon, 12 Feb 2018 03:20:10 GMT
|
|
|
+Connection: close
|
|
|
+Content-Type: text/html;charset=utf-8
|
|
|
+Content-Length: 497
|
|
|
+
|
|
|
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
|
|
+ "http://www.w3.org/TR/html4/strict.dtd">
|
|
|
+<html>
|
|
|
+ <head>
|
|
|
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
|
|
+ <title>Error response</title>
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+ <h1>Error response</h1>
|
|
|
+ <p>Error code: 501</p>
|
|
|
+ <p>Message: Unsupported method ('POST').</p>
|
|
|
+ <p>Error code explanation: HTTPStatus.NOT_IMPLEMENTED - Server does not support this operation.</p>
|
|
|
+ </body>
|
|
|
+</html>
|
|
|
+```
|
|
|
+
|
|
|
+Pas si étrange : `POST` est une méthode standard, mais on n'a rien dans notre *handler* pour gérer une requête `POST`. Page suivante, on va l'ajouter !
|