HTTP ist Text auf einem Socket · Übung
Wenn es keinen Body gibt
fetch liest jetzt genau den Body, den eine Antwort ankündigt. Bevor du etwas änderst, sende damit die andere Anfrage aus Lektion 3, HEAD statt GET, im Tab Shell:
python wire.py HEAD
Du solltest sehen, dass sie etwa zwei Sekunden wartet und mit TimeoutError anhält: Die Antwort hat die Länge angekündigt, die GET senden würde, und auf einer Verbindung, die offen bleibt, folgt kein Body. Wenn sie stattdessen sofort mit ConnectionError fehlschlägt, hat der Dienst die Verbindung geschlossen; so oder so hat dein Reader auf einen Body gewartet, den HEAD nie sendet.
In Lektion 3, als fetch nur den Kopf zurückgab, hat derselbe Befehl den Kopf sofort ausgegeben. Dieser Kopf enthält dieselben GET, einschließlich Content-Length: 182, der Größe der Seite, die du in Lektion 2 dekodiert hast. Dein read_body hat dieser Zahl vertraut und nach 182 Bytes gefragt, die nie kommen würden.
Wofür HEAD da ist
HEAD fragt nach genau dem, was GET zurückgeben würde, nur ohne den Body. Der Server sendet dieselbe Statuszeile und in der Regel dieselben Header und hört nach der Leerzeile auf. Ein Client benutzt das, um etwas über eine Ressource zu erfahren, ohne sie zu übertragen: ob sie existiert, wie groß sie ist, welchen HEAD beschreibt Content-Length also den Body, den ein GET bekommen würde. Über diese Antwort, die gar keinen Body hat, sagt es nichts.
Damit wird die read_body bekommt sie schon als seinen method, den Lektion 5 unbenutzt gelassen hat. Die Regel ist eine einzige Prüfung, die zuerst kommt: Wenn die Methode "HEAD" ist, gib b"" zurück, bevor du dir irgendeinen Header ansiehst. Dass sie zuerst kommt, ist wichtig. Eine Antwort auf HEAD darf Content-Length auch ganz weglassen, und das ist kein Grund, sie abzulehnen: Mit der Prüfung am Anfang wird die Länge nie herangezogen.
HEAD ist nicht der einzige Fall einer Antwort ohne Body. Eine Antwort 204 No Content und eine Antwort 304 Not Modified haben ebenfalls nie einen; beide kommen in späteren Kapiteln vor, wenn dein eigener Server sie sendet.
Eine Antwort auf eine Anfrage HEAD sagt Content-Length: 412. Was sollte read_body zurückgeben?
Deine Aufgabe
Füge in wire.py die Regel am Anfang von read_body hinzu: Wenn method gleich "HEAD" ist, gib b"" zurück, ohne etwas zu lesen und ohne irgendeinen Header zu prüfen. Lass den Rest von read_body so, wie er ist, damit Antworten auf GET genau wie vorher gelesen werden. fetch übergibt seine method schon an read_body.
Sende dann beide Anfragen erneut:
python wire.py HEAD
python wire.py
Die Anfrage HEAD gibt jetzt sofort etwas aus: den Status, die Header mit content-length weiterhin ['182'] und 'body': b''. Die Anfrage GET gibt dieselben Header aus und die ganze Seite als ihren Body.
Drücke dann Check my work. Lektion 7 sammelt die vier Teile von fetch und prüft sie mit deinen eigenen Tests.
Aufgabe
Füge am Anfang von read_body in wire.py eine Regel hinzu: Wenn method gleich "HEAD" ist, gib sofort b"" zurück, bevor du dir irgendeinen Header ansiehst und ohne etwas zu empfangen. Lass den Rest von read_body so, wie er ist, damit eine Antwort auf GET weiterhin genau nach ihrem Content-Length gelesen wird.
Führe im python wire.py HEAD und dann python wire.py aus.
Drücke dann Check my work. Die Prüfung ruft fetch mit einem Ersatz für connect für Anfragen HEAD auf, deren Antworten du nicht gesehen hast: einen Kopf, der eine Länge ankündigt und auf den Stille auf einer offen bleibenden Verbindung folgt, geliefert am Stück, ein Byte nach dem anderen und an jeder Position in zwei Teile geschnitten (auch innerhalb der Leerzeile), mit dem Längen-Header in ungewöhnlicher Schreibweise; und einen Kopf ganz ohne Content-Length. Sie prüft, dass der Body b"" ist und dass nach dem Kopf nichts empfangen wurde. Sie ruft außerdem fetch für GET auf, um zu prüfen, dass ein Body bei GET weiterhin gelesen wird, und ruft read_body direkt mit "HEAD" auf. Sie liest dein Terminal nicht und nimmt keinen Kontakt mit practice-api auf.