HTTP is tekst op een socket · oefening
Als er geen body is
fetch leest nu precies de body die een antwoord aankondigt. Verstuur, voordat je iets verandert, het andere verzoek uit les 3 ermee, HEAD in plaats van GET, vanuit het tabblad Shell:
python wire.py HEAD
Je zou moeten zien dat het ongeveer twee seconden wacht en stopt met TimeoutError: het antwoord kondigde de lengte aan die GET zou sturen, en er volgt geen body op een verbinding die openblijft. Mislukt het in plaats daarvan meteen met ConnectionError, dan sloot de dienst de verbinding; hoe dan ook wachtte je reader op een body die HEAD nooit stuurt.
In les 3, toen fetch alleen de kop teruggaf, drukte hetzelfde commando de kop meteen af. Die kop bevat dezelfde GET, inclusief Content-Length: 182, de grootte van de pagina die je in les 2 decodeerde. Je read_body vertrouwde dat getal en vroeg om 182 bytes die nooit zouden komen.
Waar HEAD voor dient
HEAD vraagt om precies wat GET zou teruggeven, min de body. De server stuurt dezelfde statusregel en in de regel dezelfde headers, en stopt na de lege regel. Een client gebruikt het om iets over een resource te weten te komen zonder hem over te dragen: of hij bestaat, hoe groot hij is, welk type hij heeft. In een antwoord op HEAD beschrijft Content-Length dus de body die een GET zou ontvangen. Het zegt niets over dit antwoord, dat helemaal geen body heeft.
Daardoor hoort de read_body krijgt hem al binnen als zijn method, die les 5 ongebruikt liet. De regel is één controle, als eerste geplaatst: als de methode "HEAD" is, geef dan b"" terug voordat je naar een header kijkt. Dat hij als eerste staat, doet ertoe. Een antwoord op HEAD kan Content-Length ook helemaal weglaten, en dat is geen reden om het te weigeren: met de controle vooraan wordt de lengte nooit geraadpleegd.
HEAD is niet het enige geval van een antwoord zonder body. Een antwoord 204 No Content en een antwoord 304 Not Modified hebben er ook nooit een; beide komen in latere hoofdstukken aan bod, als je eigen server ze stuurt.
Een antwoord op een HEAD-verzoek zegt Content-Length: 412. Wat moet read_body teruggeven?
Je opdracht
Voeg in wire.py de regel toe aan het begin van read_body: als method "HEAD" is, geef dan b"" terug zonder iets te lezen en zonder een header te controleren. Laat de rest van read_body zoals het is, zodat antwoorden op GET precies als eerst worden gelezen. fetch geeft zijn method al door aan read_body.
Verstuur daarna beide verzoeken opnieuw:
python wire.py HEAD
python wire.py
Het HEAD-verzoek drukt nu meteen af: de status, de headers met content-length nog steeds ['182'], en 'body': b''. Het GET-verzoek drukt dezelfde headers af en de hele pagina als body.
Druk daarna op Check my work. Les 7 brengt de vier onderdelen van fetch samen en bewijst ze met je eigen tests.
Opdracht
Voeg één regel toe aan het begin van read_body in wire.py: als method "HEAD" is, geef dan meteen b"" terug, voordat je naar een header kijkt en zonder iets te ontvangen. Laat de rest van read_body zoals het is, zodat een antwoord op GET nog steeds precies volgens zijn Content-Length wordt gelezen.
Voer in de python wire.py HEAD uit en daarna python wire.py.
Druk daarna op Check my work. De controle roept fetch aan met een vervangende connect voor HEAD-verzoeken met antwoorden die je niet hebt gezien: een kop die een lengte aankondigt en waarop stilte volgt op een verbinding die openblijft, in zijn geheel geleverd, één byte tegelijk en op elke positie in tweeën geknipt (ook binnen de lege regel), met de lengteheader in een ongebruikelijke schrijfwijze; en een kop helemaal zonder Content-Length. Ze controleert dat de body b"" is en dat er na de kop niets is ontvangen. Ze roept fetch ook aan voor GET, om te controleren dat een GET-body nog steeds wordt gelezen, en roept read_body rechtstreeks aan met "HEAD". Ze leest je terminal niet en neemt geen contact op met practice-api.