© Yurii Andreichyn/Shutterstock.com
Ein Set-up für REST-Schnittstellen

Die Eleganz von REST APIs mit Symfony


Wir EntwicklerInnen wollen klar definierte Schnittstellen und finden Dokumentieren mühsam. Wir lieben das Gefühl valider Daten, haben aber keine Lust, langweiligen Code für die Validierung zu schreiben. Ja zu sauberen Schnittstellen, Nein zu Duplikaten im Code. Das Ziel ist es, möglichst einfach sicherzustellen, dass alle Schnittstellen exakt definiert sind und nur Daten in der vorgegebenen Form bei der Applikation ankommen.

Was ist nötig, um klar definierte Schnittstellen zu erhalten, ohne aufwendig dokumentieren oder langweiligen Code schreiben zu müssen? Wie entsteht sauberer und zweckmäßiger Code ohne Duplikate? Diese Gedanken sind mir durch den Kopf gegangen, als ich wieder einmal ein Set-up für REST APIs mit dem Framework Symfony aufgebaut habe. Dieses Mal wollte ich alle diese Punkte unterbringen. Zur Spezifikation von APIs verwenden wir schon lange das OpenAPI-Format (ehemals Swagger). Damit sind die Schnittstellen dokumentiert und können einfach getestet werden. Die Informationen, die für die Validierung von eingehenden Daten benötigt werden, sind alle schon in dieser Spezifikation vorhanden und warten nur darauf, wiederverwendet zu werden. Auch die nachfolgende Weiterverarbeitung der Daten in eine nutzbare Form soll möglichst einfach funktionieren. Mit verschiedenen Symfony Bundles kann ein Set-up geschaffen werden, das genau das macht und einem bei jedem neuen API, das man implementiert, ein richtig gutes Gefühl gibt.

OpenAPI vs. Swagger

2015 wurde aus der Swagger-Spezifikation der offene Standard OpenAPI [1], an dem seither ein Konsortium aus verschiedenen Experten gemeinsam arbeitet. Das war ein wichtiger Schritt, hat allerdings zu einigen Verwirrungen geführt, da das Toolset dazu weiterhin unter dem Namen Swagger geführt wird. Eine Leseempfehlung für alle, die wissen wollen, wo genau die Unterschiede liegen und wie sich das Ganze entwickelt hat, gibt es unter [2]. So richtig durchgesetzt hat sich diese Namensänderung meiner Meinung nach nicht, meistens wird sowohl für die Spezifikation als auch für das Toolset nach wie vor der Begriff Swagger verwendet. Wie man es auch nennen mag – für uns hat sich diese Form sehr bewährt. Sowohl als Kommunikationshilfe bei der Definition eines API vor einem Projekt als auch zur Dokumentation für laufende Projekte hilft sie, Klarheit zu schaffen und Missverständnisse zu vermeiden.

Verwendung mit Symfony

Damit wir unsere Schnittstellenspezifikation nicht selbst schreiben müssen, verwenden wir in Kombination mit Symfony das NelmioApiDocBundle [3]. Das sucht sich u. a. aus Konfigurationsdateien, den konfigurierten Routen und speziellen Swagger Annotations Informationen zusammen und generiert daraus eine Spezifikation, die als JSON oder in einer WebView ausgespielt werden kann.

Das möchte ich euch gerne anhand eines Beispiels zeigen. Unsere Ausgangslage ist eine Installation von Symfony 4.3 mit einer einfachen Entity Contact, die folgende Properties hat: id, name, email, country. Dazu gibt es einen ContactController, der Actions für GET, POST, PUT und DELETE implementiert. Den vollständigen Code zu diesem Artikel findet ihr in meinem Repository [4]. Bei der Installation des NelmioApiDocBundle wird uns dank des zugehörigen Symfony Recipes bereits eine Konfigurationsdatei erstellt. In dieser können wir u. a. den Titel und die Beschreibung unserer Schnittstellen angeben und vor allem auch festlegen, welche Routen in der Spezifikation vorkommen sollen (Listing 1).

Listing 1

# config/packages/nelmio_api_doc.yaml nelmio_api_doc: documentation: info: title: Contacts API description: An API for fetching, adding, adapting and deleting contacts. version: 1.0.0 areas: # Include everything available at /api except the doc APIs. default: path_patterns: - ^/api(?!/(doc.json|doc)$)

Allein aus dieser Konfiguration und den schon vorhandenen Routenkonfigurationen kann das Bundle bereits eine minimale Spezifikation des bestehenden API erstellen. Im ContactController aus meinem Beispiel in Listing 1 ist in den Requirements der Routenkonfiguration für das GET API definiert, dass es einen Queryparameter id gibt und dieser nur aus Zahlen...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang