1. Rest API's
1. Rest API's
We gaan een api uitbouwen om boeken op te halen uit bepaalde series (bijvoorbeeld The Lord of the Rings, Harry Potter, ...). Aan deze api werken we nog een paar lessen verder, bewaar je oefening dus zeker op een plaats waar je deze nog terug vindt.
API testen met Postman
Postman is software die je kan gebruiken om je api calls te testen (dit is ook hoe de calls getest worden in de videos van de theorie). Omdat je op een localhost test moet je de service ook op je PC installeren. Je kan hier Postman downloaden en er meer info over opzoeken. Je hoeft geen account aan te maken om dit te kunnen gebruiken, maar een account zorgt er wel voor dat je testen bewaard worden in de cloud.
API bouwen
Begin vanaf de startbestanden.
Startbestanden
Om je project klaar te zetten volg je dezelfde stappen als tijdens de theorie les (neem die les er zeker even bij):
- pnpm init
- package.json aanvullen
- Typescript en Express installeren in je project
- Config files van Typescript en ESLint aanmaken/aanvullen
- pnpm add -D tsx
- package.json aanvullen met scripts
Maak een map 'src' aan en hierin een bestand 'app.ts'.
Maak in 'app.ts' een nieuwe server aan (hierin staan voorlopig nog geen methodes maar breid deze zelf uit tijdens onderstaande opdrachten).
Maak een map aan voor je routes en maak hierin 1 route voor de series en 1 voor de books (om het verschil tussen 1 serie en meerdere duidelijk te maken gebruik je 'serieses', ook al klopt dat taalkundig niet). Maak je structuur correct aan zoals aangegeven in de theorie.
Maak een index.ts aan in de routes map (geef voorlopig gewoon 'Hello World' terug). Exporteer en gebruik die in app.ts.
In de dal map van de startbestanden vind je de nodige modellen en data terug om mee te werken. Voorzie zowel voor de boeken als series volgende calls:
- Alles ophalen
- 1 ophalen op id
- Verwijderen
- Toevoegen
- Updaten
Zorg ervoor dat je bij het toevoegen en updaten telkens het aangemaakte/aangepaste object teruggeeft (zoals in de theorie).
Test deze calls in Postman.
API beschermen
Zorg ervoor dat je sommige routes beschermt met CORS:
- Series mogen getoond worden (allemaal of op id), toegevoegd en aangepast maar NIET verwijderd
- Voor boeken moet je alle calls open zetten
LET OP: Je moet de CORS middleware nu toepassen op de juiste routes in plaats van in je app.ts.
Je kan dit niet volledig testen in Postman omdat Postman zich niet gedraagt zoals een standaard website met javascript code. Wat je wel kan doen is per route via Postmen een request van het type 'OPTION' doen. Als je dan de headers bekijkt van de response kan je zien of de delete methode al dan niet voorkomt in je Access-Control-Allow-Methods header. Voor http://localhost:3000/serieses mag deze er niet tussen staan, voor http://localhost:3000/books moet deze er wel tussen staan.
API loggen
Maak een nieuwe middelware functie 'apiLogger.ts' aan die voor elke call een aantal zaken gaat loggen. Voeg deze toe in de 'middleware' folder. Deze werkt gelijkaardig aan je 'cors.ts', maar deze keer gaan we logs wegschrijven in plaats van headers instellen.
Zorg ervoor dat je naar een file 'log.txt' wegschrijft.
Zorg ervoor dat je bij elke request het volgende logt:
- De huidige date en time
- De method
- De url
- De headers
- De body
Zorg voor voldoende witregels zodat je bestand proper leesbaar blijft. Kijk naar het voorbeeld van de output voor inspiratie. Zorg ervoor dat je telkens de volledige log per call in 1 keer naar je bestand schrijft zodat verschillende logs niet door elkaar komen als de calls tegelijk binnen komen.
Om data naar een bestand weg te schrijven kan je de methodes gebruiken die beschikbaar zijn via node. In de documentatie zie je verschillende manieren om data weg te schrijven. Kies de manier uit die voor jou het best lijkt (promises, callback of synchroon).
Voorbeeld van de inhoud van log.txt:
timestamp:'Wed Nov 01 2023 09:23:27 GMT+0100 (Central European Standard Time)'
method:'POST'
url:'/serieses'
headers:
{"content-type":"application/json","user-agent":"PostmanRuntime/7.33.0","accept":"*/*","cache-control":"no-cache","postman-token":"4c28e37b-36c4-4abd-875b-30adfca3acab","host":"localhost:4000","accept-encoding":"gzip, deflate, br","connection":"keep-alive","content-length":"167"}
body:
{"title":"Nieuwe serie","genre":"Fantasy","author":"Evelien","wikipediaUrl":"https://en.wikipedia.org/wiki/Test"}
timestamp:'Wed Nov 01 2023 09:23:40 GMT+0100 (Central European Standard Time)'
method:'POST'
url:'/books'
headers:
{"content-type":"application/json","user-agent":"PostmanRuntime/7.33.0","accept":"*/*","cache-control":"no-cache","postman-token":"be014252-de8f-4241-b15c-b590f0a74f79","host":"localhost:4000","accept-encoding":"gzip, deflate, br","connection":"keep-alive","content-length":"147"}
body:
{"title":"Before the Fire","seriesId":"9ee6a9cb-bb54-4903-9f12-db55ba6ae367","amazonUrl":"not just yet"}API valideren
Ja API begint al mooi vorm te krijgen, maar wat als je gebruiker een veld te weinig opgeeft? Dan krijgt deze enkel te zien dat er ongeldige input was. Wat als je gebruiker het veld wel heeft doorgegeven, maar de inhoud is niet geldig (je verwacht een getal maar de gebruiker zend een woord)? Om je api gebruiksvriendelijk te maken, moet je validatie voorzien. Je gaat dan in je call alle velden apart checken, en een object opbouwen waar alle fouten in zitten.
Bij het toevoegen en updaten van een boek of serie voorzie je de volgende validatie:
- Voor elk veld check je of het meegegeven is (enkel bij toevoegen, niet bij updaten)
- Voor elk veld check je of dit minstens 2 karakters bevat
- Voor de URL check je of deze begint met 'http'
Geef een array van objecten terug in je response. Je object heeft volgende eigenschappen:
- fieldname
- errorCode (1 voor niet meegegeven, 2 voor niet lang genoeg, 3 voor ongeldige info)
- errorMessage (zie screenshot voor inspiratie)
Zorg er ook voor dat de status code 400 nog steeds doorgegeven wordt. Codeer dit proper: maak een model aan voor je ValidationMessage, maak 1 of meer herbruikbare methodes aan om input te checken in een helper klasse,...
Een lege string mag je als 'niet lang genoeg' beschouwen.
Uiteraard moet de werking van je methodes exact hetzelfde blijven als alle validatie ok is (boek/serie teruggeven met succes status).
Bonus als je slechts 1 validatiemethode hebt die onafhankelijk van boek of serie alle velden kan checken (niet verplicht maar een leuke oefening).
Hieronder enkele voorbeelden van wat je terugkrijgt in Postman (telkens met een 400 bad request).
Bij het toevoegen zijn 2 velden niet meegeven, 1 niet lang genoeg, en de url is niet geldig:
[
{
"fieldName": "title",
"errorCode": 1,
"errorMessage": "Value was not set"
},
{
"fieldName": "author",
"errorCode": 2,
"errorMessage": "Value is not long enough"
},
{
"fieldName": "genre",
"errorCode": 1,
"errorMessage": "Value was not set"
},
{
"fieldName": "wikipediaUrl",
"errorCode": 3,
"errorMessage": "Value is not a valid URL"
}
]Bij het toevoegen is 1 veld niet meegegeven, en 1 veld is als lege string meegegeven:
[
{
"fieldName": "author",
"errorCode": 2,
"errorMessage": "Value is not long enough"
},
{
"fieldName": "genre",
"errorCode": 1,
"errorMessage": "Value was not set"
}
]Bij het updaten is 1 veld niet meegegeven, 1 veld leeg en de URL is ongeldig (merk op dat er geen fout is voor het niet-meegegeven veld!):
[
{
"fieldName": "title",
"errorCode": 2,
"errorMessage": "Value is not long enough"
},
{
"fieldName": "wikipediaUrl",
"errorCode": 3,
"errorMessage": "Value is not a valid URL"
}
]