Dies ist eine kurze Zusammenfassung meines zweiwöchigen Praktikums zum Thema “Hypermedia as the Engine of Application State” (HATEOAS). Ausgehend von einem Talk Jon Moores war die Überlegung, ein HTML-basiertes Format zu spezifizieren, mit dem HATEOAS umgesetzt werden kann. Abgesehen von der weiten Verbreitung von HTML und der möglichen Nutzung des Browsers als generischen Client bieten sich weitere Vorteile gegenüber Alternativen, die auf XML oder JSON basieren. Alle nötigen Elemente, auch Formulare, welche bei JSON fehlen, stehen bereits zur Verfügung. Das Problem ist, dass für diesen Anwendungsfall bisher keine allgemeingültige Spezifikation existiert. Der von Jon Moore verwendete Ansatz sind mit HTML5 Microdata annotierte Objekte, die jedoch aufgrund fehlender Flexibilität hier nicht zum Einsatz kommen.

Nach weiterer erfolgloser Suche nach einem Standard wurde beschlossen, selbst einigen Elementen eine Rolle im Format zuzuweisen und darauf aufbauend ein Format zu spezifizieren, das sowohl im Browser funktioniert als auch von Maschinen verarbeitet werden kann. Hierbei sollte der REST-Ansatz zum Einsatz kommen, sodass jede Repräsentation einer Ressource mit einer URI abgerufen werden kann. Außerdem sollte die Client-Server-Bindung durch den Einsatz von HATEOAS möglichst gering gehalten werden, was durch die Verwendung von Relationen und Links erreicht wird, wodurch der Client nie selbst Links zusammensetzen soll. Werden anpassbare Links benötigt, werden diese mit ihren Parametern in einem Formular bereitgestellt, das dann wie üblich in einem GET-Request abgesendet wird. Der Server soll also seine Struktur und damit die Links jederzeit ändern können, ohne dass der Client etwas davon merkt.

Da der Client etwas braucht, das statisch bleibt und anhand dessen er sich im Dokument zurechtfinden kann, ist jeder Link zu einer Ressource durch eine Relation gekennzeichnet. Diese ist entweder eine URI oder ein standardisierter Begriff. Ein Link zu einem Artikel könnte somit folgendermaßen aussehen:

<a href="https://example.com/articles/1234"
   rel="http://rels.example.com/article">Hallo Welt</a>

Alternativ könnte er aber auch so aussehen:

<a href="https://example.com/3827eeabc49e4509e9c77e904ab6311c"
   rel="http://rels.example.com/article">Hallo Welt</a>

Welche Variante verwendet wird, spielt nur für den Server, nicht aber für den Client eine Rolle.

Die Navigation startet von einer Hauptseite, dessen URI sich nicht ändert und die dem Client bekannt ist. Von dort aus kann der Client anhand von Links und deren Relationen die API erforschen, weshalb wir für unser Projekt den (vielleicht unpassenden) Namen »Web Discoverable Hypermedia« gewählt haben. Wird nun am Server ein neues Feature hinzugefügt, kann man es als neuen Link auf der Hauptseite hinzufügen. Kennt ein Client das Feature, kennt er dessen Relation und kann darauf zugreifen, für andere Clients ändert sich nichts, was Erweiterungen einfach macht.

Eine weitere Fragestellung ist die Einbettungen von Resourcen, die einige Probleme mit sich bringt. Beispielsweise können damit nicht alle Daten in einem Dokument direkt einer Ressource zugeordnet werden, sondern müssen erst darauf geprüft werden, ob sie nicht zu einer anderen Ressource gehören. Um das Parsen zu erleichtern, werden eingebettete Ressourcen in in einem details-Element ausgeliefert, welches wiederum in summary und article unterteilt wird. Dabei enthält summary den Link mit Relation, article stellt die eigentlichen Daten bereit.

Um die Überlegungen umzusetzen, zu dokumentieren und zu testen, hat Frederik Dohr einen Beispiel-Server, einen Beispiel-Client und Dokumentation in einem GitHub-Repository bereitgestellt. Hier finden such auch Details und (möglicherweise) Aktualisierungen zu den oben genannten und weiteren Aspekten.

Ich selbst habe eine Python Client API begonnen, die vereinfachten Zugriff auf WDH-APIs bieten soll. Basis ist ein Client, der mit der oben genannten Hauptseite initialisiert wird. Anschließend können anhand von Relationen Ressourcen ausgewählt werden, auf deren Daten und Relationen dann zugegriffen werden kann. Auch bereitgestellte Formulare können befüllt und abgeschickt werden. Weitere Details und Beispiele finden sich auch hier im Repository.