Hoofdstuk 6
Doorverwijzingen
Een resource die verhuisd is
De leeslijst kan nu boeken aanmaken, vervangen en verwijderen, en elk pad dat hij beantwoordt, is een actueel pad: /books en /books/{id}. De eerste versie van deze API stond ergens anders, onder /v0/books, en sommige oude clients roepen die paden nog aan. De SERVICE_CONTRACT.md van dit hoofdstuk, die je in les 3 opent, heeft een nieuwe sectie, “Old paths”, die zegt wat de server hun verschuldigd is.
Er zijn twee makkelijke antwoorden, en beide zijn fout. De server kan /v0/books/2 beantwoorden met een 404, wat elke oude client breekt op de dag dat de paden veranderen. Of hij kan van elke route een tweede kopie onder /v0 bijhouden, wat werkt tot iemand een bug in de ene kopie oplost en niet in de andere, en de twee versies het oneens beginnen te worden.
Waar en hoe
Een doorverwijzing is een 3xx-antwoord met een header location. De twee delen beantwoorden verschillende vragen:
locationzegt waar de resource nu is, bijvoorbeeldlocation: /books/2.De status zegt hoe je erheen gaat: of de verhuizing permanent is, en of een client die hem volgt de
mag veranderen.
Vijf statussen doen dit, en twee vragen delen ze in:
POST may become GET method and body kept
permanent 301 Moved Permanently 308 Permanent Redirect
temporary 302 Found 307 Temporary Redirect
303 See Other: fetch the location with GET (or HEAD), whatever the method was
Lees het als een raster. De rijen zeggen of de verhuizing permanent is: 301 en 308 betekenen “gebruik voortaan het nieuwe adres”, 302 en 307 betekenen “gebruik het deze keer, en vraag het de volgende keer weer hier”. De kolommen zeggen wat er met de methode gebeurt. Na een 307 of 308 stuurt de client dezelfde methode met dezelfde body naar het nieuwe adres, dus een PUT blijft een PUT. Na een 301 of 302 mag een client van een POST een GET maken en de body laten vallen; elke andere methode blijft behouden. 303 staat apart: die betekent “haal nu dit andere adres op”, en RFC 9110 zegt dat dat ophalen een GET of een HEAD is. De volger die je in les 4 schrijft, stuurt GET, en les 5 laat een bibliotheek zien die een HEAD een HEAD laat blijven.
Browsers onthouden een permanente doorverwijzing en kunnen de volgende keer meteen naar het nieuwe adres gaan. Dat is een browserfunctie die je hier alleen leert herkennen; de clients in deze cursus vragen het elke keer.
Waarom vijf en niet twee
Op papier zouden er twee genoeg zijn: één permanente, één tijdelijke. HTTP/1.0 had twee doorverwijscodes, 301 en 302, en geen van beide stond een client toe de methode op eigen houtje te veranderen. Browsers deden het toch: na een POST die met 301 of 302 werd beantwoord, stuurden de meeste een GET naar het nieuwe adres en lieten ze de body vallen, en genoeg servers gingen op dat gedrag vertrouwen dat het geen vergissing meer genoemd kon worden.
Dus voegde HTTP codes toe in plaats van oude te veranderen. 303 zegt ronduit wat browsers deden: haal het resultaat op met een GET (of een HEAD). 307 en 308 zeggen het tegenovergestelde: behoud de methode en de body, wat er ook gebeurt. RFC 9110 (sectie 15.4) staat het oude gedrag voor 301 en 302 nog steeds toe, en alleen voor POST: een client mag daar van een POST een GET maken, en behoudt elke andere methode. Een server die wil dat een POST of een PUT ongewijzigd aankomt, stuurt 307 of 308, waar helemaal geen wijziging is toegestaan.
Daarom gebruikt de leeslijst 308 voor /v0/books: de verhuizing is permanent, en de PUT van een oude client moet het nieuwe pad bereiken als PUT, met zijn body.
Geen location, geen doorverwijzing
De status alleen maakt nog geen doorverwijzing. Een 3xx zonder header location geeft de client geen plek om heen te gaan, dus een client behandelt hem als het definitieve antwoord en geeft hem terug. Ook is niet elke 3xx een doorverwijzing: 304 Not Modified, die je in hoofdstuk 8 bouwt, zegt “je kopie in de cache is nog goed”, en heeft geen location.
Een doorverwijzing volgen is altijd de beslissing van de client. http.client, dat je in hoofdstuk 3 gebruikte, neemt zo’n beslissing niet: het stuurt één verzoek en geeft één antwoord terug. Gevraagd om GET /v0/books/2?x=1 op een server die dat doorverwijst, geeft het 308 Permanent Redirect terug met location: /books/2?x=1 en stopt daar. Les 4 schrijft de code die die header leest en het volgende verzoek stuurt, en les 5 vergelijkt die met een bibliotheek die doorverwijzingen voor je volgt.
/v0/books/{id} is voorgoed verhuisd, en oude clients sturen daar PUT naartoe. Welke status moet de server sturen?
Na een POST van een formulier wil de server dat de client de resultaatpagina laadt met GET. Welke status zegt dat?
Boek 7 wordt tijdens onderhoud een uur lang geleverd vanaf /books/7-old, en PUT moet blijven werken. Welke status stuurt clients daarheen?
De server zal location: /books/2 sturen, geen volledige location op ten opzichte van de URL die werd opgevraagd.