Een bezoeker die onthoudt
Je script stuurt nu ook een formulier, en onthoudt net als een browser zijn cookies. Daarvoor krijgt de oefenserver uit Een script als bezoeker twee endpoints erbij.
Twee endpoints erbij
Vervang het main.py in je map oefenen door deze versie. Het endpoint /
blijft, en er komen een formulier en een teller bij die met een cookie telt hoe
vaak je langs bent geweest.
from fastapi import Cookie, FastAPI, Form
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/")
async def root():
return {"bericht": "Hallo wereld!"}
@app.post("/groet")
async def groet(naam: str = Form(...)):
return {"bericht": f"Hallo, {naam}"}
@app.get("/bezoek")
async def bezoek(teller: int = Cookie(default=0)):
teller = teller + 1
antwoord = JSONResponse({"bezoek": teller})
antwoord.set_cookie(key="teller", value=str(teller))
return antwoord
- Regel 10-12:
Een POST-endpoint met een formulierveld, zoals in Een formulier versturen (POST).
- Regel 14-19:
De teller staat in een cookie, zoals in Onthouden met een cookie. Elk bezoek leest hem, telt er één bij op, en zet hem terug. Een cookie is altijd tekst, daarom
str(teller).
Sla op: fastapi dev start vanzelf opnieuw.
Een formulier sturen
Maak naast main.py een script groet.py:
import httpx
antwoord = httpx.post("http://127.0.0.1:8000/groet", data={"naam": "Sara"})
print(antwoord.status_code, antwoord.json())
httpx.post met data verstuurt een formulier. De sleutels in data zijn de
names van de velden, hier naam, net als de parameter in Form. Draai het
in de tweede terminal met python groet.py:
200 {'bericht': 'Hallo, Sara'}
Een bezoeker die cookies onthoudt
Een browser onthoudt de cookies die een server terugstuurt, en stuurt ze bij
het volgende verzoek weer mee. httpx.get doet dat niet: elk verzoek is een
nieuwe bezoeker. Voor een bezoeker die onthoudt, gebruik je een Client. Maak
teller.py:
import httpx
for i in range(3):
print(httpx.get("http://127.0.0.1:8000/bezoek").json())
bezoeker = httpx.Client(base_url="http://127.0.0.1:8000")
for i in range(3):
print(bezoeker.get("/bezoek").json())
- Regel 3-4:
Drie losse verzoeken, zonder geheugen.
- Regel 6:
Een
Clientis één bezoeker die zijn cookies onthoudt, zoals een browser. Metbase_urltyp je daarna alleen nog het pad.
Draai het met python teller.py.
Met een Client per bezoeker laat een script straks Sara en Alex tegelijk
je gastenboek bezoeken.
Er gaat iets mis
De Client telt niet door
Ook de Client print drie keer {'bezoek': 1}.
Oorzaak: je maakt de Client binnen de for-lus:
# FOUT
for i in range(3):
bezoeker = httpx.Client(base_url="http://127.0.0.1:8000")
print(bezoeker.get("/bezoek").json())
# GOED
bezoeker = httpx.Client(base_url="http://127.0.0.1:8000")
for i in range(3):
print(bezoeker.get("/bezoek").json())
Elke ronde maakt dan een nieuwe bezoeker, zonder de cookie van de vorige.
Oplossing: maak de Client één keer, boven de lus, en gebruik hem in de
lus.
Method Not Allowed op /groet
Je opent http://127.0.0.1:8000/groet in je browser, en ziet
{"detail":"Method Not Allowed"}.
Oorzaak: een adres intypen is een GET, en /groet is een
POST-endpoint. FastAPI antwoordt dan met een 405.
Oplossing: stuur het formulier met groet.py. Daarin staat httpx.post.
Opdrachten
Opdracht 1: Predict - Een formulier zonder naam
Je stuurt httpx.post("http://127.0.0.1:8000/groet", data={}): een formulier
zonder het veld naam.
Vraag: welke statuscode krijg je?
Tip
Form(...) betekent dat het veld verplicht is.
Antwoord
422. FastAPI mist het verplichte veld naam, en weigert het verzoek voordat
je functie draait.
Opdracht 2: Investigate - De browser als bezoeker
Open http://127.0.0.1:8000/bezoek in je browser en druk een paar keer op F5.
Loopt de teller op, zoals bij httpx.get of zoals bij de Client?
Antwoord
Zoals bij de Client: 1, 2, 3, enzovoort. De browser bewaart de cookie
teller en stuurt hem bij elke keer herladen mee. Een Client doet in je
script precies wat de browser doet.
Zo ziet je main.py er nu uit
from fastapi import Cookie, FastAPI, Form
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/")
async def root():
return {"bericht": "Hallo wereld!"}
@app.post("/groet")
async def groet(naam: str = Form(...)):
return {"bericht": f"Hallo, {naam}"}
@app.get("/bezoek")
async def bezoek(teller: int = Cookie(default=0)):
teller = teller + 1
antwoord = JSONResponse({"bezoek": teller})
antwoord.set_cookie(key="teller", value=str(teller))
return antwoord
Deze oefenserver heb je na deze les niet meer nodig; elke reeks begint met zijn eigen server.
Door naar de eerste reeks: Wat je server laat zien.