Shownotes & Links
- REST und HTTP
- Dissertation von Roy Fielding
- Atom Syndication Format
- HAL
- SIREN
- Colllection+JSON
- Atom Publishing Protocol
- Play
- Rails
- JAX-RS
- Spray
- Spring MVC
- Vortrag von Jon Moore auf der GOTO Berlin bzw. QCon
- ROCA
- Neue HTTP/1.1-RFCs
- SPDY
- HTTP/2-RFC
- HTTP/2 explained
- Swagger
- RAML
- API Blueprint
- OAuth 1
- OAuth 2
- OpenID Connect
- Vortrag zu OAuth2 und OpenID Connect
- HAL-Bibliotheken
- HAL-Browser
Transkript
Stefan Tilkov: Hallo und herzlich Willkommen zu einer neuen Episode des innoQ-Podcasts. Heute in einer ganz besonders großen Runde. Wir haben gedacht, wir machen mal unsere eigene Talkshow, sammeln eine erlesene Autorenriege zusammen und machen Werbung für unser Buch. Schauen wir mal, wie gut das funktioniert. Erstmal bitte ich alle in der Runde, sich mal vorzustellen. Silvia, fang du doch kurz an.
Silvia Schreier: Ja hallo, ich bin Silvia Schreier, arbeite bei innoQ als Consultant, beschäftige mich schon seit einigen Jahren mit REST – sowohl in der Wissenschaft als auch jetzt in der Praxis – ja und freue mich, heute uns über spannende Themen zu unterhalten.
Stefan Tilkov: Alles klar. Der nächste in der Runde ist Martin.
Martin Eigenbrodt: Ja, ich bin Martin Eigenbrodt, bin eine gefühlte Ewigkeit bei innoQ, beschäftige mich dort mit Entwicklung von Webanwendungen und RESTful APIs, meistens mit Java oder Scala.
Stefan Tilkov: Und der letzte: Oli Wolf.
Oliver Wolf: Ja, meine Name ist Oliver Wolf, bin seit ungefähr vier Jahren jetzt bei innoQ und ja, genau wie meine Kollegen auch, Berater und beschäftige mich mit dem ganzen Thema SOA und Services, was alles sich so damit zu tun hat, seit vielen Jahren inzwischen. Und damit natürlich auch in der neuesten und aktuellsten, modernsten Ausprägung in Form von REST.
Stefan Tilkov: Alles klar. Das Thema ist REST, weil ich das große Glück hatte, mir diese drei Kollegen als Co-Autoren suchen zu können, damit die verfluchte nächste Auflage meines – jetzt unseres – REST-Buches endlich mal raus kommt, die wir gestern in den Druck gegeben haben, hurra. Deswegen haben wir uns gedacht, das ist eine gute Gelegenheit, einfach mal über REST zu sprechen. Und sinnvollerweise, denke ich, fangen wir einfach kurz damit an, indem wir mal erklären, was das eigentlich ist. Silvia, willst du einen Versuch starten?
Silvia Schreier: Ich versuche das mal. REST steht ja erstmal für Representational State Transfer – ein ziemlich sperriges Wort –, kommt ursprünglich aus einer Dissertation von Roy Fielding aus 2001 und ist sozusagen der Architekturstil des Webs. Das heißt, alle Ideen sind quasi eingeflossen, um dann HTTP zu bauen oder auch andersrum, wenn man das so sehen will. Und das Ganze basiert auf fünf Grundprinzipien, die das Web so skalierbar machen, wie es auch einfach heutzutage ist.
Das Erste ist, dass jede Sache – egal, eine Person, ein Artikel, was auch immer – eine identifizierbare Ressource ist und damit auch eine eindeutige URL im Web hat. Das heißt, wenn ich so eine URL habe, kann ich die jemand anderem schicken, der bekommt die gleichen Inhalte dargestellt, wie ich sie vorher gesehen habe.
Das Zweite ist, dass man Inhalte in verschiedenen Formaten darstellen kann. So eine Darstellung nennt man Repräsentation einer Ressource. Und so kann ich mir z. B. vorstellen, dass ich einen Inhalt als HTML-Seite abrufen kann, ich kann den aber auch als PDF bekommen oder eine Bilddarstellung oder bei irgendwelchen Daten als CSV zum Beispiel.
Die dritte Säule ist dann, dass man für alle Ressourcen ein einheitliches Interface zur Verfügung stellt. Das ist quasi sehr unterschiedlich zu der objektorientierten Denke, wo ich mein Objekt mit vielen verschiedenen Methoden ausstatte, die immer genau auf die Rolle zugeschnitten sind. Stattdessen habe ich diese HTTP-Standard-Verben wie GET, PUT, POST und DELETE. Das sind die vier, die man am häufigsten benutzt. Es gibt auch noch HEAD, um nicht alle Daten zu kriegen. Und die kann ich dann auf alle Ressourcen anwenden bzw. eine Ressource kann auch entscheiden, einen Teil davon nicht anzubieten. Damit kann ich dann Ressourcen abrufen, mit einem GET, oder ich kann sie mit einem PUT modifizieren, mit einem DELETE löschen oder mit einem POST z. B. neue Ressourcen anlegen oder andere Verarbeitungen anstoßen.
Das vierte ist die zustandslose Kommunikation. Das ist für viele erstmal etwas ungewohnt. Das heißt, dass jeder Request, den ein Client an einen Server schickt, quasi alle Informationen beinhaltet, die der Server braucht, um diese Anfrage zu verarbeiten. Das heißt, ich schicke z. B. immer mit, wer ich bin, was ich alles haben will und der Server muss sich keinen Zustand merken, also wissen, dass ich schon mal da gewesen bin, und dass ich z. B. gerade eben diese Ressource oder jene Ressource abgeholt habe. Dadurch habe ich natürlich die Möglichkeit, dass das Ganze unheimlich gut skaliert, weil ein Client mit jedem Server, der diese Ressource bedienen kann, quasi sprechen kann, egal ob er vorher schon da war oder ob er gerade eben mit einem anderen Server gesprochen hat.
Und das letzte Prinzip nennt sich Hypermedia und – wenn man es noch ausführlicher will – Hypermedia as the Engine of Application State.
Stefan Tilkov: Oder, jetzt muss du dieses tolle Acronym sagen.
Silvia Schreier: Ja, HATEOAS oder HATEOAS, wie auch immer man das gerne aussprechen möchte. Das ist, erlebt gerade so ein bisschen eine Renaissance oder bzw. das entdecken jetzt alle möglichen Leute plötzlich für sich, dass REST ja mehr ist, als diese anderen vier Sachen, sondern dass da jetzt plötzlich auch Hypermedia dazu kommt. Die Idee dahinter ist, was für uns im Web total natürlich ist, dass ich einem Link folge. Das heißt, auf einer Webseite ist ein Link zu einem weiteren Artikel oder zu einer weiteren Erklärung oder zu irgendeinem Katzenvideo oder was auch immer. Und ich als Benutzer weiß, dass ich auf diesen Link klicken kann und zu einer weiteren Ressource komme. Die Idee von Hypermedia ist, dass ich quasi meine Anwendungsressourcen auch untereinander so verknüpfte und so mich durch die Inhalte der Anwendung oder des Service bewegen kann. Und das Wichtige ist, dass es dabei nicht nur darum geht, sich durch die Inhalte zu bewegen, sondern auch mit Hilfe von Links, den Zustand der Anwendung auch wirklich verändern zu können. Das heißt, ich kann, wenn ich so einem Link folge, nicht nur ein GET darauf machen, was man typischerweise im Web macht, sondern ich kann ihn z. B. auch dafür benutzen, um die Ressource zu löschen oder sie mit einem PUT zu editieren. Und wenn man das nutzt, erhält man eine deutlich losere Kopplung zwischen zwei Services, weil der Service, der die Ressource anbietet, mir quasi den Link anzeigt, den ich nutzen kann, um etwas zu machen oder um weitere Informationen zu erhalten.
Stefan Tilkov: Jetzt ließt man häufig sowas, wie “REST vs. SOAP” oder “REST vs. Webservices”. Was hältst du von der Diskussion?
Silvia Schreier: Es sind beide Möglichkeiten, verteilte Systeme zu bauen. Man sollte sich entscheiden, was man machen will. Eine Mischung davon funktioniert nicht. Also, der große Unterschied ist wirklich schon allein diese Verwendung von Standard-Verben, also eines Uniform Interfaces, vs. eben eines spezifischen Interfaces. Also das, was ich bei einem SOAP-Service mache, dann habe ich ein Interface und Operationen, die ich pro Service definiere. Das heißt, es ist einfach ein großer Unterschied, man sollte das nicht als SOAP, was auch eine Technologie ist, vs. REST, was erstmal nur ein abstrakter Ansatz ist – selbst wenn man dann schon RESTful HTTP spricht –, immernoch nichts sehr Konkretes dann in dem Fall ist, vergleicht man so ein bisschen Äpfel mit Birnen miteinander. Das heißt, man sollte sich überlegen, was ich in meinem Anwendungsfall brauche, was am Besten passt und dann sind das beides legitime Architekturentscheidungen erstmal.
Stefan Tilkov: Würdest du denn sagen, dass das vor allem für Services gedacht ist oder auch für andere Dinge im Web?
Silvia Schreier: Also SOAP ist sicherlich nur für Services gedacht, weil – also ich als Endanwender möchte keinen SOAP-Service bedienen müssen. Aber REST ist sowohl für Services gedacht, als auch eben für Webanwendungen. Weil alle Webseiten, die wir verwenden, wenn sie denn eben gut gebaut sind, sind eigentlich RESTful, ich kann sie ohne Probleme benutzen und kann somit sogar mit einer Anwendung quasi beides bedienen, sowohl den menschlichen Client als auch den Maschinen-Client.
Stefan Tilkov: Jetzt ist eine Sache, die du vorhin gesagt hast, die Verlinkung, der Hypermedia-Aspekt, und ich glaube bei HTML können sich das die meisten Leute relativ gut vorstellen, dass man einem Link folgt und dass man ein Forumlar hat, das vom Server kommt, in das man was einträgt, das man mit POST oder GET dann abschickt. Wie macht man das Ganze denn, wenn man Maschinen-zu-Maschinen (M2M)-Kommunikation macht?
Silvia Schreier: Für die M2M-Kommunikation kann ich verschiedene Formate
verwenden. Das historischste ist wohl XML. Auch in XML kann ich Links
unterbringen. Also, wenn man sich Atom z. B. anschaut, dann waren da auch schon
immer Links drin, nämlich zu den einzelnen Blogpost-Einträgen zum Beispiel. Ich
kann aber auch in jedes andere textbasierte Format prinzipiell erstmal Links
unterbringen, muss mich dann aber natürlich darauf einigen, wie ich die quasi
ausdrücke. In HTML ist klar, dass z. B. hinter einem <a>
-Tag sich ein
Attribut href
im Normalfall verbirgt, wo dann eben ein Link drin steht. Oder
in einem Formular ist eben auch die URL kodiert. Und da gibt es auch inzwischen
Varianten für JSON, wie ich sowas darstelle.
Stefan Tilkov: Oli, erzähl du uns doch mal was zu diesen Varianten. Welche Varianten für JSON oder für XML gibt es denn, die in irgendeiner Form dabei helfen, Hypermedia auszudrücken?
Oliver Wolf: Ja, da gibt es natürlich inzwischen eine ganze Menge an Dingen, die da so entstanden sind in den letzten Jahren. Also, man muss dazu sagen, vielleicht bevor wir auf die Formate ein bisschen detaillierter eingehen: nichts davon, vielleicht mit einer Ausnahme, hat so ein bisschen den Status als Standard. Also, das meiste sind Vorschläge von schlauen Leuten, die sich Gedanken darüber gemacht haben, die auch in der Szene irgendwo einen Namen haben und die durch Vorträge und Publikationen sich da vor tun. Auch sehr positiv hervor tun. Und ja, das einzige, wo man vielleicht sagen kann, dass es so ein bisschen diesen Standard-Charakter hat, das wäre aus meiner Sicht HAL. Die Hypermedia Application Language. Das ist ein Standard, der eigentlich sehr schlank ist von der Beschreibung her. Das heißt, man kann praktisch beliebige JSON-Dokumente sehr einfach um Hypermedia-Elemente erweitern, ohne sie dabei fundamental ändern zu müssen. Das ist ein sehr großer Vorteil, wenn ich einfach bestehende APIs habe, die bisher keine Hypermedia-Fähigkeiten hatten, aber die mit diesen Hypermedia-Fähigkeiten jetzt versehen möchte, dann kann ich das damit sehr einfach tun. Nachteil dabei …
Stefan Tilkov: Du musst mir mal kurz auf die Sprünge helfen. Was wäre das denn jetzt, was ich als Hypermedia-Aspekt da einbauen würde? Was ist denn ein gutes Beispiel, damit man sich das vorstellen kann? Also ein JSON – ich vermute, dass die meisten Zuhörer bei uns irgendwie schon mal JSON über HTTP irgendwo abgeholt haben oder hingeschickt haben. Was wäre denn ein Hypermedia-Aspekt, den man ergänzen würde?
Oliver Wolf: Ja gut, ein Hypermedia-Aspekt wäre z. B., wenn ich beispielsweise ein JSON-Dokument bekomme, was eine Repräsentation einer Collection ist, dass ich in dieser Collection Links habe, die auf die einzelnen Elemente dieser Collection verweisen. Das wäre so eine sehr einfache Art von Verlinkung zwischen verschiedenen Repräsentationen und auch das ist ja letztendlich schon Hypermedia. Es geht natürlich in der Praxis wesentlich weiter, Silvia hat das ja gerade schon gesagt, dass das eigentliche Ziel natürlich ist, Zustandswechsel von Ressourcen auch über das Verfolgen von Links herbeizuführen. Und damit kann ich natürlich auch mir vorstellen, dass es in Repräsentationen Links gibt, über die ich Aktionen auslöse, wie den Zustand einer Ressource verändere. Zum Beispiel eine Bestellung in der Status “Versandt” zu setzen.
Stefan Tilkov: Was jetzt, wobei “Link folgen” müssen wir doch noch, bevor jemand denkt, wir haben überhaupt gar keine Ahnung, müssen wir nochmal deutlich sagen: mit “Link folgen” meinen wir hier nicht, ein GET drauf zu machen, sondern eben die zur Aktion passende Methode drauf anzuwenden.
Oliver Wolf: Natürlich, richtig. Das hätte ich vielleicht dazu sagen sollen, ja.
Stefan Tilkov: Ja.
Oliver Wolf: Damit will man natürlich an den Punkt, wie kommuniziere ich jetzt einem Client, welche Aktionen er ausführen kann. Denn erstmal, wenn der Client auf einen Link trifft, dann hat der erstmal kein Wissen darüber, was da zu tun ist. Da unterscheiden sich die aktuellen Formate so ein bisschen. HAL ist da relativ schlank, das heißt, bei HAL gibt es erstmal vom Standard her keine Spezifikation, die beschreibt, wie diese Zustatzinformation – also sprich “Welches Verb kann ich auf diesen Link anwenden?” – zu transportieren ist. Das kann man natürlich erweitern, klar. Ich meine, das ist letztendlich JSON, und JSON hat ja die schöne Eigenschaft, dass ich es fast beliebig erweitern kann, ohne damit bestehende Implementierungen zu brechen. Und das haben wir z. B. im Buch auch getan. Da haben wir ja in unserem Code-Beispiel HAL benutzt und erweitert, um die Fähigkeit, auch die Information darüber zu transportieren, welches Verb zu nutzen ist. Es gibt aber andere Formate, wie z. B. Siren von Kevin Swiber, was da ein bisschen weiter geht und eben nicht nur den Link und die Information über die Link-Relation transportiert, sondern auch solche Detailinformationen wie “Welches Verb kann benutzt werden?” und “Wie sehen die Nachrichten aus, die dann dahin geschickt werden müssen?”.
Stefan Tilkov: Wie würdest du diese – oder gibt es noch andere Formate, die man erwähnen kann, außer HAL und Siren?
Oliver Wolf: Es gibt noch eine ganze Reihe anderer, was vielleicht auch noch relativ prominent ist, ist das “Collection+JSON” von Mike Amundsen. Vor allen Dingen auch deswegen, weil Mike Amundsen natürlich auch eine bekannte Größe in der Szene ist. Collection+JSON ist ein bisschen spezieller vom Einsatzzweck her. Es ist also ein nicht ganz so generisches Format, sondern bezieht sich eigentlich primär auf die Arbeit mit Collections. Also ist so ein bisschen vielleicht vergleichbar mit AtomPub, mit dem AtomPub-Protokoll, wer das kennt. Also, es geht dadrum, eine Collection von Ressourcen zu haben und dieser Collection Objekte hinzuzufügen, Objekte aus der Collection zu löschen usw. In der Collection zu suchen zum Beispiel auch.
Stefan Tilkov: Und wie würdest du die miteinander vergleichen? Also welches gefällt dir am besten, magst du HAL am liebsten und deshalb haben wir es im Buch benutzt? Oder sind dir alle gleich recht?
Oliver Wolf: Hmm, schwer zu sagen. Also ich finde, ich persönlich mag Siren ziemlich gerne, weil ich finde, dass da ein paar nette Konzepte drin sind, zum Beispiel auch die Möglichkeit, einzelne Entitäten durch Klassenbezeichner zu qualifizieren. Damit habe ich so eine Art, will nicht sagen Vererbungshierarchie, aber das ist so ein bisschen vergleichbar wie Mixins in Programmiersprachen. Also, ich kann bestimmten Objekten in meinem JSON-Dokument, dadurch dass ich da einfach Klassenbezeichner dran schreiben kann, Informationen über die Semantik dieser Objekte mitgeben. Kann zum Beispiel sagen, dass irgendetwas in diesem JSON-Dokument sowohl ein Eintrag einer Collection ist, als auch eine Order, ne? Und damit habe ich die Möglichkeit, einen Client zu bauen, der ganz generisch mit Collections umgehen kann und der erkennen kann, dass es sich bei dieser Entität um einen Collection-Eintrag handelt. Ich kann aber auch einen Client bauen, der sehr spezifisch meine Fachlichkeit kennt und dann weiß, dass es sich bei diesem Eintrag um eine Order handelt und diese Order eben so behandeln kann, wie er eine Order behandeln würde. Das finde ich eine ganz schöne Eigenschaft. Ansonsten würde ich aber eher dazu tendieren, wenn ich jetzt was Neues machen würde, HAL zu benutzen, einfach weil es eine große Verbreitung hat, weil es gute Library-Unterstützung dafür gibt und es einfach auch sehr einfach und sehr schlank ist, was man von Siren nicht unbedingt behaupten kann. Das ist deutlich komplexer, aber damit auch eben deutlich ausdrucksstärker.
Stefan Tilkov: Library-Unterstützung ist ein gutes Stichwort. Was man häufig ausklammert – oder was man entweder ausklammert oder viel zu viel macht, ist der Bezug zu einer konkreten Implementierung. Also entweder Leute reden nur darüber, wie genau ihre eigene Implementierung funktioniert oder man redet gar nicht drüber. Wir sind eher schuldig des letzteren. Also, auch im Buch reden wir relativ wenig über Implementierung. Aber trotzdem ist das eine spannende Frage. Martin, was ist denn deine Sicht, was braucht man denn, wenn man erfolgreich RESTful Service APIs implementieren will?
Martin Eigenbrodt: Naja, wenn man sich anschaut, dass REST im Grunde die Architektur hinter dem Web ist, ist es wenig überraschend, dass man genau die Dinge benutzen kann, die man auch benutzen kann, um vernünftige Webanwendungen zu bauen. Das heißt, man benutzt sein Web-Framework erstmal, was HTTP z. B. verstanden hat und nicht versteckt, nicht weg abstrahiert. Das wäre z. B. sowas wie Play oder wie Rails. Das kann man dafür gut benutzen. Man bekommt da in der Regel aber etwas mehr, als man eigentlich braucht, weil ich für eine API meistens etwas weniger brauche, als für eine Anwendung, weil ich mich z. B. nicht um clientseitige Dinge wie CSS oder JavaScript und die Asset Pipelines und all solche Dinge nicht kümmern will. Das ist eigentlich zu viel, ich kann also ein bisschen reduzieren. Im Java-Umfeld wäre dann z. B. JAX-RS ein Kandidat, der sich, der fokusiert darauf wirklich nur, im Grunde nur HTTP vernünftig zu machen. Ich kann, wenn ich Scala machen, da Spray nehmen, was jetzt Akka-HTTP nimmt, was auch sehr schlank ist und einem sehr wenig Unterstützung für alles drum rum bietet. Aber wenn man sich eben auf eine API konzentriert, wäre das eine vernünftige Wahl. Wenn ich mich in einem Spring-Universum wohl fühle, kann ich natürlich auch da Spring-MVC z. B. nehmen.
Stefan Tilkov: Würdest du jetzt, wenn du beides macht, wenn du eine Webanwendung, also eine Webanwendung mit HTML für den Browser, plus – was heute relativ üblich ist – JSON und HTTP für die API Nutzung machst, würdest du dann zwei getrennte Dinge aufsetzen oder würdest du das aus einer Anwendung heraus mit einem Ding bedienen?
Martin Eigenbrodt: Wenn ich vom Schnitt meiner Anwendung her das an einer Stelle sehe, also wenn ich auf der selben Fachdomäne bin, dann würde ich das innerhalb eines Web-Frameworks in demselben Ding implementieren. Das ist auch die, denke ich, die Kernaussage, ich würde die Technik danach auswählen, womit ich mich als Entwickler wohl fühle und wo ich mich gut auskenne. Also, es ist jetzt kein Fehler, ein Full-Stack Web-Framework zu nehmen und dann eben die Hälfte davon nicht zu benutzen. Wenn ich mich in diesem Universum gut auskenne und wohl fühle, ist das völlig in Ordnung. Es macht natürlich wenig Sinn, sich ein neues Web-Framework anzueignen, wenn ich das zum Großteil gar nicht brauche.
Stefan Tilkov: Was sind denn Dinge, die so ein Framework leisten kann, die mir irgendwie weiter helfen? Also ich kann ja, ich kann – was weiß ich – ich kann ein Servlet benutzen oder CGI verwenden, um RESTful Services zu bauen, weil, wie du schon gesagt hast, alles ja nichts anderes ist, als das Web und HTTP. Was wären denn Dinge, die mir weiter helfen würden, die ein Framework mir bieten könnte?
Martin Eigenbrodt: Erstmal wäre mir wichtig, dass es mir nichts kaputt macht. Das es z. B. nicht versucht, die Illusion einer Zustandsbewahrung – oder, ja – vermittelt. Das heißt, dieses Framework sollte irgendwie zustandslos sein, es sollte mir die Chance geben, die Dinge, die in HTTP elementar sind, auch zu sehen. Das heißt, ich muss erkennen können, mit welchem Verb, mit welcher HTTP-Methode wurde ich denn aufgerufen? [Ich] muss zugreifen können auf Header zum Beispiel und die auch setzen können. Ich muss meinen Response auch in dieser Detailtiefe mal ändern können. Das ist etwas, was man historisch lieber versteckt hat, wo man gesagt hat “Ich gebe ein Java-Objekt zum Beispiel zurück und alles andere passiert magisch.” Das funktioniert für RESTful APIs nicht. Es gibt immer wieder den Punkt, wo ich sehr konkret sage “Ich möchte diesen Header setzen.” oder so. Wo ich Unterstützung gebrauchen kann, ist z. B. Content-Negotiation. Das heißt, dass ich irgendwie eine Möglichkeit habe, meinem Framework mitzuteilen, ich kann diese Dinge z. B. als JSON und XML, aber vielleicht auch in einer HTML-Darstellung raus geben. Wie kannst du mir dabei unter die Arme greifen? Ein Punkt, wo Unterstützung sehr schön wäre, aber immernoch recht dünn gesäht ist, ist eben genau der Hypermedia-Aspekt. Das heißt, ich brauche eine Möglichkeit, Links auf andere Ressourcen innerhalb meiner Anwendung z. B. zu generieren. Aber auch auf Ressourcen in anderen Anwendungen. An der Stelle sind wir dann oft an dem Punkt, wo ich auch nicht nur als Server agieren will, sondern selber HTTP-Client sein muss, für andere Services, mit denen ich integriere. Das wäre es schön, wenn meine Frameworks vernünftige Client-Unterstützung besitzen.
Stefan Tilkov: Vielleicht schieben wir das noch ein bisschen nach hinten. Einen Punkt finde ich sehr interessant, nämlich diese Link-Unterstützung. Irgendwie komme ich ja nicht drum herum, in meinem Anwendungscode mir Gedanken darüber zu machen, wie ich Links auf andere Dinge unterbringe. Wobei das irgendwie gefühlt von der Schicht her an der falschen Stelle passiert. Weißt du, was ich meine? Also irgendwie bin ich an einer Stelle, wo ich eigentlich mich mit Domänenlogik beschäftigen möchte oder zumindest mit einer abstrakten Schnittstellenlogik und da muss ich jetzt auf einmal so ein sehr konkretes Konzept, wie einen Link, einbauen. Und ich kann nachvollziehen, warum man das irgendwie doof findet. Man hat das Gefühl, man ist an der falschen stelle. Hast du dazu eine Meinung und hast du eine Idee, wie man damit konkret umgehen kann?
Martin Eigenbrodt: Ich glaube, es gibt noch ein vorgelagertes Problem. Das ist die Frage: “Was ist überhaupt mein Domänenmodell oder meine Domänenlogik?” Häufig ist das so, dass man seine Fachdomäne modelliert hat und dann denkt “Ja, die will ich ja jetzt nur rausrendern als JSON, und ich nehme die und bastel so ein bisschen und dann klappt das schon.” Man kommt aber relativ schnell in größeren Projekten an den Punkt, wo man feststellt “Nein, das stimmt nicht.” Die Schnittstelle, die ich nach außen habe, wie diese RESTful Schnittstelle, die hat ihre eigenen Domänenobjekte und die sind verwandt sicherlich zu meiner Fachdomäne, aber sie sind eben nicht identisch. Es lohnt sich, die getrennt zu modellieren. Und wenn ich diese getrennte Modellierung der Schnittstelle dann nach außen habe, dann habe ich auch einen Platz, wo Links plötzlich Sinn machen und wo sie hin gehören. Und da gehören sie dann rein. Man hat immernoch ein bisschen technischen Ärger, dass man bei der Link-Generierung manche Dinge einem erst spät weiß, also “Auf welchem Host laufe ich überhaupt?”, “Wie ist mein Hostname von außen?” Das sind alles technische Details, die man dann rein frickeln muss im Grunde, aber man hat dann einen Platz, wo Link-Generierung hin gehört.
Stefan Tilkov: Das heißt, du würdest – eigentlich ist das eigentlich auch eine allgemeine Weißheit – du würdest sagen, man sollte die Schnittstelle separat betrachten von der darunter liegenden Domänenmodellierung, weil man ansonsten beide zu sehr miteinander verheiratet.
Martin Eigenbrodt: Genau. Und meine Behauptung ist es, dass es sich lohnt, die auch in – wenn ich jetzt in einer Sprache bin wie Java – die in getrennten Objekten auszudrücken. Genauso wie man die Diskussion auch immer auf der Persistenzseite hat “Möchte ich, dass meine Objekte, die ich in die Datenbank schreibe, identisch sind mit meinen Domänenobjekten oder möchte ich das lieber trennen?” Und meine Aussage ist, gerade auch auf der Schnittstellenseite nach vorne möchte ich das lieber trennen.
Stefan Tilkov: Und dann muss man auch keine Bedenken haben, wenn man diese Schnittstellen Dinge eben mit HTTP oder REST-Spezifika verseucht, weil das sowieso architekturell was anderes sein wird, als ein Schnittstellenmodell, was man vielleicht für Webservices oder irgendeine andere Schnittstellentechnologie raus reicht.
Martin Eigenbrodt: Ganz genau.
Stefan Tilkov: Ok. Oli, diese Frage “Services vs. Webanwendung” bringt irgendwie den Punkt nochmal raus, dass man natürlich auch, anstatt sich ein tolles neues Hypermedia-Format auszudenken und dabei einzubauen, was man im eigentlichen Web-Hauptformat, nämlich HTML, findet, doch auch auf die Idee kommen könnte, einfach HTML zu benutzen. Also, anstatt mir einem Standard hinterher zu laufen oder mich an einen Standard dran zu hängen, der gerade noch im Entstehen ist und wo es noch viel Konkurrenz gibt, könnte ich doch auch einfach HTML benutzen?
Oliver Wolf: Stefan, das ist aber jetzt wirklich eine ganz und gar absurde Idee, oder?
Stefan Tilkov: Kaum rhetorisch gefragt.
Oliver Wolf: Nein, ist es natürlich nicht. Und es sind auch schon ein paar
andere Leute auf die Idee gekommen, das zu machen. Also ich erinnere mich da z.
B. an einen Vortrag von einem gewissen Jon Moore von Comcast, der hat das auf
der vorletzten GOTO-Konferenz in Berlin mal vorgestellt, wie das aussehen
könnte, wenn man das tun würde. Und das hat erstaunlich gut funktioniert und
das ist eigentlich auch kein Wunder, denn HTML ist eigentlich, wenn man sich
das anschaut, das Format, was die meiste Unterstützung für Hypermedia-Elemente
mitbringt von allen, die wir heute so kennen. Da ist eigentlich alles drin, was
man braucht. Und es ist vielleicht ein bisschen unintuitiv erstmal zu sagen,
ein Protokoll oder ein Format, was eigentlich dafür gedacht ist, grafisch
Benutzern präsentiert zu werden, jetzt für M2M-Kommunikation zu benutzen, aber
es geht erstaunlich gut. Denn Voraussetzung ist natürlich, dass man ein HTML
erzeugt, was sich nicht an der Gestaltung orientiert, sondern was versucht, die
Semantik der Inhalte zu beschreiben. Und dazu gibt es in HTML alle Mittel, die
man dafür braucht. Es gibt sowas wie unordered collections
zum Beispiel. Also
das <ul>
-Tag, beispielsweise. Und das würde man vielleicht in einer
Textdarstellung, was so die klassische Anwendung von HTML wäre, vielleicht
benutzen, um eine Aufzählung in einem Text darzustellen. Aber man kann das
natürlich genauso gut benutzen, um eine Liste von Collection-Einträgen zu
repräsentieren. Und das ist semantisch völlig korrekt. Und es hat auch noch den
Vorteil, dass man es dann sogar, dieses Format benutzen kann, um auch z. B. ein
Benutzer-UI zu bauen oder eine Benutzeroberfläche zu bauen, indem man es
entsprechend mit CSS stylt und dann benutzerfreundlich präsentiert. Also damit
kommt man dem Ziel, dass API und Webanwendung eigentlich das Gleiche sind, sehr,
sehr nah.
Stefan Tilkov: Was ist mit der Gegenrichtung? Jetzt hast du ja nur Dinge auf dem Server so dargestellt, dass der Client sie rendern kann. Ich glaube, das kann man noch relativ gut nachvollziehen und verstehen, warum das ein Vorteil sein könnte, weil ich ja, wie du gesagt hast, ein Format benutze, was schon mal von einem ziemlich verbreiteten Client verstanden wird. Was ist mit der Gegenrichtung, wenn ich jetzt was zum Server schicken will?
Oliver Wolf: Ja, auch da hat HTML natürlich mit Formularen genau das Mittel, was
man braucht, ne? Also genauso, wie ein Benutzer eben über ein HTML-Formular vom
Browser aufgefordert wird, irgendwelche Daten einzugeben und auf den
Submit-Button zu drücken, genauso kann natürlich auch eine Maschine aus einer
HTML-Repräsentation genau die Informationen entnehmen, welche URL aufzurufen
ist, welches Verb zu benutzen ist und welche Daten zu liefern sind, in Form von
<input>
-Elementen, die in der Form definiert sind.
Stefan Tilkov: Aber ist das Formular dann nicht total überflüssig? Die Anwendung weiß doch schließlich, was sie schicken will. Die braucht doch kein Formular vom Server, wo drin steht, was sie theoretisch schicken könnte.
Oliver Wolf: Naja, genauso kannst du argumentieren, der Mensch weiß ja auch, was er schicken möchte. Er wird ja auch im Prinzip durch ein visuell dargestelltes Formular aufgefordert und praktisch dadurch geleitet, die Informationen einzugeben, die jetzt nötig sind. Und genauso geht’s eben bei Maschinen auch. Man kann natürlich auch sagen “Die Maschine weiß das alles vorher.”, indem der Entwickler, der diese Maschine entwickelt hat, sich Dokumentationen durchgelesen hat und genau weiß, was da erwartet wird. Aber das Ziel von Hypermedia ist natürlich auch – und das hat Silvia vorhin schon dargestellt –, die Kopplung einfach zu reduzieren, zwischen Client und Server. Dazu geht eben auch, dass der Client möglichst wenig Wissen darüber haben müssen soll, was der Server eigentlich erwartet.
Stefan Tilkov: Silvia, lass mich zu dir nochmal zurück gehen mit der Frage, ob das dann nicht bedeutet, dass wir einfach nur Webanwendungen ordentlich bauen müssten, um das Thema gleich erschlagen zu haben. Ist das so? Also, müssten wir nur einfach irgendwie Webanwendungen vielleicht auf eine andere Art bauen und dann kriegen wir das API einfach geschenkt?
Silvia Schreier: Also, wenn man das, wenn man den Gedanken quasi zu Ende denkt, dass man HTML dafür benutzt, um Inhalte quasi zu transportieren, die auch semantisch auszeichnet, so dass sie jeder Client erstmal benutzen kann, dann kann man das auch noch sich überlegen, wofür denn diese anderen ganzen Webtechnologien, die es so gibt, eigentlich gedacht sind. Nämlich dafür, dass man CSS zum stylen benutzt, also das Layout und das Look and Feel quasi zu verändern. Dass man dann noch JavaScript nutzen kann, um quasi noch zusätzliches Verhalten mit auf den Client zu transportieren, sodass es für den Endbenutzer etwas charmater macht, die Anwendung zu benutzen, eine bessere User Experience liefert. Und wenn man sich das genau anschaut, dann ist das sogar noch eine der, das ist sozusagen die sechste Säule von REST, die wir vorhin gar nicht angesprochen haben, weil sie optional ist. Die nennt sich dann Code on Demand, das heißt, ich schicke dem Client quasi Code mit – in dem Fall JavaScript, das ist die gängigste Variante, wie man das macht –, die er dann ausführen kann, um quasi noch zusätzliches Verhalten, was nicht standardisiert ist, was nämlich nicht schon im Browser vorhanden ist, noch mit anzubieten, dem Benutzer. Also z. B. sei es ein Date-Picker, weil ich kann natürlich das Datum einfach in ein kleines Formularfeld, ein Textfeld eingeben, und wenn ich aber JavaScript zusätzlich nutze, dann kann ich da vielleicht so einen schönen Kalender anzeigen und das Datum viel angenehmer für mich als Mensch auswählen. Und wenn man diesen Gedanken weiter trägt und sich zu Ende denkt, dann – was auch ein paar von unseren Kollegen getan haben – dann kommt man auf sowas wie ROCA. Und das steht für Resource-oriented Client Architecture, was genau darauf aufbaut, dass man serverseitig REST benutzt, dann die Webtechnologien, wie sie gedacht sind, nämlich semantisches HTML, CSS fürs Styling und JavaScript eben für zusätzliche Funktionalitäten. Das nennt sich dann auch “Unobtrusive JavaScript”. Das heißt, ich habe da nur immer zusätzliche convenience Funktionen quasi mit drin. Und das ist auch wieder einfach eine Möglichkeit, sowohl den Maschinen-Client zufrieden zu stellen, als auch den Endbenutzer wirklich gute Experience zu bieten. Und zu diesem ROCA-Style gehört noch so ein bisschen mehr. Die Idee dahinter ist, dass man nämlich auch – das, was eigentlich in REST schon drin steckt, dass man jeder Sache eine URL gibt, die diese Sache identifiziert – versucht man auch auf jeder Seite einen Hauptinhalt zu haben. Was nicht heißt, ich darf keine Navigation oder sowas haben, sondern ich habe einen identifizierbaren Inhalt, den ich dann quasi auch eine URL gebe, und diese URL kann ich auch jederzeit durch die Gegend schicken, ich kann ein zweites Fenster mit dieser URL aufmachen und bin immer wieder da, wo ich eigentlich auch sein möchte.
Stefan Tilkov: Das musst du unbedingt meiner Bank mal erzählen. Die könnte davon deutlich profitieren.
Silvia Schreier: Genau.
Stefan Tilkov: Wenn ich ein zweites Fenster aufmachen könnte.
Silvia Schreier: Ja. Also, es gibt jede Menge Anwendungen im Web, wo man eben sowas nicht tun kann, wo ich einen Link an jemand anderen schicke und dann ist er wieder auf der Startseite oder ich schicke sowieso nur den Link für die Startseite durch die Gegend, der ändert sich auch nie, wenn ich auf der Seite verschiedenste Dinge tue. Das heißt, ich kann auch nicht später zurückkommen oder ein Bookmark setzen. Und wenn man ROCA quasi zuende denkt und auch nutzt und befolgt, dann ist das sehr gegensätzlich zu dem, was man heute mit Single-Page Anwendungen hat, die nämlich alles auf dem Client nur mit JavaScript erledigen und der Server da dann nur noch sehr wenig tut. Nämlich ein Mal am Anfang eine Menge JavaScript-Code ausliefern und dann passiert das alles im Client – und zwischendrin werden nur nochmal Daten ausgetauscht. Und warum wir auch ROCA als sinnvolle Architektur betrachten, aus Entwicklersicht vielleicht, ist, weil ich durch diese Trennung von semantischem HTML, CSS und JavaScript in ihrer Funktionalität auch eine klare Trennung kriege. Es ist klar, wer für was zuständig ist, der Server generiert das HTML und verarbeitet das Ganze dann auch und validiert das. Das CSS ist einfach nur da, damit es für den Endbenutzer schön ist. Und damit habe ich eine Separation of Concerns und kriege eigentlich auch eine sehr gute Wartbarkeit der ganzen Anwendung, weil ich weiß, wo ich was zu suchen habe und nicht alles irgendwie miteinander vermische.
Stefan Tilkov: Ok. Lasst mich diese Frage vielleicht ein bisschen in die Runde werfen. Was würden wir denn jetzt, was würdet ihr denn empfehlen, wenn wir – ich meine, eine Firmenmeinung haben wir ja nicht, da bin ich jetzt gespannt, was bei uns jetzt passiert, wenn ich das so frei in die Runde frage, aber: Was wäre denn aus eurer Sicht eine kluge Strategie, wenn man jetzt was Neues startet? Würdet ihr auf HTML setzen und es dabei belassen oder würdet ihr ein JSON-API daneben stellen oder was wären für euch Vor- und Nachteile der beiden Varianten?
Martin Eigenbrodt: Mir wäre da ein Punkt wichtig: alles, was Silvia gesagt hat, ist technisch richtig, ist mir aber zu technisch. Also, ich kann eine, kann HTML benutzen für die API und ich kann eine API so machen, dass sie auch von einem Menschen konsumiert werden kann, im Browser auf technischer Ebene. Häufig ist es aber so, dass sich die Verhaltensmuster oder die fachliche Anforderung des API-Clients im Sinne einer Maschine unterscheiden von den Anforderungen eines Menschen. Das heißt, dass ich möglicherweise einen anderen Ressourcenschnitt z. B. brauche, dass ich andere Links brauche. Das heißt, mein Interaktionsmodell insgesamt ist ganz anders. Ich kann trotzdem natürlich bei beidem HTML verwenden, aber es ist eine Illusion zu glauben, dass ich alles nur ein Mal bauen muss und das wird dann von zwei völlig verschiedenen Kunden gleich benutzt, weil die fachlichen Anforderungen unterschiedlich sein können.
Oliver Wolf: Ja, ich sehe das eigentlich genauso wie Martin. Ich finde auch, dass die Interaktion eines Mobil-Clients mit der Anwendung ganz anders sein kann, als die Interaktion eines Benutzers, der vor dem Browser an seinem Rechner sitzt. Und das wird sich auch in der API in irgendeiner Form widerspiegeln. Also, ich bin großer Freund davon, solche Webschnittstellen so zu gestalten, dass sie sich möglichst nah an den Anwendungsfällen orientieren, die darüber unterstützt werden sollen. Also, so Stichwort “Design for Intent”. Und das schlägt sich einfach auf den Ressourcenschnitt nieder, das schlägt sich auch auf die möglichen Aktionen nieder, die dann wiederum entsprechend sich in den Hyperlinks ausdrücken. Und ich glaube auch, dass man in vielen Fällen zu einem etwas anderen – oder manchmal auch sehr anderen – Modell kommen wird, als für die eigentliche Webanwendung. Trotzdem kann man aber natürlich technologisch zumindest schon mal das gleiche tun, ne? Also, es spricht ja nichts dagegen, das gleiche MVC-Framework zu benutzen, für die dem Menschen präsentierte Webanwendung und die API. Dass man zumindest auf technologischer Seite da einheitlich unterwegs ist und es dem Entwickler damit einfacher macht. Aber ich glaube auch, dass es heute noch ein bisschen früh ist vielleicht, Entwicklern, die z. B. Mobilapplikationen entwickeln, die es gewöhnt sind, gegen JSON-APIs zu arbeiten, mit HTML zu konfrontieren. Ich glaube, das wäre im Moment noch kontraproduktiv, wenn man das tun würde, einfach was die Annahme dieser API durch die Entwickler betrifft.
Silvia Schreier: Also, ich stimme zu, dass es einfach auch Clients gibt, die vielleicht JSON viel besser verarbeiten können – vielleicht auch, weil es eben kleine embedded Devices sind, die keine HTML-Parser zur Verfügung haben oder sowas. Dann würde ich auch sofort sagen, dass das definitiv der richtige Weg ist. Was ich nur wichtig finde ist, dass man die gleiche Fachlogik benutzt. Also nicht, dass ich jetzt zwei völlig verschiedene Anwendungen hoch ziehe, nur um zwei Clients zu bedienen, sondern dass ich eigentlich schon versuche, da einen gemeinsamen Service draus zu machen, der eben Persistenz-Anbindung, Validierung usw. gemeinsam nutzen kann. Dass das vielleicht insgesamt zwei völlig verschiedene Schnittstellen nach Außen anbietet, HTTP-Schnittstellen, das mag ja sein. Aber es kann sein, dass ich manche Ressourcen komplett benutzen kann und nur über Content-Negotiation unterscheide und andere wiederum nur in HTML oder nur in JSON anbiete. Aber dass ich nicht von vornherein sage, dass, wenn ich eine Webanwendung bauen will, ja dann brauche ich was ganz anderes, als wenn ich jetzt einen Service für M2M-Kommunikation abbilden will. Das passiert oft, dass Leute sagen: “Das sind zwei völlig unterschiedliche Dinge und deswegen brauche ich dafür unterschiedliche Frameworks und am besten auch noch zwei unterschiedlich laufende Anwendungen, die ich gleichzeitig pflegen muss.”
Stefan Tilkov: Also, wenn ich euch richtig verstehe, dann seht ihr das im Prinzip so, dass es zwei so orthogonale Aspekte sind. Das eine ist die Technologie, da mag mal die und mal die andere oder mal beide möglich sein. Und das andere ist, es gibt möglicherweise einen unterschiedlichen Ressourcenschnitt für unterschiedliche Use-cases, was ja auch nichts Ungewöhnliches ist und bedeutet nicht, dass nicht derselbe Ressourcenschnitt mit zwei verschiedene Technologien genutzt werden kann oder eben andersrum. Beides ist absolut denkbar.
Martin Eigenbrodt: Was sehr schön ist, was Silvia gerade ja auch gesagt hat, dass man gar nicht ganz zusammenlegen oder ganz trennen muss, sondern gerade durch die Möglichkeit der Verlinkung kann ich sagen “Ich habe bestimmte Ressourcen, die werden von beiden Clients benutzt”, und dann folgen die vielleicht einfach anderen Klickpfaden sozusagen. Und dann gibt es eben bestimmte Ressourcen, die guckt nur mein mobile Client an und der Desktop-Client könnte die vielleicht rein technisch aufrufen, tut das aber einfach nie, weil das nicht in sein Anwendungsmuster passt. Das heißt, diese APIs können sich überlappen und ich kann dann Synergien benutzen an den Stellen, wo sie die gleichen Dinge benutzen, die gleichen Fachlichkeiten und kann aber eben auch getrennte Sachen zusätzlich besitzen.
Stefan Tilkov: Ok. Lasst uns vielleicht nochmal kurz darüber sprechen, was wir sonst noch so im Buch untergebracht haben an neueren Dingen. Viel von dem, was wir jetzt besprochen haben, taucht in der ein oder anderen Form da auf. Hypermedia-Formate haben eine größere Rolle bekommen, viele andere Dinge, viele Fehler adressiert. Einen Punkt, den wir noch hinzugefügt haben, sind so ein paar neuere technische Entwicklungen im HTTP-Umfeld. Wer von euch hat Lust, dazu ein bisschen was zu erzählen?
Silvia Schreier: Der Punkt ist einfach, dass man vor ein paar Jahren festgestellt hat, dass der alte HTTP-RFC vielleicht schon ein bisschen in die Jahre gekommen ist, und dass man sich da vielleicht nochmal hinsetzen könnte und vielleicht auch nochmal ein bisschen überarbeiten könnte und ein bisschen Sachen klarstellen könnte. Und da gab es dann eine Working Group, die sich dadrum gekümmert hat, das quasi zu bearbeiten, und die ist jetzt auch kürzlich fertig geworden. Das heißt, aus dem einen HTTP-RFC sind jetzt plötzlich sechs neue geworden. Das heißt also, man sieht, das ist auch deutlich strukturierter geworden. Die Semantik hat sich nicht geändert, also es ist kein neues Protokoll oder sowas geworden, sondern es ist einfach ein bisschen aufgeräumt worden. Da haben eine Menge kluger Köpfe dran gearbeitet und es ist also auf jeden Fall mal ein Blick wert, diese neuen RFCs sich anzuschauen. Gleichzeitig dazu hat man aber irgendwie festgestellt, dass heutzutage die Anforderung, die wir ans Web haben – also wir benutzen das ständig und überall und mit mobilen Geräten, mit vielleicht nicht so guten Verbindungen, aber wir wollen trotzdem ein tolles Benutzererlebnis haben – dass das irgendwie mit HTTP/1.1 nicht mehr ganz so gut zusammen funtioniert. Also, ich habe einfach aufgrund von technischen Constraints sozusagen Probleme. Das heißt, ich muss – wenn ich eine neue Verbindung aufbaue, dann habe ich den sogenannten Slow Start, der einfach auf TCP basiert. Das heißt, wenn ich für jeden Request eine neue TCP-Verbindung aufmachen würde, dann habe ich immer so eine kleine Verzögerung. Und ich kann über eine Verbindung auch nur ein Request-Response Paar in der Regel benutzen. Und HTTP ist auch relativ geschwätzig. Das wird im Plain Text übertragen und wenn ich da so einen Stapel Header oben mit drin habe, dann ist das auch einfach relativ umfangreich. Und das sind alles so Sachen, die quasi die Performance vom Client nicht unbedingt verbessert haben bisher.
Stefan Tilkov: Aber sowas adressiert man, zumindest in webbasierten Anwendungen, doch schon lange, ne? Browser machen mehr als eine Verbindung auf, die machen zwei oder sechs oder acht, je nach Browser, und man macht all möglichen Hacks, indem man Sachen zusammen packt oder so. Adressiert das das Problem nicht genügend?
Silvia Schreier: Genau, also das adressiert das nicht genügend. Also, damit verbessert man die Performance für den Client schon mal massiv. Aber irgendwie hat sich dann Google mal irgendwann hingesetzt und hat gesagt “Wir haben einen Browser, wir haben den Chrome unter die Leute gebracht, der hat eine große Verbreitung, wir haben auch genügend Server, die werden auch von genügend Leuten benutzt, wir versuchen das doch jetzt einfach mal ein bisschen besser zu machen.” Das heißt, sie haben gesagt, “Wir behalten die Semantik bei, aber wir versuchen, die Übertragungsart einfach zu ändern, auf technischem Level.” Und haben dann angefangen, quasi Multiplexing auf der Leitung zu betreiben. Das heißt, eine TCP-Verbindung für mehrere Requests und Responses quasi zu benutzen. Und auch gleichzeitig die Header z. B. zu komprimieren. Und haben dabei festgestellt, dass das laut ihren Aussagen sehr gut funktioniert. Und das hat keiner mitgekriegt und viele haben das benutzt und dann hat man irgendwann gesagt, diese Working Group, die da am arbeiten war, hat dann beschlossen “Ok, wir sind jetzt fast fertig, vielleicht gehen wir doch mal das Thema HTTP/2 an.” Und haben dann quasi gesagt, haben einen Call gemacht, wo man – haben gesagt, die Semantik soll gleich bleiben bei HTTP, das wollen wir nicht ändern, aber wir wollen eben technisch verbesserte Übertragung. Und daraufhin gab es dann verschiedene Vorschläge, einer davon war eben auch SPDY und der ist es dann auch geworden. Und man hat …
Stefan Tilkov: SPDY ist der Name des Google-Protokolls. Das hast du glaube ich gar nicht gesagt.
Silvia Schreier: Genau. SPDY ist das – das haben wir noch nicht erwähnt. Genau. Und das wurde dann genommen. Und daraufhin dann weiter gearbeitet, um quasi HTTP/2 zu entwickeln. Und da hat man noch ein paar Sachen dran geändert, man hat z. B. die Header Komprimierung umgestellt. Aber hat ansonsten dieses Multiplexing z. B. beibehalten und die grundlegenden technischen Ideen, die dahinter stehen. Und jetzt ist HTTP/2 soweit, dass es eigentlich kurz vor der Standardisierung steht. Sie sind noch in den letzten Editor-Änderungen, aber das heißt, in Zukunft ändert sich vielleicht einiges für uns.
Stefan Tilkov: Was hat das konkret für Auswirkungen für APIs? Also, im Browser kann man sich vorstellen, die machen dann irgendwann HTTP/2, dann sind Dinge da schon mal anders. Was bedeutet es für jemanden, der sich vor allem für APIs interessiert?
Martin Eigenbrodt: Das Schöne ist meinem Verständnis nach, auf Architekturebene kaum etwas, ja? Weil die ganze Semantik gleich geblieben ist. Natürlich muss ich aber dann Clients und Server haben, die in der Lage sind, dieses neue Protokoll zu sprechen. Das heißt, ich muss gucken “Funktioniert das schon?” Aber ich muss jetzt nicht, wenn ich etwas entwickelt oder designt habe, das komplett neu machen, sondern das bleibt im Grunde erstmal alles so wie es ist. Es gibt natürlich so ein paar Schmankerln oben drauf, die man machen kann, wie dass der Server aktiv Dinge pushen kann. Aber das muss ich nicht benutzen. Das heißt, ich kann im Prinzip mit genau der Architektur und der Semantik aus HTTP/1.1 weiter arbeiten und trotzdem diese technischen Verbesserungen mitnehmen.
Stefan Tilkov: Ok. Jetzt haben wir schon ganz schön viel Content für unseren Podcast. Normalerweise bleiben wir ein bisschen weiter oben. Jetzt haben wir relativ tief schon uns bewegt. Gibt es Dinge, die ihr noch ergänzen wollen würdet, wenn wir so ein Übersichtsding machen? Oli?
Oliver Wolf: Ja, was wir ja auch jetzt im Buch zugefügt haben, ist das Thema Dokumentation, ne? Das ist ja was, was wir ja auch oft erleben – also ich weiß nicht, wie es euch geht, aber wenn ich z. B. meine SOA-Schulung veranstalte, dann kommt natürlich oft die Frage “Wie dokumentiert man denn solche APIs eigentlich?”
Stefan Tilkov: “Was ist die WSDL für mein REST API?”
Oliver Wolf: Genau. “Was ist die WDSL …?”, genau. Da hört man natürlich immer so ein bisschen raus, dass es manchen eben dann doch nicht so sehr um Dokumentation geht, sondern mehr um die Hoffnung, dass man jetzt doch wieder ganz viel Code generieren kann, um sich mit den Details der Technologie dann nicht beschäftigen zu müssen. Da sage ich dann immer “Ja, das ist eigentlich gerade nicht die Idee.” Wir wollen ja eigentlich weg davon, dass wir solche Protokolle nur als reine Transportmechanismen betrachten, sondern wir wollen sie als Integralbestandteil unserer Anwendung sehen, wo man die Anwendung praktisch um das Protokoll herum baut. Das ist ja eigentlich das, was wir im Web tun, im Vergleich zu SOAP oder sowas. Und insofern hat Dokumentation etwas an Stellenwert vielleicht, als sie ihn in der klassischen Webservice-Welt hatte, wo eben sehr viel mit Generierung gearbeitet wurde.
Stefan Tilkov: Was würden wir denn konkret vorschlagen als Dokumentationsstrategie für unsere REST APIs? Oder was für Optionen hat man überhaupt?
Silvia Schreier: Also es gibt einfach technologisch ein paar Optionen. Da gibt es sowas wie Swagger, was recht weit verbreitet ist, was in vielen Projekten benutzt wird. Es gibt sowas wie RAML – Resource Application Modeling Language, irgendwie sowas
Stefan Tilkov: Markup Language oder so.
Silvia Schreier: Markup Language. [Anm.: gemeint war RESTful API Modeling Language] Dann gibt es noch von apiary.io Blueprint. Und die sind sich alle relativ ähnlich, dass sie in irgendeinem Textformat sozusagen die API beschreiben und entweder daraus dann hübsche Dokumentation generieren oder auch Stubs generieren können oder Tests generieren können oder sie erstmal quasi Dokumentation first oder das als Modellierungssprache sozusagen benutzen wollen. Die haben nur alle drei eine große Schwäche, nämlich dass sie Hypermedia eigentlich außen vor lassen. Also das heißt, da nehme ich meine URLs und dokumentiere. Das heißt, ein Client, der diese Dokumentation nutzt, hart codiert dann diese URL-Muster quasi bei sich und greift dann auf die zu. Das heißt, der Server und der Client sind zu dem Zeitpunkt dann eigentlich doch wieder sehr eng gekoppelt, denn ob ich jetzt einen SOAP-Call mache, wo ich weiß, wie der aussehen muss, oder ob ich eine URL aufrufen muss, wo ich weiß, wie die aufgebaut ist, ist von der Kopplung her nicht mehr so groß unterschiedlich. Das heißt, das kann man machen, wäre aber die Empfehlung eher das für die internen Entwickler Dokumentation zu machen. Als Entwickler will ich natürlich wissen, welche Ressourcen bieten wir an, was können die alles, was liefern die wann und wo zurück. Dafür ist das sicherlich ein ganz guter Mechanismus auch vor allem, weil die zum Teil Testsupport bieten. Das heißt, da kann ich in der Dokumentation einen Request an die Ressource abschicken zum Beispiel. Jetzt könnte man sich fragen “Wie mache ich das denn jetzt aber für den Endanwender?” Und da liegt natürlich irgendwie nahe, dass ich z. B. meine Ressourcen, die im großen weiten Netz hängen, mit meiner Dokumentation einfach über Links verknüpfen könnte. Weil Dokumentationen sind auch wiederum Ressourcen, die sich auf andere Ressourcen beziehen. Das heißt, ich könnte jede Ressource mit einem Link zur zugehörigen Dokumentation oder zum zugehörigen Dokumentationsabschnitt versehen. Und die Dokumentation, nachdem die typischerweise für den Menschen gedacht ist, kann ich dann mit HTML umsetzen und kann auch aus der Dokumentation wieder in die Ressourcen verlinken, zum Beispiel. Und wir haben das noch nicht so ausführlich besprochen, aber wenn man jetzt Hypermedia macht, dann muss man auch Link-Relationen [benutzen]. Und wenn man keine standardisierten Link-Relationen benutzt, sondern eigene entwirft, dann sollten das im Normalfall auch URLs sein und dann kann ich natürlich hinter so einer URL auch wieder Dokumentation zu dieser Link-Relation verstecken, weil das der naheliegendste Ort ist, wo jemand danach suchen würde.
Stefan Tilkov: Ok. Das heißt, die beste Dokumentation wäre sozusagen eine Website, die so aussieht, wie die Anwendung, die man da dokumentiert. Würdet ihr das so unterschreiben? Oli?
Oliver Wolf: Das wäre sicherlich ein Ansatz. Wobei generell würde ich da grad zu dem, was Silvia gerade gesagt hat, noch ergänzen, dass in dem Moment, wo man sehr intensiv mit Hypermedia arbeitet und eigentlich auch bereits den Einstiegspunkt praktisch in die API über Hypermedia-Elemente gestaltet, indem man beispielsweise ein Startdokument hat, was einfach per Hyperlinks auf die, praktisch auf die Einstiegsressourcen, Einstiegs-Collections dieser API referenziert, dann hat generell Dokumentation einen anderen Charakter, als wir den vielleicht bisher so gesehen haben. Also, so klassische Dokumentationen von REST APIs gehen sehr stark auf URL-Struktur auf das Ressourcenmodell und sowas ein. Und das verliert natürlich alles in dem Moment, wo praktisch Hypermedia das führende Konzept ist, stark an Bedeutung, weil die konkreten URL-Pfade sich jederzeit ändern können und das eigentlich für den Client auch keine große Relevanz hat, denn er folgt ja letztendlich nur Links. Das heißt, der konkrete Inhalt, der konkrete Aufbau einer URL ist ohne Bedeutung, eigentlich. Oder sollte es zumindest sein. Das heißt, eine Dokumentation einer Hypermedia-API, wenn man es wirklich konsequent betreiben würde, besteht letztendlich eigentlich nur aus einer Dokumentation der einzelnen Link-Relationen. Also der Semantik der einzelnen Links, die es da geben kann. Und nicht mehr der Ressourcen oder der URL-Pfade oder sonst irgendwas. Das ist schon ein großer Unterschied und das wird auch von den Tools, die es heute so gibt – also nehmen wir mal sowas wie Swagger oder sowas – eigentlich überhaupt nicht unterstützt.
Silvia Schreier: Also, ich stimme dir zu, was ich aber nicht behaupten würde, dass man zu Ressourcen nicht trotzdem noch was dokumentieren kann. Nämlich z. B. für den Menschen prinzipiell “Welche Zustände kann diese Ressource durchleben?” oder “Welche Attribute erwarte ich zwangsläufig?” oder “Welche Formate kann ich da erwarten?” Also ganz, gar keine Dokumentation mehr zu den Ressourcen nicht, aber dass die Link-Relationen das zentrale Element sind, da stimme ich dir voll und ganz zu, und dass die auch mitliefern, was sich denn wohlmöglich dahinter verbirgt an Semantik.
Stefan Tilkov: Martin, würdest du das unterschreiben, dass die Struktur der URL keine besondere Bedeutung hat? Dass die Buchstaben darin keine besondere Bedeutung haben?
Martin Eigenbrodt: Ja und nein. Also rein von der Theorie her ist das völlig richtig und wenn ich einen gut gebauten Client habe, ist dem das auch egal. Dem gebe ich eine Einstiegs-URL und kann alles, was danach an Links kommt, auf Serverseite verändern und der sollte immer noch funktionieren. Es ist aber für Menschen oft unheimlich wichtig, und das ist ein Punkt, wo diese Dokumentationssprachen rein kommen, nämlich in der Phase des Designs habe ich das RAML öfter schon benutzt, weil es eine gute Chance gibt, mit Teamkollegen APIs zu diskutieren, die es noch gar nicht gibt. Wenn ich das diskutiere, dann ist es gut, wenn meine URLs sprechende Namen haben, unter denen jeder sich was vorstellen kann, weil ich Konzepte viel schneller transportieren kann. Das heißt, als sprachliches Kommunikationsmittel sind die Buchstaben in der URL enorm wichtig. In der technischen Ausprägung sollten sie am Ende dann aber wieder egal sein.
Stefan Tilkov: Ok. Haben wir sonst noch was Neues, über das wir noch reden sollten?
Silvia Schreier: Wir haben gerade einen Aspekt noch ein bisschen ausgelassen, nämlich wir haben jetzt behauptet, man folgt einfach nur Links. Aber wenn man sich das jetzt mal genauer anschaut, alle URLs kann der Client ja auch nicht immer wissen. Das heißt, manchmal muss man ihm schon sagen so nach dem Motto: “Wenn du den Benutzer mit der Kundennr. sowieso suchst, wie finde ich denn dann dessen URL?” Das heißt, dann kann ich ihm sogenannte URL-Templates quasi anbieten als Server. Das heißt, das ist dann sozusagen wie ein Formular in HTML die Struktur, wo der Client weiß, wie er das dann, wo er die Parameter quasi einsetzen muss in der URL. Das heißt, die eigentliche Struktur ist ihm egal, er weiß aber, welche Parameter er da unterbringen muss, kann, um dann quasi eine gültige URL zu bekommen.
Stefan Tilkov: Aber warum hilft mir das? Das ist doch eigentlich nur eine Indirektion. Dann bin ich doch einfach noch von was anderem abhängig.
Silvia Schreier: Du bist von was anderem abhängig, aber du erlaubst dem Server damit auch eine gewisse Eigenständigkeit, dass er sich nämlich ändern kann, dass er die URL-Struktur ändern kann, dass sich der Host womöglich dadrin einfach ändern kann. Das heißt, wenn ich jetzt anfange, plötzlich meine Anwendung zu zerlegen und auf zwei Hosts zu betreiben oder ein Archiv einzurichten für alte Rechnungen oder Kunden, die es nicht mehr gibt, dann ermögliche ich das durchaus auf diesem Wege. Aber wenn ich natürlich die hart kodiert drin stehen habe, die URL, dann kann ich das leider nicht machen.
Stefan Tilkov: Vielleicht ein Punkt als Abschluss, über den wir noch nicht gesprochen haben: das Thema Security ganz allgemein. Welche Möglichkeiten sind den gerade hip und in und schick, wenn man sich gerade bei REST APIs mit Security auseinander setzen möchte?
Martin Eigenbrodt: Vielleicht fange ich mal an mit den Dingen, die nicht hip und in sind. Man sollte sich vielleicht auf die Basics zurück besinnen, auch, und z. B. verstehen, dass es sowas wie Basic Authentication gibt. Und dass das, wenn ich verschlüsselte Kommunikation über SSL habe, durchaus eine Option sein kann, weil das einfach ist, weil das leicht zu verstehen ist. Das hat also einen geringen kognitiven Overhead. Und wenn ich mich in einigermaßen kontrollierten Umgebungen befinde, wo ich was über die Clients und über den Server weiß, ist das eine valide Wahl für REST APIs. Und hat eben auch keinen Overhead, einfach beim Request zu sagen “Ich bin der und der und das ist mein Passwort.”
Stefan Tilkov: Was gibt es sonst noch an hippen, schicken Sachen?
Oliver Wolf: Ja, ich weiß jetzt nicht, ob es wirklich hip und schick ist. Es ist ja auch nicht mehr ganz so jung, aber das, was man heute hier typischerweise tut, ist OAuth – in der Version 1.0 teilweise noch verbreitet, mittlerweile aber eher die Version 2.0, die deutlich vereinfacht worden ist, weil sie an ein paar Stellen auf Kryptografie verzichtet und sich einfach darauf verlässt, dass auf dem darunter liegenden Kanal sowas wie SSL benutzt wird. Das macht es dem Entwickler deutlich einfacher und hat sicherlich auch dazu beigetragen, dass mehr und mehr Services das nutzen. Im Kern geht es dabei darum, wenn ich beispielsweise einen API Client habe – also meinetwegen eine Mobilanwendung, die über die API auf irgendeine Website z. B. zugreifen soll, wo ich vielleicht Benutzeraccount habe – diesem Client einen Zugriff ermöglichen zu müssen, ohne meine Credentials – also sprich mein Username, mein Passwort – wirklich in dieser Mobilapp hinterlegen zu müssen. Das ist ein großer Vorteil. Das ganze passiert halt Token-basiert, das heißt, ich als Benutzer kann über die Webschnittstelle beispielsweise dieser Applikation Zugriffrechte geben – zeitlich begrenzt, vielleicht auch inhaltlich begrenzt vom Scope her – und der Client kann dann eben im Rahmen dieser Zugriffsrechte darauf zugreifen, ohne dass ich da jetzt entweder mein Passwort hinterlegen müsste oder es jedes Mal eingeben müsste. Das ist eigentlich das, was man typischerweise heute tut.
Silvia Schreier: Stimme ich dir voll und ganz zu. Und es gibt allerdings auch jede Menge Leute, die OAuth2 ein bisschen verteufeln und große Tiraden darüber geschrieben haben, einfach weil es viele Sachen auch im Unklaren lässt. Und damit zwei OAuth2 Implementierungen z. B. nicht mehr miteinander kompatibel sind, was natürlich schlecht ist, wenn ich mich da nicht auf irgendwas geeinigt habe. Und wenn man da etwas haben will, dann kann man sich z. B. OpenID Connect anschauen, was sozusagen OAuth2 ist. Eine quasi Spezifikation, eine OAuth2-konforme Spezifikation, die auch noch Authentifizierung mit abdeckt. Das heißt, wenn ich sowas gebrauchen kann, dann ist das durchaus eine Idee, das quasi zu nutzen, weil ich mich dann selber nicht mehr um gewisse Entscheidungen kümmern muss, die ich dann wohlmöglich auch noch falsch treffen würde.
Stefan Tilkov: Letzter Punkt vielleicht: wir haben ganz, ganz viel über Server gesprochen jetzt, über serverseitige Frameworks und über serverseitige APIs. Was ist denn mit dem armen Client?
Martin Eigenbrodt: Ich fürchte, das ist ein Gebiet, auf dem wir noch viel Entwicklung einfordern müssen, auf dem noch einiges passieren wird. Also erstmal bräuchten wir natürlich als Basis überhaupt einen vernünftigen HTTP-Client. Das heißt, der muss mit Dinge wie Redirects, konfigurierbar, der muss vielleicht sowas wie Caching sogar selber beherrschen. Das sind also diese Basics. Dann würde ich mir aber natürlich wünschen, dass ich vielleicht mehr als einen HTTP-Client habe, sondern dass ich einen Hypermedia-Client habe. Das heißt, einen Client, der Konzepte wie Links schon versteht und mir die Möglichkeit gibt, zu sagen “Folge doch bitte dem Link, den du unter dieser Relation findest und benutze dabei diesen Parameter, den man in diesem Link-Template vielleicht noch einsetzen kann.” Und solche Dinge gibt es, aber noch nicht fürchterlich weit verbreitet, und da sehe ich noch viel Potential. Denn diese Entkopplung, die wir versprechen im Grunde, zwischen dem Konsumenten und dem Server, die tritt erst dann ein, wenn tatsächlich der Client so gebaut ist, dass er dem Links folgt. Und wenn der Client so gebaut ist, dass der Entwickler sich ein Mal die Links angeguckt hat, sie auf Papier aufgeschrieben hat und dann in seinen Code getan hat, dann ist nichts entkoppelt und dann habe ich mir sehr viel Mühe auf dem Server gegeben und dabei nichts gewonnen.
Stefan Tilkov: Wenn du sagst, es gibt schon ein bisschen was, was wäre ein Beispiel für Dinge, die es schon gibt? [Pause] Ich sehe schon, diese Frage müssen wir eher streichen.
Martin Eigenbrodt: Diese Frage streichen wir.
Silvia Schreier: Also, ich wüsste nicht, dass es schon was wirklich fertiges gibt …
Martin Eigenbrodt: Wir haben was selber gebaut.
Silvia Schreier: …, was wir sofort unterschreiben, dass das super ist. Wir haben in einem Projekt selber so einen Client gebaut, also Martin und ich waren da beide irgendwie dran beteiligt und haben da versucht, die Idee, die Martin gerade beschrieben hat, also umzusetzen. Und das hat auch relativ gut funktioniert. Redirect-Support hatten wir in dem Fall leider auch noch nicht automatisch im Client mit drin. Da gibt es aber durchaus auch HTTP-Bibliotheken, die das unterstützen oder optional, wo man sagen kann “Ich will, dass du denen automatisch folgst.” Und Caching ist so das andere große Problem, weil eigentlich ist das nichts, worum ich mich selber kümmern möchte.
Stefan Tilkov: Du meinst clientseitig.
Silvia Schreier: Genau, dass ich mich clientseitig, so max-age
-Header
auswerten, das will ich eigentlich nicht von Hand machen. Es gibt aber durchaus
auch da Clients, die sowas wieder unterstützen, wenn ich ihnen sage, dass sie
das tun sollen. Und das müsste man noch vielleicht ein bisschen mehr bündeln
und noch ein bisschen mehr zeigen, wie das eigentlich wirklich geht und dann
eben diese Hypermedia-Unterstützung kombinieren. Es gibt aber durchaus
Bibliotheken zum Parsen natürlich von sowas wie HAL oder Siren oder was auch
immer. Also diese Mittel gibt es durchaus, aber das große
Hypermedia-Bundle-Client gibt es noch nicht.
Oliver Wolf: Wobei man auch da sagen muss, dass es da eben viele verschiedene Lösungen gibt, die alle im Detail sehr unterschiedlich sind. Also natürlich gibt es für HAL z. B. den HAL-Browser. Das ist im Prinzip ein JavaScript-basiertes Tool, um in HAL-Dokumenten zu navigieren. Und da gibt es auch eine wiederverwendbare JavaScript-Library, die man da benutzen kann. Aber es gibt eben nicht die Art von Standard-API für Hypermedia, die über verschiedene Plattformen, verschiedene Programmiersprachen hinweg mit einem halbwegs eindeutigem Konzept arbeitet. Sondern es gibt mal hier was und mal da was und man kann sich sicherlich für eins entscheiden und das dann benutzen, aber wenn man dann z. B. vor der Aufgabe steht, dass plötzlich jetzt mit einer anderen Sprache oder mit einer anderen Technologie realisieren zu müssen, dann fängt man letztendlich wieder von vorne an. Da haben sich also so gewisse einheitliche – also nehmen wir mal ein blödes Beispiel: wir alle finden die DOM-API nicht besonders gut, ne? Aber sie ist zumindest überall irgendwie gleich. Man weiß, wie man mit so einem DOM-Tree umgeht.
Stefan Tilkov: Gleich schlecht.
Oliver Wolf: Gleich schlecht, genau.
Stefan Tilkov: Überall gleich schlecht.
Oliver Wolf: Ja, aber sie ist überall gleich, ne? Und das ist eben in diesem Bereich überhaupt noch nicht so.
Stefan Tilkov: Ok. Wir sind für einen unserer Podcasts auch mittlerweile relativ lange unterwegs. Deswegen schlage ich vor, wir belassen es hierbei. Wer mehr wissen will, muss einfach unser Buch kaufen. Das Leben hat Härten, da müsst ihr jetzt einfach durch, liebe Zuhörer. Vielen Dank an euch für die Zeit, hat sehr viel Spaß gemacht. Danke auch nochmal fürs Mitschreiben und fürs Helfen dabei, dass dieses verfluchte Ding endlich raus kommt. Ich bin sehr froh drüber, danke euch und danke an die Zuhörer fürs Zuhören.