|
| 1 | +--- |
| 2 | +draft: true |
| 3 | +authors: [dimitri-van-hees] |
| 4 | +--- |
| 5 | +import { Blockquote } from "@rijkshuisstijl-community/components-react"; |
| 6 | + |
| 7 | +# Een lange weg, maar hij komt eraan: OpenAPI 3.1! |
| 8 | + |
| 9 | +Ruim zeven jaar geleden werd het traject afgerond om de OpenAPI Specification (OAS) op de pas-toe-leg-uit lijst van het Forum Standaardisatie te krijgen. Hiermee werden overheden verplicht om, als er REST API's gepubliceerd worden, deze te voorzien van een OAS document. De versie werd vastgesteld op 3.0 en is sindsdien niet gewijzigd, terwijl de opvolger (3.1) al enige tijd uit is en enkele belangrijke features bevat om Developer Experience aanzienlijk te verhogen. Waar staan we in de upgrade van OpenAPI 3.0 naar OpenAPI 3.1? |
| 10 | + |
| 11 | + |
| 12 | +*Ondergetekende met het bewijs dat OpenAPI verplicht werd gesteld voor REST API's van de overheid, ruim zeven jaar geleden.* |
| 13 | + |
| 14 | +<!-- truncate --> |
| 15 | + |
| 16 | +## OpenAPI Specification |
| 17 | + |
| 18 | +OAS is ontstaan uit een samenwerking tussen verschillende API Description Frameworks, zoals Swagger, RAML en API Blueprint, met als doel één standaard te creëren voor het machine-leesbaar beschrijven van REST API's. De eerste versie van OAS werd 3.0 genoemd, omdat het grotendeels voortbouwde op Swagger 2.x. In juni 2018 werd OpenAPI Specification 3.0 verplicht gesteld via de pas-toe-leg-uit lijst. In 2021 verscheen versie 3.1, die volgens het *semver*-principe een minor update zou moeten zijn, maar toch enkele breaking changes bevatte. Door beperkte ondersteuning in tooling besloot de expertgroep van het Forum Standaardisatie op 7 december 2022 de upgrade naar 3.1 tijdelijk te pauzeren. Inmiddels zijn we ruim twee jaar verder en is de situatie veranderd. Daarom is afgelopen week besloten de procedure te hervatten, zodat versie 3.1 hopelijk binnenkort gebruikt kan worden voor overheids-API's. |
| 19 | + |
| 20 | +:::note[Semver] |
| 21 | +Semver staat voor *Semantic Versioning*, een manier om versienummers van software op een gestructureerde manier op te bouwen. Het bestaat uit drie delen: `major.minor.patch`. Een verhoging van het eerste cijfer (`major`) betekent dat er mogelijk breaking changes zijn. Het tweede cijfer (`minor`) wordt verhoogd bij het toevoegen van nieuwe, compatibele functionaliteit. Het derde deel (`patch`) geeft kleine, backwards-compatibele bugfixes aan. Zo kun je aan het versienummer direct zien wat voor soort wijzigingen je kunt verwachten. |
| 22 | +::: |
| 23 | + |
| 24 | +## De wijzigingen in het kort |
| 25 | + |
| 26 | +Voordat we dieper ingaan op de details, volgt hier alvast een overzicht van de belangrijkste nieuwe features in OpenAPI 3.1: |
| 27 | + |
| 28 | +- **HTTP API's in plaats van REST API's**: verbreding van het toepassingsgebied van OAS |
| 29 | +- **Webhooks**: maakt het beschrijven van asynchrone requests mogelijk |
| 30 | +- **Meerdere voorbeelden**: responses kunnen nu meerdere voorbeelden bevatten via een `examples` array |
| 31 | +- **Mutual TLS support**: ondersteuning voor beveiliging met Mutual TLS |
| 32 | +- **Volledig JSON Schema compatible**: volledige compatibiliteit met de officiële JSON Schema standaard |
| 33 | + |
| 34 | +Hieronder lichten we deze wijzigingen verder toe. |
| 35 | + |
| 36 | +## Van REST API's naar HTTP API's |
| 37 | + |
| 38 | +De termen REST, RESTful en REST-ish worden vaak door elkaar gebruikt, maar wat betekenen ze nu eigenlijk? Volgens de oorspronkelijke principes van Roy Fielding — de bedenker van **RE**presentational **S**tate **T**ransfer — moet een API strikt aan een aantal architectuureisen voldoen om écht REST te zijn. In de praktijk zijn er echter veel varianten. Zo is OData een goed voorbeeld van een *REST-ish* API: het is resource-gebaseerd en stateless, maar introduceert een eigen querytaal met parameters als `$filter` en `$expand`. Volg je de API Design Rules, dan is je API waarschijnlijk *RESTful*, omdat operaties zoals `/v1/gebouwen/_zoek` formeel geen REST zijn, ook al lijken ze er sterk op. Zelfs RPC-achtige patronen, zoals `POST /doeIets`, zijn te beschrijven in OAS. |
| 39 | + |
| 40 | +<Blockquote |
| 41 | + attribution=" — OpenAPI 3.1 Specification" |
| 42 | + variation="pink-background" |
| 43 | +> |
| 44 | +"The OpenAPI Specification (OAS) defines a standard, programming language-agnostic interface description for HTTP APIs." |
| 45 | +</Blockquote> |
| 46 | + |
| 47 | +<br/> |
| 48 | + |
| 49 | +Met de komst van OpenAPI 3.1 is het bovendien mogelijk om webhooks (HTTP callbacks) te beschrijven, waardoor het toepassingsgebied van OAS verder wordt verbreed. Daarom wordt er vanaf OAS 3.1 over **HTTP API's** gesproken in plaats van REST API's. GraphQL valt hier overigens buiten: hoewel het HTTP als transport gebruikt, volgt het niet het HTTP-model waarop OAS is gebaseerd. OpenAPI is bedoeld voor API's die zich gedragen volgens de principes van HTTP, niet alleen het protocol gebruiken. |
| 50 | + |
| 51 | +## Webhooks |
| 52 | + |
| 53 | +OpenAPI 3.1 introduceert het nieuwe element `webhooks`, waarmee je asynchrone HTTP callbacks kunt beschrijven die door de server worden getriggerd, bijvoorbeeld na een API-call. Hierdoor is het veld `paths` niet langer verplicht; je kunt nu ook alleen webhooks documenteren als je dat wilt. Een voorbeeldscenario is dat een client een afbeelding uploadt (1), de API direct (synchroon) met een `202 Accepted` bevestigt dat de afbeelding is ontvangen (2), vervolgens de afbeelding verwerkt (3) en na afronding (asynchroon) een callback naar de client stuurt (4). Afhankelijk van de *retry policy* is het over het algemeen gebruikelijk om een ontvangen callback netjes te beantwoorden met een relevante status code (5): |
| 54 | + |
| 55 | +```mermaid |
| 56 | +sequenceDiagram |
| 57 | + autonumber |
| 58 | + Client->>API: POST /afbeeldingen image.png |
| 59 | + API->>Client: 202 Accepted |
| 60 | + API->>API: process image.png |
| 61 | + API->>Client: POST /callback-url processed_image.png |
| 62 | + Client->>API: 200 OK |
| 63 | +``` |
| 64 | + |
| 65 | +De payload van deze callback wordt in OAS 3.1 beschreven met het `webhooks` element. In dit voorbeeld wordt het verwerkte bestand direct meegestuurd in de callback: |
| 66 | + |
| 67 | +```yaml |
| 68 | +webhooks: |
| 69 | + imageProcessed: |
| 70 | + post: |
| 71 | + requestBody: |
| 72 | + required: true |
| 73 | + content: |
| 74 | + image/png: # een schema is niet nodig voor dit content-type |
| 75 | +``` |
| 76 | +
|
| 77 | +## Mutual TLS |
| 78 | +
|
| 79 | +OAS 3.0 ondersteunt de beschrijving van de volgende security schemes: |
| 80 | +
|
| 81 | +- HTTP Authentication |
| 82 | +- API Keys |
| 83 | +- OAuth 2.0 |
| 84 | +- OpenID Connect |
| 85 | +
|
| 86 | +Een grote speler die ontbreekt is Mutual TLS. OAS 3.1 ondersteunt Mutual TLS wél, waardoor ook HTTP API's van de overheid die op deze manier beveiligd zijn, dit in OAS 3.1 kunnen uitdrukken: |
| 87 | +
|
| 88 | +```yaml |
| 89 | +security: |
| 90 | + type: mTLS |
| 91 | +``` |
| 92 | +
|
| 93 | +## Meerdere examples |
| 94 | +
|
| 95 | +Waar OAS 3.0 nog één `example` bij request en response velden accepteerde, ondersteunt OAS 3.1 meerdere `examples` in de vorm van een array. `example` wordt nog wel ondersteund, maar is *deprecated*. Dat betekent dat de ondersteuning hiervoor in een volgende versie zal verdwijnen. |
| 96 | + |
| 97 | +Met meerdere examples wordt het voor tooling, zoals bijvoorbeeld mocking services, makkelijker om realistische testdata te kunnen genereren. Voorbeeld: |
| 98 | + |
| 99 | +```yaml |
| 100 | +voornaam: |
| 101 | + type: string |
| 102 | + examples: [Dimitri, Frank, Jaap-Hein, Joost, Martin, Matthijs, Tom, Vivian] |
| 103 | +``` |
| 104 | + |
| 105 | +## JSON Schema |
| 106 | + |
| 107 | +Tijdens de totstandkoming van OAS 3.0 werd er nog volop gewerkt aan de JSON Schema standaard. Dat betekent dat de makers van OAS er niet vanuit konden gaan dat de toenmalige versie van JSON Schema stabiel zou zijn. Om echter wel vooruit te kunnen met OAS, is er besloten een eigen dialect van JSON Schema vast te stellen in OAS: het OpenAPI Schema. Na de lancering van OAS 3.0 lanceerde de JSON Schema werkgroep een stabiele versie (draft 2020) van JSON Schema. Helaas week deze af van het OAS 3.0 dialect, waardoor JSON Schema niet gebruikt kon worden in OAS. Immers, tooling die OAS ondersteunde, ging uit van het OAS dialect en niet van de JSON schema draft. |
| 108 | + |
| 109 | +```mermaid |
| 110 | +classDiagram |
| 111 | + direction TD |
| 112 | + note for Adres "BAG" |
| 113 | + note for Plaats "CBS" |
| 114 | + note for Organisatie "ROO" |
| 115 | +
|
| 116 | + Api --> Organisatie : $ref |
| 117 | + Organisatie --> Adres : $ref |
| 118 | + Adres --> Plaats : $ref |
| 119 | + |
| 120 | + class Organisatie["Organisatie.schema.json"]{ |
| 121 | + string naam |
| 122 | + Adres postAdres |
| 123 | + Adres bezoekAdres |
| 124 | + } |
| 125 | + class Adres["Adres.schema.json"]{ |
| 126 | + string straat |
| 127 | + Plaats plaats |
| 128 | + } |
| 129 | + class Plaats["Plaats.schema.json"]{ |
| 130 | + string naam |
| 131 | + } |
| 132 | + class Api["openapi.json"] { |
| 133 | + string naam |
| 134 | + Organisatie organisatie |
| 135 | + } |
| 136 | +``` |
| 137 | + |
| 138 | +## Impact analyse |
| 139 | + |
| 140 | +Uit een impact analyse op alle API's in het huidige register blijkt dat 15% gebruikmaakt van het keyword `nullable`. Dit moet worden aangepast voor volledige compatibiliteit met OpenAPI 3.1, maar veroorzaakt geen breaking change in de meeste tooling. Daarnaast gebruikt 3% van de API's het keyword `exclusiveMaximum`, wat bij een upgrade wel tot breaking changes kan leiden en dus aangepast moet worden. Gelukkig is het mogelijk om deze aanpassingen automatisch door te voeren met de tool [openapi-format](https://www.npmjs.com/package/openapi-format): |
| 141 | + |
| 142 | +```sh |
| 143 | +openapi-format openapi-3.0.json -o openapi-3.1.json --convertTo "3.1" |
| 144 | +``` |
| 145 | + |
| 146 | +In het [nieuwe API-register](https://developer.overheid.nl/blog/2025/06/18/het-nieuwe-api-register) zullen wij deze conversie standaard toepassen, zodat alle API's probleemloos kunnen overstappen naar OpenAPI 3.1 en iedereen direct profiteert van de vele voordelen van deze nieuwe versie. Wij zullen er in ieder geval alles aan doen om de expertgroep van Forum Standaardisatie ervan te overtuigen dat het tijd is om de volgende stap te zetten. |
0 commit comments