Ga naar hoofdinhoud

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
  1. Regel 10-12:

    Een POST-endpoint met een formulierveld, zoals in Een formulier versturen (POST).

  2. 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())
  1. Regel 3-4:

    Drie losse verzoeken, zonder geheugen.

  2. Regel 6:

    Een Client is één bezoeker die zijn cookies onthoudt, zoals een browser. Met base_url typ 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.

Controlevraag
Een script maakt twee Clients, sara en alex. Sara vraagt twee keer /bezoek op, daarna alex één keer. Welk bezoek print alex?
Kies wat jij denkt. Bij het goede antwoord zie je de uitleg.

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.