developer.overheid.nl

Ontwikkelaarsportaal van de Nederlandse overheid

Ga naar hoofdinhoud

5. Genereer API code

Nu we een gevalideerde OpenAPI Specification hebben, kunnen we automatisch servercode genereren. We gebruiken hiervoor OpenAPI Generator, een populaire open-source tool die code kan genereren in tientallen programmeertalen en frameworks.

Voorbereiding

Zorg dat we de volgende zaken klaar hebben:

  1. Het OAS bestand - Sla de OAS uit de Swagger Editor op als openapi.json
  2. Node.js - Controleer met node --version dat Node.js 22+ geïnstalleerd is. Dit hebben we nodig voor de npx tooling en voor de NestJS-template. Download Node.js
  3. Java - OpenAPI Generator is een Java applicatie. Controleer met java --version dat Java 11+ geïnstalleerd is. Download Java
  4. Runtime voor je template - Kies je later voor een Go-, Java-, Rust- of Python-template? Zorg dan ook dat die runtime lokaal beschikbaar is. De template-repository noemt de actuele minimale versies.
npx

We gebruiken npx om tools uit te voeren zonder ze eerst globaal te installeren. Met npx worden packages automatisch gedownload en uitgevoerd. De eerste keer kan dit even duren, daarna worden ze gecached.

Bundlen

Onze OAS bevat $ref verwijzingen naar externe URL's, zoals https://static.developer.overheid.nl/adr/components.yaml voor standaard headers en error responses. Dit is handig omdat we zo herbruikbare ADR-componenten kunnen gebruiken, maar de OpenAPI Generator kan niet overweg met externe referenties.

We moeten de OAS daarom eerst bundlen. Dit betekent dat externe verwijzingen worden opgehaald en als interne $ref verwijzingen in het document worden opgenomen. Het resultaat is een zelfstandig bestand zonder externe afhankelijkheden.

Dit doen we met Redocly CLI:

npx @redocly/cli bundle ./openapi.json --output openapi.bundled.json --ext json

Dit haalt externe referenties op en zet ze om naar interne $ref verwijzingen binnen het document. Gebruik openapi.bundled.json als input voor de volgende stappen.

Valideer de gebundelde OAS ook nog een keer voordat je code genereert:

npx @developer-overheid-nl/don-checker@latest validate \
--ruleset adr-21 \
--input openapi.bundled.json
Volledig platslaan

Sommige tools ondersteunen ook interne $ref verwijzingen niet. In dat geval kunnen we de --dereferenced flag toevoegen om alles volledig plat te slaan:

npx @redocly/cli bundle ./openapi.json --output openapi.bundled.json --ext json --dereferenced

Het resultaat bevat dan geen enkele $ref meer; alle schemas zijn volledig inline geplaatst.

Code genereren

Stap 1: Clone de codegen templates

We hebben aangepaste templates gemaakt die beter aansluiten bij de ADR en de design-first workflow. Clone de template-repository naar de werkdirectory:

git clone git@github.com:developer-overheid-nl/codegen-templates.git

Stap 2: Kies een template

De repository bevat templates voor meerdere runtimes:

TemplateGeneratorRuntimeGebruik wanneer
nodejs-express-servernodejs-express-serverNode.js + ExpressJe snel een eenvoudige JavaScript serverstub of mockserver wilt.
nestjs-fastifytypescript-nestjs-serverNestJS + FastifyJe een TypeScript/NestJS basisapp met runtime-validatie, mock mode en problem-details wilt.
go-gin-templatego-gin-serverGo + GinJe een compacte Go serverstub wilt die aansluit op bestaande DON Go-apps.
java-spring-bootspringJava + Spring BootJe een Spring Boot-app met delegate interfaces, Bean Validation en problem-details wilt.
rust-axum-templaterust-axumRust + AxumJe een Rust crate met Axum-router, API traits en request-validatie wilt.
python-fastapi-templatepython-fastapiPython + FastAPIJe een FastAPI-app met Pydantic-validatie, routers per API-groep en problem-details wilt.

In deze tutorial gebruiken we nestjs-fastify. Die template genereert een TypeScript-app met NestJS, Fastify, runtime-validatie op basis van de OAS, mock mode en application/problem+json foutafhandeling. De Express-template is nog steeds handig voor een eenvoudige JavaScript serverstub. De Go-, Java-, Rust- en Python-templates zijn basisvarianten en moeten nog verder in echte API-applicaties worden beproefd.

De gegenereerde code is niet productiewaardig. Zie het als een startpunt: routes, validatie, basisfoutafhandeling en duidelijke plekken voor je eigen businesslogica zijn al ingericht, maar security, autorisatie, logging, databasetoegang, monitoring en tests moet je zelf toevoegen.

Andere generators

Op de OpenAPI Generator website vind je tientallen andere generators voor verschillende talen en frameworks. Die kun je ook gebruiken, maar dan mis je de ADR-specifieke aanpassingen uit de DON-templates.

Stap 3: Genereer de NestJS server

Voor deze tutorial genereren we een NestJS server met Fastify:

npx @openapitools/openapi-generator-cli generate \
-i ./openapi.bundled.json \
-g typescript-nestjs-server \
-o ./generated-api-nestjs \
-t ./codegen-templates/nestjs-fastify \
-c ./codegen-templates/nestjs-fastify/generator-config.yaml \
--skip-validate-spec \
--additional-properties=npmName=bier-api-nestjs,npmVersion=1.0.0,nestVersion=11.0.0,rxjsVersion=7.8.2,tsVersion=5.9.3,nodeVersion=22.0.0

Kopieer daarna dezelfde gebundelde OAS naar de runtime-locatie van de gegenereerde app:

cp ./openapi.bundled.json ./generated-api-nestjs/api/openapi.yaml

De runtime gebruikt dit bestand bij het starten. Door de gebundelde OAS te kopiëren weet de gegenereerde app exact welk contract hij moet valideren en publiceren.

ParameterBetekenis
-iInput: pad naar de OpenAPI Specification
-gGenerator: welke taal/framework (typescript-nestjs-server)
-oOutput: map waar de code gegenereerd wordt
-tTemplates: pad naar de aangepaste template
-cConfiguratiebestand van de gekozen template

Gebruik een van deze commando's als je een andere template wilt proberen:

npx @openapitools/openapi-generator-cli generate \
-i ./openapi.bundled.json \
-g nodejs-express-server \
-o ./generated-api-express \
-t ./codegen-templates/nodejs-express-server \
--additional-properties=projectName=bier-api-express

Stap 4: Bekijk de gegenereerde structuur

Na het genereren met de NestJS-template hebben we onder andere deze mapstructuur:

generated-api-nestjs/
├── api/ # OpenAPI specificatie en abstracte API classes
│ ├── BierenApi.ts
│ ├── BierstijlenApi.ts
│ ├── BrouwerijenApi.ts
│ ├── index.ts
│ └── openapi.yaml
├── app/ # NestJS module en bootstrap
│ ├── api-implementations.ts
│ ├── api.module.ts
│ └── index.ts
├── controllers/ # NestJS controllers
│ ├── BierenApi.controller.ts
│ ├── BierstijlenApi.controller.ts
│ ├── BrouwerijenApi.controller.ts
│ └── index.ts
├── decorators/ # Helpers voor headers en cookies
│ ├── cookies-decorator.ts
│ ├── headers-decorator.ts
│ └── index.ts
├── models/ # Types op basis van de schemas
│ ├── bier.ts
│ ├── bierstijl.ts
│ ├── brouwerij-adres.ts
│ ├── brouwerij.ts
│ ├── create-brouwerij-400-response-invalid-params.ts
│ ├── create-brouwerij-400-response.ts
│ └── index.ts
├── package.json
├── tsconfig.json
└── README.md
Controllers vs implementaties

De gegenereerde code scheidt routing van implementatie:

  • Controllers handelen HTTP requests af en roepen de abstracte API classes aan.
  • API classes beschrijven welke methods je moet implementeren, bijvoorbeeld listBrouwerijen, retrieveBier en createBier.
  • Implementaties koppel je later via ApiModule.forRoot.

Laat de gegenereerde controllers bij voorkeur ongemoeid. Voeg je eigen services of providers toe en registreer die als implementatie van de gegenereerde API classes.

Server starten

Voor het NestJS-voorbeeld uit deze tutorial gebruiken we npm.

Stap 1: Installeer dependencies

cd generated-api-nestjs
npm run init-install

Stap 2: Start de server met mock data

Voor deze tutorial starten we de server in mock-modus. Hiermee worden automatisch voorbeeldresponses gegenereerd op basis van de example waarden in de OAS:

PORT=8080 npm run dev-mock

De server draait nu op http://localhost:8080.

De servers URL in de OAS bevat /v1, maar de gegenereerde NestJS-routes volgen de paden uit paths. Daarom testen we lokaal met /brouwerijen en niet met /v1/brouwerijen.

Gebruik bij andere templates de startinstructies uit de gegenereerde README. In grote lijnen zijn dit de commando's:

TemplateStartenMock mode
nestjs-fastifynpm run init-install en daarna npm run devnpm run dev-mock
nodejs-express-servernpm install en daarna npm startnpm run start-mock
go-gin-templatego mod tidy en daarna go run .Niet standaard
java-spring-bootmvn spring-boot:runNiet standaard
rust-axum-templatecargo test voor checks; implementeer daarna een mainNiet standaard
python-fastapi-templatepip install -r requirements.txt en start met uvicornNiet standaard

Stap 3: Test de API

Open een nieuwe terminal en test een endpoint:

curl http://localhost:8080/brouwerijen

We krijgen nu mock data terug gebaseerd op de voorbeeldwaarden die we aan de schemas hebben toegevoegd:

[
{
"id": "046b6c7f-0b8a-43b9-b35d-6489e6daee93",
"naam": "Weizen Tripel",
"grootte": "micro",
"adres": {
"straat": "Waldeck Pyrmontsingel",
"huisnummer": 12,
"postcode": "6521 BC",
"plaats": "Nijmegen"
}
}
]

De gegenereerde server valideert ook automatisch de query parameters. Probeer de filter die we in stap 3 hebben toegevoegd:

curl http://localhost:8080/brouwerijen?grootte=micro

Dit retourneert een geldige mock response. Maar als we een typfout maken:

curl http://localhost:8080/brouwerijen?grootte=klein

Dan krijgen we een 400 Bad Request met een problem+json response:

{
"title": "Request validation failed",
"status": 400,
"errors": [
{
"in": "query",
"location": "grootte",
"code": "enum",
"detail": "must be equal to one of the allowed values"
}
]
}

De OAS fungeert dus niet alleen als documentatie, maar ook als validatielaag voor de API.

Mock vs productie

De gegenereerde NestJS-server heeft twee modi:

  • npm run dev-mock - Retourneert mock data op basis van de OAS voorbeelden. Request-validatie blijft actief.
  • npm run dev - Start de server zonder mocking. Operaties zonder eigen implementatie geven standaard 501 application/problem+json terug.

Met OPENAPI_VALIDATE_RESPONSES=true npm run dev kun je ook responses tegen de OAS laten valideren. Zet dit pas aan wanneer je eigen implementaties responses teruggeven die in het contract zijn beschreven.

Volgende stappen voor implementatie

De gegenereerde code is een werkend skelet. Om een volledige API te bouwen moeten we:

  1. Database connectie toevoegen - Bijvoorbeeld met PostgreSQL, MongoDB of SQLite
  2. API-implementaties toevoegen - Implementeer de gegenereerde API classes en koppel ze via ApiModule.forRoot
  3. Authenticatie toevoegen - Bijvoorbeeld met API keys of OAuth
  4. Error handling uitbreiden - Voeg custom error responses toe
  5. Testen schrijven - Unit tests en integration tests

Samenvatting

In deze tutorial hebben we geleerd:

  • Hoe we met de OAS Generator snel een basis OpenAPI Specification maken
  • Hoe we schemas modelleren met properties, types en referenties
  • Hoe we query parameters toevoegen voor filtering
  • Hoe we de DON Checker gebruiken om te valideren tegen de API Design Rules
  • Hoe we met OpenAPI Generator en DON-templates servercode genereren

We hebben nu alle kennis om een API te ontwerpen die voldoet aan de Nederlandse overheidsstandaarden en om die specificatie om te zetten naar werkende code.

Verder lezen