14.11.2024

API Dokumentation mit FastAPI: Ein Blick auf die wichtigsten Funktionen.

FastAPI Dokumentation mit Programmierbeispielen

Es gibt eine Sache, die uns immer wieder umtreibt, wenn wir eine gute API bauen wollen - die Dokumentation. Insbesondere für öffentlich konsumierbare APIs weiß man nie, wer diese einsetzt und wie die Voraussetzungen des jeweiligen Entwicklers sind. Für eine besonders gute DX (= Developer Experience) statten wir unsere OpenAPI Dokumentationen mit Code-Beispielen in vielen Sprachen aus.

Blueshoe und FastAPI: Dokumentation mit Programmierbeispielen

Inhaltsverzeichnis

Dokumentation via OpenAPI

Zuallererst die Grundlagen - FastAPI ist eines der Frameworks, welche wir verwenden, um APIs zu schreiben. Es basiert auf Python und wirbt mit sehr guter Performance. FastAPI ist stark typisiert, was bedeutet, dass die Typen Eingabe- und Ausgabewerte im Programm weitestgehend bekannt sind (in dem Rahmen, in dem das in Python möglich ist).

Durch die bekannten Typen lässt sich ein Schema der API generieren. Dieses Schema beinhaltet alle notwendigen Informationen zu den verfügbaren Endpunkten. Als Standardformat wird hierfür OpenAPI hergenommen. Beispiel für ein OpenAPI Endpunkt:

openapi: 3.1.0
info:
  title: Redocly Museum API
  description: An imaginary, but delightful Museum API for interacting with museum services and information. Built with love by Redocly.
  version: 1.0.0
  contact:
    email: team@redocly.com
    url: 'https://redocly.com/docs/cli/'
  x-logo:
    url: 'https://redocly.github.io/redoc/museum-logo.png'
    altText: Museum logo
  license:
    name: MIT
    url: 'https://opensource.org/license/mit/'
servers:
  - url: 'https://api.fake-museum-example.com/v1'
paths:
  /museum-hours:
    get:
      summary: Get museum hours
      description: Get upcoming museum operating hours
      operationId: getMuseumHours
      x-badges:
        - name: 'Beta'
          position: before
          color: purple
      tags:
        - Operations
      parameters:
        - $ref: '#/components/parameters/StartDate'
        - $ref: '#/components/parameters/PaginationPage'
        - $ref: '#/components/parameters/PaginationLimit'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetMuseumHoursResponse'
              examples:
                default:
                  summary: Museum opening hours
                  value:
                    - date: '2023-09-11'
                      timeOpen: '09:00'
                      timeClose: '18:00'
                    - date: '2023-09-12'
                      timeOpen: '09:00'
                      timeClose: '18:00'
                    - date: '2023-09-13'
                      timeOpen: '09:00'
                      timeClose: '18:00'
                    - date: '2023-09-17'
                      timeOpen: '09:00'
                      timeClose: '18:00'
                closed:
                  summary: The museum is closed
                  value: []

        '400':
          description: Bad request
        '404':
          description: Not found

Die erzeugte Spezifikation enthält Beispiele, mögliche Antworten, sowie Beschreibung der Parameter des Endpunktes.

Programme wie Swagger oder Redoc greifen dieses Schema auf und erzeugen eine für Menschen lesbare Ansicht im Browser:

Redoc Beispiel

Hier werden Informationen wie Authentifizierung, Pagination und Filter für den Endpunkt dargestellt.

Beispiele in API Dokumentation

Ein großer Mehrwert des OpenAPI Standards ist, dass aus den strukturierten Daten auch noch Beispiele erzeugt werden können. Dies sieht in Redoc dann beispielsweise folgendermaßen aus:

Redoc API Aufruf

Die Beispiele können explizit bei der Entwicklung angegeben werden oder sie werden mit einfachen Daten (wie 0 für Integer, "string" für Zeichenketten) automatisch erzeugt. Diese Beispieldaten für einen HTTP Post Request zu unserer FastAPI zeigen allerdings nur den Payloads. Zur Unterstützung der Entwickler, die unsere API benutzen, wollen wir konkrete Programmierbeispiele einbetten. Dies lässt sich mit Redoc via dem x-codeSamples Tag einfach realisieren. Doch woher bekommen wir die Beispiele, ohne jede Programmiersprache selbst zu lernen?

Erzeugung von Codebeispielen - Pakete

Auf Github sind wir auf 2 Pakete gestoßen, welche zur Generierung von API Code Beispielen geeignet scheinen: postman-code-generators und httpsnippet. postman-code-generators stammt von Postman, einer Firma welche sich rund um Entwickler-Tooling für APIs beschäftigt. Es hat seine eigene Datenstruktur, um für HTTP Anfragen abzubilden.

httpsnippet stammt von Kong, einer Firma, welche vornehmlich ein API-Gateway entwickelt. Es arbeitet mit dem Standard von HTTP Archives. Beide Pakete sind gut gewartet und wir entscheiden uns an dieser Stelle aus pragmatischen Gründen für postman-code-generators. Die Daten, die wir in unserem OpenAPI Schema vorhanden haben, lassen sich recht leicht in die Strukturen von Postman überführen

Umwandlung der OpenAPI in Postman Strukturen

Zuerst zur Struktur des Postman SDKs. Um mit postman-code-generators zu arbeiten, wird zusätzlich das SDK postman-collection benötigt.

const codegen = require('postman-code-generators')
const sdk = require('postman-collection')


const baseUrl = "https://unsere-api.de"
const openapiJSON = getOpenApiJSON();
const supportedCodegens = codegen.getLanguageList()

postman-code-generators kommt mit einer Liste von Sprachen, über die wir einfach iterieren, um Codebeispiele zu erzeugen.

for (const codegen of supportedCodegens) {
   language = codegen.key;
   languageLabel = codegen.label;
   for (const variation of codegen.variants) {
       variant = variation.key
       generateSamples()
   }
}

Jede Sprache hat verschiedene Varianten, welche i.d.R. einfach verschiedene Möglichkeiten abbilden, HTTP Anfragen zu stellen - z.B. http und requests für Python. Unsere generateSamples Funktion erzeugt nun einfach für jeden Endpunkt (hier nur POST Endpunkte) ein Codebeispiel in der aktuellen Sprache:

function generateSamples() {
   // generate samples for open api endpoint paths
   const paths = openapiJSON["paths"]
   for (const [path, operation] of Object.entries(paths)) {
       currentPath = path;
       const data = generateExamplePayload(operation["post"], openapiJSON)
       convertEndpoint(path, "POST", data, addEntry)
   }
}

Im Rahmen der Erzeugung des Payloads (generateExamplePayload) wird dann das Postman Request Objekt erzeugt:

function buildRequest(url, method, data) {
   // build postman request
   return new sdk.Request({
       url: `${baseUrl}${url}`,
       method,
       body: buildBody(data),
       header: {
           ...header,
       }
   })
}

Da wir in unserer openapi.json Datei mit Schemata arbeiten, nutzen wir ein weiteres Paket, welches uns hilft Beispiel-Payloads für diese Schemata zu erzeugen:

var OpenAPISampler = require('openapi-sampler');
const schema = spec["components"]["schemas"][name]
   // Generate sample data
   return OpenAPISampler.sample(
       schema,
       {},
       spec
   )

Zum Schluss stecken wir unsere Schleife und die Code Generierung zusammen:

function convertEndpoint(path, method, data, cb) {
   const request = buildRequest(path, method, data)
   codegen.convert(language, variant, request, sampleFormattingOptions, cb);
}

Als letzten Schritt fügen wir die erzeugten Beispiele in unsere openapi.json Datei ein:

function addEntry(error, snippet) {
   if (error) {
       console.log(error, language, variant)
       return
   }
   const xCodeSample = {
       lang: languageLabel,
       label: `${languageLabel} (${variant})`,
       source: snippet
   }
   if (openapiJSON["paths"][currentPath]["post"]["x-codeSamples"]) {
       openapiJSON["paths"][currentPath]["post"]["x-codeSamples"].push(xCodeSample)


   } else {
       openapiJSON["paths"][currentPath]["post"]["x-codeSamples"] = [xCodeSample]
   }
}

Und schon beinhaltet unsere openapi.json Datei Codebeispiele aus allen möglichen Sprachen.

Redoc alle Clients

Fazit

Die Entwicklung einer API und das Schreiben einer Dokumentation dient nicht nur dem Selbstzweck. Es gilt, die Benutzer / Entwickler in Betracht zu ziehen, welche beispielsweise unsere REST API konsumieren. Die API Konsumenten dort abzuholen wo sie stehen, sodass die Verwendung der API weiter erleichtert wird, sollte insbesondere das Ziel für öffentliche Schnittstellen sein.

Was unsere Kunden über uns sagen

Ofa Bamberg GmbHRainer Kliewe
Ludwig-Maximilians-Universität MünchenProf. Dr. Mario Haim
Deutsches MuseumGeorg Hohmann
Fonds Finanz Maklerservice GmbHNorbert Porazik
  • Ofa Bamberg GmbH
    Ofa Bamberg GmbH
    B2B Online-Shop | B2C Website | Hosting | Betreuung | Security
    Rainer Kliewe
    © Ofa Bamberg GmbH
    Blueshoe betreut uns und unsere Webapplikationen seit vielen Jahren. Vom Online-Shop bis hin zu großen Teilen unseres Web-Umfelds hat sich das Unternehmen stets kompetent, verlässlich und vorausschauend gezeigt. Wir sind sehr zufrieden mit Blueshoe als Partner.
    Rainer KlieweGeschäftsführer
  • Ludwig-Maximilians-Universität München
    Ludwig-Maximilians-Universität München
    Plattformentwicklung | Hosting | Betreuung | APIs | Website
    Prof. Dr. Mario Haim
    Blueshoe hat unsere Forschungsdatenplattform Munich Media Monitoring (M3) entwickelt und uns hervorragend dabei beraten. Das Team hat unsere Anforderungen genau verstanden und sich aktiv in die Ausgestaltung der Software und der Betriebsumgebung eingebracht. Wir sind froh, dass auch Wartung und weiterführender Support in Blueshoes Händen liegen.
    Prof. Dr. Mario HaimLehrstuhlinhaber, Institut für Kommunikationswissenschaft und Medienforschung
  • Deutsches Museum
    Deutsches Museum
    Digitalisierung | Beratung | Datenbank-Optimierung | GraphQL | CMS
    Georg Hohmann
    Foto: Anne Göttlicher
    Im Rahmen eines komplexen Digitalisierungsprojekts für unsere Exponate-Datenbank war Blueshoe ein äußerst verlässlicher Partner. Sie haben uns nicht nur während des gesamten Projekts hervorragend beraten, sondern unsere Anforderungen perfekt umgesetzt. Dank ihrer Arbeit ist unsere Datenbank nun ein bedeutender Mehrwert für die weltweite wissenschaftliche Forschung.
    Georg HohmannLeiter Deutsches Museum Digital
  • Fonds Finanz Maklerservice GmbH
    Fonds Finanz Maklerservice GmbH
    Plattformentwicklung | Prozess-Systeme | Hosting | Betreuung | Zertifikate | Website
    Norbert Porazik
    © Fonds Finanz Maklerservice GmbH
    Blueshoe ist unsere verlängerte Werkbank für Entwicklung, Wartung und Support unserer Weiterbildungs- und Zertifizierungsplattformen. Das Team hat sich gründlich in unsere Abläufe eingearbeitet, und wir freuen uns, Blueshoe als zuverlässigen Partner an unserer Seite zu haben.
    Norbert PorazikGründer und Geschäftsführer
BLUESHOE GmbH
© 2024 BLUESHOE GmbH