Apps | Web

OpenAPI 3.0 – Blaupause für REST APIs

Ein Beitrag von
12. September 2019
openapi
Als Backend Entwickler hat man zwangsläufig mit REST APIs zu tun, doch auch im Frontend- und App-Development kommt man um die Kommunikation mit solchen APIs nicht herum. Damit die Interface-Landschaft nicht zum Wilden Westen wird und sich unterschiedliche Entwickler leichter austauschen und an einem Strang ziehen können, wird natürlich ein Standard entwickelt: OpenAPI als sprichwörtlicher Messias (bitte verzeiht den Frevel).

Representational State Transfer (REST) ist ein Entwicklungsmuster im Bereich von Web/Netzwerk-basierten Softwaresystemen. Es legt fest, wie unterschiedliche Systeme miteinander kommunizieren und Daten austauschen. Dieser Austausch geschieht über Programmier-Schnittstellen – Application Programming Interfaces(APIs). Die OpenAPI Specification (OAS) dient der Beschreibung solcher Interfaces. Setzt eine API nun auf REST als Architektur-Vorgabe, wird daraus eine RESTful API, auch REST API genannt. Die unterschiedlichen Client-Apps für Smartphones, Desktops etc. können so alle auf eine gemeinsame Schnittstelle zugreifen und sprechen so auch die gleiche Sprache. Für gewöhnlich werden Daten über solche REST APIs im JavaScript Object Notation (JSON) Format ausgetauscht, was aber nicht zwingend notwendig ist.

 

 

A RESTful API (done right) is just a website for clients with a limited vocabulary. [Roy Fielding, InfoQ]

 

One Ring Specification to rule them all

Diese APIs müssen nicht nur implementiert, sondern auch dokumentiert werden, damit Mensch und Maschine gleichermaßen damit arbeiten können. Dokumentation ist in der Programmierung und Entwicklung ein sehr wichtiger Prozess, der leider oft ermüdend ist und in einem Mehr (also zusätzlich) an Arbeit resultiert. Die OpenAPI Specification (OAS) schickt sich an, diesen Aufwand zu reduzieren und eine einheitliche API-Definition zu ermöglichen. Die Definition kann dann beispielsweise von Tools zur Generierung von Dokumentationen und Implementierungen (Client und Server), sowie für API-Tests verwendet werden.

 

 

OpenAPI hieß früher Swagger (heute OpenAPI 2.0) und die Dokumentation dazu ist auch heute noch unter swagger.ioim Web zu finden. OpenAPI 3.0.2 ist die die aktuelle Version der Spezifikation zum Zeitpunkt dieses Blogposts. In einer OpenAPI-Datei (JSON oder YAML) können ganze APIs beschrieben werden, dazu zählen:

  • Allgemeine Informationen wie Lizenz, Nutzungsbedingungen, Kontakt und Server

  • Authentifizierungsmethoden (z.B. API-Keys oder Basic Auth)

  • verfügbare Endpunkte (z.B. /posts) und deren HTTP-Operationen (GET, POST usw.)

  • Eingabe- und Ausgabe-Daten für die einzelnen Operationen

 

 

Zum Tooling rund um OpenAPI gibt es eine praktische Sammlung unter openapi.tools. Dort findet sich eine Menge an Tools für OAS: Converter, um andere API-Spezifikationen zu OpenAPI 3.0 umzuwandeln, Prüftools zur Verifikation der OpenAPI Spezifikation und der eigenen API, Generatoren für schön aufbereitete Dokumentation, Editoren und Linter zur einfacheren Bearbeitung von OpenAPI-Dateien, Generatoren für Clients und Server und vieles mehr. Zum Beispiel kann man mit dem Swagger Editor OpenAPI-Dateien bearbeiten und erhält eine Live-Vorschau der Dokumentation mittels Swagger UI. Swagger Codegen liefert auch noch die Möglichkeit, sich gleich passende Client-Bibliotheken generieren zu lassen.

 

 

Ans Eingemachte (Beispiel)

Eine API-Definition nach OAS in YAML (YAML Ain’t Markup Language) sieht wie folgt aus:

openapi: 3.0.0
info:
title: Sample API
description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/)
or HTML.
version: 0.1.9
servers:
- url: http://localhost:3000
description: Optional server description, e.g. Main (production) server
paths:
/users:
get:
summary: Returns a list of users.
description: Optional extended description in CommonMark or HTML.
x-swagger-router-controller: Users
operationId: usersGET
responses:
200:
description: A JSON array of user names
content:
application/json:
schema:
type: array
items:
type: string

Beispiel von swagger.io

 

Anfangs werden allgemeine Informationen zur API beschrieben, während unter paths die einzelnen Endpunkte definiert sind. Diese Datei kann man mit anderen Entwicklern teilen, damit diese eine Vorstellung von der API bekommen und ihre Software-Teile umsetzen können. Gleichzeitig kann man damit aber auch die vorher erwähnten Tools einsetzen, zum Beispiel Swagger UI.

Beispiel OpenAPI Definition in Swagger UI

Beispiel OpenAPI Definition in Swagger UI

 

Mit der Definition können wir auch eine Node.js Server-Applikation füttern. Alles was wir hierfür tun müssen, ist ein Skript index.js mit folgendem Inhalt:

'use strict';
 var fs = require('fs'), path = require('path'), http = require('http');
 var express = require('express');
 var app = express(); 
 var oasTools = require('oas-tools');
 var jsyaml = require('js-yaml'); 
 var serverPort = 3000; // swaggerRouter configuration
 var options = { controllers: path.join(__dirname, './controllers'), }; // The Swagger document (require it, build it programmatically, fetch it from a URL, ...) 
 var spec = fs.readFileSync(path.join(__dirname,'api/swagger.yaml'), 'utf8');
 var swaggerDoc = jsyaml.safeLoad(spec);  // Initialize the Swagger middleware 
 oasTools.initializeMiddleware(swaggerDoc, app, function (middleware) {  // Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain 
 app.use(middleware.swaggerMetadata()); // Validate Swagger requests 
 app.use(middleware.swaggerValidator()); // Route validated requests to appropriate controller
 app.use(middleware.swaggerRouter(options)); // Serve the Swagger documents and Swagger UI 
 app.use(middleware.swaggerUi()); // Start the server 
 http.createServer(app).listen(serverPort, function () { 
 console.log('Your server is listening on port %d (http://localhost:%d)', serverPort, serverPort); 
 console.log('Swagger-ui is available on http://localhost:%d/docs', serverPort); });  });

Code aus Swagger Codegen mit Änderungen für oas-tools

 

Im Verzeichnis controllers/ legen wir nun die einzelnen Handler für die jeweiligen Endpunkte und Operationen ab, während in api/swagger.yaml unsere OpenAPI Definition verweilt.

 

 

Ein Handler bzw. Controller für den /users-Endpunkt könnte so aussehen:

'use strict'; 
const DB = require('../lib/Database'); 
 module.exports.usersGET = async (req, res, next) => { 
 const users = await DB.usersGET(); res.send(users); 
 };

Die operationId aus der API-Definition wird hier automatisch der entsprechend benannten Methode zugeordnet – nice! Die Controller-Datei ist mit x-swagger-router-controller festgelegt (controllers/Users.js). Nach der Installation der benötigten Pakete express, oas-tools und js-yaml (z.B. über NPM) ist die Applikation dann auch schon lauffähig und unter http://localhost:3000 bzw. http://localhost:3000/docs (Swagger UI) erreichbar.

Klingt gut, schmeckt gut

Was heißt das konkret? App-Entwickler müssen dank fertiger Spezifikation und Mocking-Möglichkeiten nicht auf ein fertiges Backend warten, ehe sie mit der Entwicklung und dem Testing beginnen können. Backend-Entwickler können die Validierung der Parameter an die entsprechenden OAS Tools abgeben. Und und und. Wie ihr sehen könnt, bietet OpenAPI einige Vorteile für die koordinierte Entwicklung von Schnittstellen in der Welt der REST APIs und, wer weiß, vielleicht werden in Zukunft weniger Bücher wie Surviving Other People’s APIs verfasst.  😉

Bild zusammengestellt mit Material von OpenAPI Initiative und Swagger