REST-APIs heute

Der Datenaustausch zwischen Frontend und Backend stellt ein wichtiges Werkzeug für uns Programmierer dar. REST-Schnittstellen sind ein Mittel zum Zweck, jedoch führt nicht gleich jede Umsetzung sofort zu einer übersichtlich strukturierten REST-API. Weniger sauber konzipierte Schnittstellen haben oft zur Folge, dass es Missinterpretationen oder Verständnisschwierigkeiten gibt. Nicht selten sind dabei fehlendes Wissen und die Nichtbeachtung von Best Practice eine Ursache. In diesem Artikel werden einige sinnvolle Wege und Möglichkeiten hinsichtlich der Benennung aufgezeigt, die es uns erleichtern, eine hierarchisch strukturierte API zu bauen. Ziel sollte dabei sein, dass später Ressourcen und Zusammenhänge leicht verstanden werden können.

Kurzexkurs REST

Um die Frage zu beantworten, was mit REST eigentlich gemeint ist, werfen wir einen Blick auf die Definition. REST steht für Representational State Transfer und wurde von Roy Fielding im Jahr 2002 vorgestellt. Dabei handelt es sich nicht um ein Protokoll oder einen Standard. Vielmehr stellt REST einen Architektur-Stil für Web-Services dar. Vereinfacht gesagt werden bei diesem Stil Daten und Funktionalität als Ressourcen betrachtet, die durch URIs (Uniform Resource Identifiers) angesprochen werden können.

REST-API Naming Conventions

Damit später Ordnung und Struktur vorherrschen, ist die Benennung von Ressourcen ein wichtiges Kriterium bei der Entwicklung einer API. Als Ressource kann dabei ein Dokument, Bild, Dienst oder etwas Ähnliches verstanden werden. Gezielte Benennung und Struktur verstärken den Zweck einer Ressource. Später können Personen, die auf diese Schnittstelle zurückgreifen, Zusammenhänge einfacher verstehen. Zur Veranschaulichung werden nun ein paar Möglichkeiten vorgestellt. Als Beispielszenario dafür wird angenommen, dass für einen Fahrzeugverleih eine REST-API erstellt werden soll.

Nomen für Ressourcen im Plural

Sinnvoll und gängig bei der Benennung von REST-API-Ressourcen ist die Verwendung von Nomen durch Wahl eines treffenden Begriffs. Mit Nomen lassen sich weitere Attribute und Eigenschaften später besser zur Ressource zuordnen. Für diesen Fall würde bei einer Ressource für Fahrzeuge demnach vehicle auf ein einzelnes Fahrzeug verweisen, während unter vehicles die Gesamtheit aller Fahrzeuge verstanden werden kann. Bei REST spricht man auch von Collection (vehicles) sowie Singleton (vehicle). Der Plural macht daher Sinn, sodass durch dieses Vorgehen auch einzelne Eigenschaften und Attribute gut adressiert werden können.

/vehicles

/vehicles/12

In den oberen Zeilen sehen wir ein konkretes Beispiel, wie die Anwendung eines solchen Prinzips aussehen kann. Während in der ersten Zeile die Gesamtheit aller Fahrzeuge (vehicles) angesprochen wird, zeigt die darunterliegende Zeile explizit auf ein einzelnes Fahrzeug mit der id=12. Beide Zeilen lassen den Zusammenhang, dass es sich um ein einzelnes Fahrzeug aus der Gesamtmenge handelt, schnell klar werden.

Keine Verben in URL's

Weiterhin sollte bei der Definition von URLs darauf geachtet werden, keine Verben zu verwenden. CRUD Operationen(Create, Read, Update, Delete) können hier Abhilfe schaffen. Mittels GET, PUT, POST oder beispielsweise DELETE lassen sich auch einzelne Pfade für eine Ressource mehrfach verwenden. Bei den genannten Operationen handelt es sich um die primären Http-Methoden, die mit den CRUD-Operationen in Verbindung stehen. Hierdurch lassen sich unterschiedliche Absichten und damit verschiedene Operationen ausdrücken. Die Operationen geben dadurch auch Aufschluss, ob etwas geholt, gesetzt oder beispielsweise gelöscht werden soll. Des Weiteren sollten Verben auch vermieden werden, um unnötige Verwirrung zu verhindern und Overhead zu eliminieren.

(GET)    /vehicles/12/getColor

(GET)    /vehicles/12/color

(DELETE) /vehicles/12/color

Angewendet auf das Beispiel der Autovermietung sehen wir oben wieder drei Ressourcen-Aufrufe. Die erste Ressource zeigt hierbei ein schlechtes Beispiel, das zu vermeiden ist. Die Ressource verwendet hier mit getColor ein Verb. Es findet sich der Methodennamen in der Ressource wieder und darüber hinaus wird Camelcase verwendet. Beides ist unschön. Bei Ressourcen mit längeren Wörtern kann dies schnell sehr unsauber werden und zu Verwirrung führen. Gut gelöst wird der Zugriff auf die Ressource in der darunter liegenden Zeile. Die Ressource wird mit einem GET-Request angesprochen. Die Absicht wird klar und deutlich vermittelt. In der zweiten Zeile soll eine Farbe für ein bestimmtes Fahrzeug mit id=12 gesetzt werden. In Zeile drei wird die Farbe wieder entfernt.

Nesting (Schachtelung) von Ressourcen

Geschachtelte Ressourcen können Fluch aber auch Segen sein. Daher ist es empfehlenswert, diese Kapselung sparsam einzusetzen. Auch hier gilt: "Weniger ist mehr". Wird dies beachtet, entsteht eine funktionale Hierarchie, die zur Vereinfachung von Zusammenhängen und damit zu einem runden Gesamtbild beiträgt.

/vehicles/12/components/44/specifications/13

/vehicles/12/vehicle-number

Das obige Beispiel zeigt auf, was passiert, wenn zu viel Schachtelung betrieben wird. Innenliegende Teile des Aufrufs auf die Ressource müssen zunächst verstanden werden, um den Gesamtaufruf und dessen Bedeutung nachvollziehen zu können. Der Kontext geht dadurch unter Umständen schnell verloren. Hingegen wird im Beispiel darunter zügig viel verständlicher dargestellt, dass das Fahrzeug mit id=12 eine Fahrzeugnummer besitzt. Für Aufruf-Versuche, wie in der oberen Zeile zu sehen, sollte eventuell ein Aufruf mit Filter-Parametern herangezogen oder eine kürzere Lösung dafür überlegt werden.

Definition eines Ursprungstyps

Für die Strukturierung einer API ist es wichtig, Ressourcen zu verwenden, von denen andere Ressourcen abgeleitet werden können. Diese Basis-Ressourcen kann als eine Art Ursprungstyp bezeichnet werden. Darunter lässt sich eine Ressource verstehen (in unserem Fall wieder beispielsweise vehicles), von der aus alle weiteren URIs abgeleitet und beschrieben werden können. Die oben bereits genannten Punkte fließen hier mit ein. Fahrzeuge können unterschiedliche Attribute haben, die selbst wieder Attribute besitzen. Deshalb ist die Wahl des Begriffs auch wichtig, sodass später möglichst gut damit gearbeitet werden kann.

/vehicles/12

/vehicles/12/chassis-number

/vehicles/12/components/

/vehicles/12/components/34/data

Die darüberliegenden Zeilen zeigen unterschiedliche Beispiele für mögliche Ableitungen von einem Ursprungstyp auf.

Verwendung von "/"

Eine weitere Konvention stellt der '/' (Schrägstrich) dar. Hierarchische Beziehungen werden durch dieses Zeichen besser hervorgehoben und für den Anwender werden die Ressourcen leichter lesbar und damit verständlich ausgedrückt.

/vehicles/12/data/power/

/vehicles/12/data/power

Auch hier ist der bedachte Umgang mit Schrägstrichen wichtig. Das Resultat in der ersten Zeile sieht zwar nicht verkehrt aus, ist jedoch unschön und kann eventuell bei Verwendung von bestimmten Frameworks Probleme verursachen. Zudem könnte dem Betrachter vermittelt werden, dass nach dem Slash noch weitere Daten kommen, was auch Verwirrung erzeugt. Zeile Zwei zeigt hingegen ein gutes Beispiel und sorgt auch nicht für Verwirrung. Der Ressourcen-Aufruf wird hier auf den Leistungs-Parameter (power) begrenzt.

Verwendung von Trennstrichen

Neben Schrägstrichen ist auch die korrekte Verwendung von '-' (Trennstrichen) zu beachten. Besonders können hiermit Hierarchien betont und Bezeichnungen besser kenntlich gemacht werden. Der Einsatz dieses Zeichens führt auch zu besserer Lesbarkeit und entzerrt längere Ressourcennamen.

/vehicles/12/dateOfManufacturing

/vehicles/12/date_of_manufacturing

/vehicles/12/date-of-manufacturing

In der obigen ersten Zeile wird fälschlicherweise Camelcase verwendet. Der Einsatz macht die URL schlecht leserlich. Weiterhin gilt auch von übermäßiger Verwendung des Unterstrichs abzusehen und, sofern es sich nicht um eine Query handelt, diesen nicht zu verwenden, weil er leicht übersehen werden oder aber zu Irritationen führen kann. Auf Queries wird im unteren Abschnitt noch einmal kurz eingegangen. In der Web-Welt werden Trennstriche von manchen Suchmaschinen unterschiedlich behandelt und die Annahme, dass es keinen Unterschied darstellt, ist demnach hinfällig. Als Beispiel kann man das im Chrome Browser erkennen. Dort werden bei der Markierung von Teilen der URL in der Adressleiste die Wörter je nach Trennzeichen unterschiedlich markiert angezeigt. Es sollte also überlegt werden, welches Trennzeichen zum Einsatz kommt und sinnvoll ist. Das letzte Beispiel ist für den Fall, dass eine Ressource aus mehreren Wörtern besteht, daher sinnvoll und führt zu guter Übersichtlichkeit.

Verwendung von Query-Komponenten

Mit dem letzten Punkt in dieser Kurzübersicht soll ein Blick auf URL-Abfrageparameter geworfen werden. Dabei handelt es sich um optionale Key-Value-Paare, die in einer URL angehängt werden, um bestimmte Operationen wie Filterung oder Paging durchführen zu können. Das Beispiel unten zeigt den Aufruf einer Ressource für Fahrzeugbuchungen. Diese werden mit Hilfe von Query-Parametern gefiltert und können dann zurückgegeben werden. Im Beispiel werden mit der Filterung dabei Buchungen aus Österreich abgefragt, die sich dabei im Zeitraum vom 21. bis 23. Dezember befinden. Anfragen können damit auch mit Hilfe des Fragezeichens an die bestehende URI angehängt und mit & verknüpft werden, um Abfragen mit Filter-Kriterien auszuführen.

/vehicles/12/bookings/sortBy=date

Hier gibt es nun einen Fall, in dem ein Unterstrich Sinn ergibt.

/vehicles/12/bookings/sort_by=date

Wird diese Vorgabe beachtet, sieht die Anfrage ähnlich der in der darüberliegenden Zeile aus. Hier werden für das Fahrzeug mit der id=12 die entsprechenden Buchungen, sortiert nach Datum, angesprochen.

Fazit

Für weiterführende Informationen sind im letzten Abschnitt noch einige Referenzen / Quellen aufgeführt, die mich bei meiner Recherche begleitet haben. Dort lassen sich noch weitere ausführliche Informationen zum Thema finden.

Quellen dieses Artikels für ausführliche Informationen

REST-API Naming