Ga naar hoofdinhoud

Invoer controleren: maxlength is geen controle

In een formulier kun je met maxlength een grens zetten op een veld. De browser laat je dan niet verder typen. Maar die grens is een hulp voor wie zich vergist, geen controle. Met een script zie je waarom, en hoe ver het gaat. Deed je de uitbreiding JavaScript al, dan ken je het idee uit Server of browser?; deze les kun je ook zonder die uitbreiding volgen.

Doe het na, op je eigen server​

Start je server uit les 1, en open het formulier uit de map static: http://127.0.0.1:8000/static/formulier.html. Typ een lang bericht in het vak bericht: na 280 tekens gaat er niets meer bij, want maxlength houdt je tegen.

Nu een scriptje groot.py, naast main.py, dat níét via het formulier gaat, maar rechtstreeks naar het endpoint:

import httpx

adres = "http://127.0.0.1:8000/bericht"

bericht = "a" * 1_000_000
antwoord = httpx.post(adres, data={"naam": "Sara", "bericht": bericht})
print(antwoord.json())
  1. Regel 5:

    Een bericht van een miljoen keer de letter a. In het formulier kreeg je dit er nooit in. 1_000_000 is hetzelfde getal als 1000000; het liggende streepje maakt het leesbaar.

  2. Regel 6:

    Hetzelfde verzoek dat de browser zou sturen, maar zonder de grens uit de HTML.

Draai het met python groot.py, en daarna lees_database.py uit les 1.

Alle miljoen tekens staan in je database. maxlength zat in de HTML, en die HTML draaide in de browser die je nu hebt overgeslagen. Het endpoint zag alleen het verzoek, en dat had geen grens.

Eén bericht van een miljoen tekens is al vervelend, en een script dat dat duizend keer doet, vult je schijf.

Eén ruwe grens​

Helemaal zonder grens is je server niet. Maak naast groot.py een tweede script, te_groot.py, met tien miljoen tekens en onderaan ook de statuscode. groot.py zelf laat je zoals hij is: die heb je in de opdrachten en in les 3 nog nodig.

import httpx

adres = "http://127.0.0.1:8000/bericht"

bericht = "a" * 10_000_000
antwoord = httpx.post(adres, data={"naam": "Sara", "bericht": bericht})
print(antwoord.json())
print(antwoord.status_code)

Uitvoer:

{'detail': 'Field exceeded maximum size of 1024KB.'}
400

Starlette, het deel van FastAPI dat formulieren leest, weigert zelf een veld dat groter is dan een megabyte, ongeveer een miljoen tekens. Het bericht van precies een miljoen kwam er nog net door. Die grens beschermt je tegen het ergste, maar een bericht in een gastenboek hoort geen megabyte te zijn. De echte grens zet je zelf, in les 3.

Controlevraag
Het formulier stopt na 280 tekens. Waarom houdt maxlength groot.py niet tegen?
Kies wat jij denkt. Bij het goede antwoord zie je de uitleg.

Er gaat iets mis​

Field required in plaats van de lengte​

groot.py print geen lengte, maar een melding zoals deze:

{'detail': [{'type': 'missing', 'loc': ['body', 'bericht'], 'msg': 'Field required', 'input': None}]}

Oorzaak: je stuurt geen naam of bericht mee, of de namen in data komen niet overeen met de Form-parameters, zoals berichten in plaats van bericht. FastAPI mist dan een verplicht veld en antwoordt met een 422.

Oplossing: stuur beide velden mee, met precies de namen naam en bericht, net als het formulier.

Wat er in zo'n 422 staat, lees je in les 4. Alle statuscodes van deze route staan op de startpagina.

Opdrachten​

Opdracht 1: Predict - 300 tekens​

In het formulier kom je niet verder dan 280 tekens. Je stuurt met een script een bericht van 300 tekens.

Vraag: wat antwoordt de server?

Antwoord

{'lengte': 300}. De server kent de grens van 280 niet: die staat alleen in de HTML.

Opdracht 2: Investigate - Vijf keer​

Draai groot.py, met het bericht van 1_000_000 tekens, vijf keer achter elkaar, en daarna lees_database.py. Veranderde je groot.py voor opdracht 1, zet het bericht dan eerst terug op 1_000_000. Hoeveel tekens staan er nu in je database?

Tip

Tel ook het bericht mee dat er al stond.

Antwoord

Onder je berichten uit het formulier staan zes regels [Sara] 1000000 tekens: het bericht van daarnet en de vijf nieuwe. Stuurde je in opdracht 1 echt 300 tekens, dan staat daartussen ook [Sara] 300 tekens. Het bericht van te_groot.py staat er niet bij: dat weigerde de server. Samen zes miljoen tekens, en het bestand gastenboek.db is ongeveer zes megabyte. Elke keer dat het script draait, groeit het. Een script dat niet stopt, maakt je schijf vol.

Door naar les 3: grenzen in Form.