Wat een framework voor je doet
Bekijk de bytes van FastAPI
Elk antwoord dat je app tot nu toe stuurde, ging als Python-TestClient. Geen byte ervan ging over een
Een server die stopt
Elke server in deze cursus is begrensd, en deze ook. pl_http bindt een socket aan 127.0.0.1 op een make_server deed, geeft die socket aan uvicorn, en zegt uvicorn dat hij na drie verzoeken moet stoppen. Daarna stuurt het drie verzoeken met wire.fetch uit wire.py, de client uit hoofdstuk 9, en drukt het de bytes in beide richtingen af. uvicorn stopt kort na het derde antwoord vanzelf en sluit zijn luistersocket. Als de client eerder klaar was, zou pl_http uvicorn zeggen dat hij moet stoppen en er hooguit 2 seconden op wachten. Geen enkele server in deze cursus wacht tot jij hem met de hand stopt.
Draai het in het tabblad Shell:
python pl_http.py uvicorn
Met de GET /books. Net als in eerdere hoofdstukken noemt de regel Host books.test, terwijl de verbinding naar 127.0.0.1 gaat:
client -> server b'GET /books HTTP/1.1\r\nHost: books.test\r\n\r\n' (41 bytes)
server -> client b'HTTP/1.1 200 OK\r\ndate: ...\r\nserver: uvicorn\r\ncontent-length: 120\r\ncontent-type: application/json\r\n\r\n{"books":[{"id":1,"title":"Kindred","author":"Octavia E. Butler"},{"id":2,'... (246 bytes)
De regel date bevat het tijdstip van jouw run, hier getoond als .... pl_http kort een lang antwoord in, maar wire.fetch las de hele body:
body: b'{"books":[{"id":1,"title":"Kindred","author":"Octavia E. Butler"},{"id":2,"title":"Caf\xc3\xa9 Society","author":"Ana Ruiz"}]}' (120 bytes)
Er volgt geen spatie na een : of een ,. De json.dumps van je server zette na elk ervan een spatie, dus zijn body voor dezelfde twee boeken is 132 bytes.
Het tweede verzoek is HEAD /books, en de 405 uit les 2 komt over de lijn binnen:
client -> server b'HEAD /books HTTP/1.1\r\nHost: books.test\r\n\r\n' (42 bytes)
server -> client b'HTTP/1.1 405 Method Not Allowed\r\ndate: ...\r\nserver: uvicorn\r\nallow: GET\r\ncontent-length: 31\r\ncontent-type: application/json\r\n\r\n' (153 bytes)
De content-length van 31 is de grootte van de body van FastAPI voor deze fout, {"detail":"Method Not Allowed"}, en er volgt geen body: uvicorn stuurt er geen als antwoord op HEAD, de regel die je in les 4.5 met de hand schreef. Het derde verzoek vraagt om een boek dat niet bestaat:
client -> server b'GET /books/99 HTTP/1.1\r\nHost: books.test\r\n\r\n' (44 bytes)
server -> client b'HTTP/1.1 404 Not Found\r\ndate: ...\r\nserver: uvicorn\r\ncontent-length: 25\r\ncontent-type: application/json\r\n\r\n{"detail":"no such book"}' (157 bytes)
wire.fetch had voor dit alles niets nieuws nodig. Het las elke kop, vond content-length, en las precies zoveel bytes, of geen na HEAD: de framingregel uit hoofdstuk 9. Geen enkel antwoord zegt connection: close, dus onder wire.fetch sluit zijn kant zodra het de body heeft gelezen. Een client heeft alleen bytes nodig die HTTP volgen, welk programma ze ook schreef. De run eindigt zo:
--- uvicorn's log ---
(nothing)
--- result ---
uvicorn stopped on its own after 3 requests; the listening socket is closed
pl_http: every thread has stopped
Als een functie nog NotImplementedError opwerpt, krijgt het verzoek ervan HTTP/1.1 500 Internal Server Error, en het log van uvicorn noemt de error: Exception in ASGI application: NotImplementedError: not written yet: Lesson 1.
Wie welke regel schreef
Elke regel van de 404 kwam van een van drie plaatsen:
| Regel | Geschreven door |
|---|---|
de status 404 | je functie, via HTTPException |
Not Found en de rest van de statusregel | uvicorn |
date en server: uvicorn | uvicorn |
content-type: application/json en content-length: 25 | FastAPI, dat het antwoord als |
de body {"detail":"no such book"} | je functie koos de reden; FastAPI schreef de JSON |
In de 405 koos FastAPI de status en schreef het ook allow: GET; je functie draaide niet. De headernamen zijn in kleine letters omdat de interface tussen de app en de server, ASGI, ze zo doorgeeft, dus Starlette, de toolkit waarop FastAPI is gebouwd, zet content-type, content-length en allow in kleine letters, en uvicorn schrijft zijn eigen regels date en server op dezelfde manier. http.server schreef Server en Date. Namen zijn niet hoofdlettergevoelig, dus allebei kloppen ze.
Er gebeurt nog iets buiten beeld. FastAPI draait een gewone def-functie zoals get_book op een werkthread, zodat een trage functie de server niet ophoudt terwijl ze wacht. Een functie die met async def is geschreven, zou in plaats daarvan één thread veel wachttijden laten overlappen; deze cursus houdt het bij gewone def, en hoofdstuk 13 noemt async HTTP als route om te volgen.
Welke regel voegde uvicorn toe, en niet je functie of FastAPI?
Je server stuurde 132 bodybytes voor dezelfde twee boeken; deze run toont er 120. Waarom?
Waarom eindigt deze run vanzelf?
Deze run is om naar te kijken, en niets ervan wordt beoordeeld. Les 5 maakt de app af met DELETE en de query limit. Daarna haalt hoofdstuk 12 je eigen server terug en verbindt het die met een client.