Representational State Transfer (REST)

From
Jump to navigation Jump to search

In den frühen 1990ern war das Web von einer einfachen Logik geprägt, Dokumente in einem bestimmten Format die sich eindeutig identifizieren konnten und sich über diese Identifikation referenzierten, sowie ein einfaches Protokoll zum übertragen der Dokumente. Das reichte nicht mehr aus als das Internet dynamischer wurde und man Datenbankinhalte oder Inhalte, die auf mehr oder weniger komplizierten Berechnungen beruhten, abrufen konnte. Dadurch wurde unklar ob eine bestimmte URL eine Datei oder einen Dienst, der viele Dateien oder Informationen liefern kann, anspricht. Seit 1994 beschäftigte sich dann Roy Fieldings mit dieser Problemstellung und entwarf in seiner Dissertation<ref>Roy Thomas Fielding: Architectural Styles and the Design of Network-based Software Architectures. Abgerufen am 6. Mai 2018(englisch)</ref> ein Architekturstil der sich bis heute zum Industriestandard entwickelt hat. In seiner Architektur nennt Fieldings 6 Prinzipien (Constraints) die es einzuhalten gilt um einen REST oder RESTful Service zu erstellen.

Rest-Constraints

Client-Server

Die einheitliche Schnittstelle trennt die Daten-Schicht von der Benutzer-Schnittstelle. Diese Trennung bedeutet, dass beispielsweise Clients sich nicht mit Datenspeicherung befassen, die intern auf dem Server verbleibt, so dass die Portabilität des Client-Codes verbessert wird. Server befassen sich nicht mit der Benutzerschnittstelle oder dem Benutzerstatus, sodass Server einfacher und besser skalierbar sind. Server und Clients können auch unabhängig ersetzt und entwickelt werden, solange die Schnittstelle nicht geändert wird.

Stateless

Die Kommunikation zwischen Client und Server hat Zustandslos zu erfolgen. Hierzu muss jede Anfrage eines Clients alle nötigen Informationen zur Beantwortung beinhalten und ohne Vorwissen über vorangegangene Anfragen vom Server ausgewertet und beantwortet werden können. Das bedeutet auch, dass der Client alle für die Kommunikation nötigen Zustände selbst verwaltet. Bei Wiederholung einer Anfrage wird somit immer die gleiche Antwort vom Server erwartet. Dieses erhöht die Skalierbarkeit, da Anfragen auf mehrere Server verteilt werden können ohne dass ein Server den Zustand des anderen Servers kennen muss. Bei verteilten Servern ist natürlich besondere Vorsicht geboten wenn zum Beispiel nach einer Änderungsoperationen lesend auf den inkonsistente Zustand zugegriffen wird.

Cache

Daten in einer Server-Antwort sollen explizit oder implizit als Cache-fähig oder -unfähig markiert werden. Die Verwendung eines Zwischenspeichers (Cache) auf Client-Seite steigert die Systemkapazität und die vom Benutzer empfundene Geschwindigkeit, da gleiche Anfragen mit Cache-fähigen Antworten nicht mehrfach an den oder die Server gestellt werden. Beim Cachen ist natürlich sehr genau abzuwägen welche Daten sich zum Cachen eignen. Es besteht die Gefahr sich ungewollte Effekte einzuhandeln, wie zum Beispiel durch die Verwendung veralteter Messwerte in einem sehr dynamischen Regelkreislauf. Cachen wird im Allgemeinen auch immer einen höheren Bedarf an Speicherplatz auf der Client-Seite erfordern.

Layered System

Für Clients soll nicht ersichtlich sein, ob diese direkt zum eigentlichen Server verbunden sind, oder nur zu einer Schnittstelle, die lediglich Zugriff auf die REST-API bietet. Dadurch kann ein Server mehrschichtig aufgebaut werden, wobei die unteren Schichten dem Clienten verborgen bleiben. Dies ermöglicht es weiterhin, die Struktur des Servers zu verändern, ohne dass bestehende REST-Anfragen angepasst werden müssen, solange die obere Schicht unverändert bleibt.

Uniform Interface

Dieses Constraint fasst vier Eigenschaften zusammen, deren gemeinsames Ziel es ist, eine einfache Nutzung der Schnittstelle zu gewährleisten:

Resource identification in requests:

Ressourcen einer REST-Schnittstelle sollen einheitlich über URIs (im Internet URLS) ansprechbar sein, und durch ihre jeweilige URI eindeutig identifizierbar sein.

Resource manipulation through representations:

Ressourcen können in einer REST-Antwort unterschiedlich repräsentiert werden - verbreitet sind JSON, XML oder auch CSV. Sämtliche dieser Repräsentationen sollen ermöglichen,eine Ressource zu bearbeiten oder zu löschen.

Self-descriptive messages:

Diese Eigenschaft greift das "statelessness"-Constraint auf und besagt, dass der Inhalt der Nachrichten so wie er ist ("as is"), also ohne weitere Informationen von außen, weiterverarbeitet werden sollen kann. Solche Nachrichten werden auch als kontextfrei bezeichnet.

Hypermedia As The Engine Of Application State (HATEOAS):

Laut Roy Fielding, dem Autoren der ursprünglichen REST-Spezifikation, ist dies die wichtigste aller REST-Eigenschaften. Dennoch wird sie von vielen Entwicklern missachtet. Die Idee hinter HATEOAS ist, dass Repräsentationen von Ressourcen jeweils auch immer Links mitliefern, die die weitere Bearbeitung der Ressource ermöglichen. Wenn HATEOAS korrekt implementiert wird müssen die genauen URLS der Rest-Anfragen nicht mehr hart in der Client-Application kodiert sein, sondern können direkt aus der vorhergehenden Antwort übernommen werden.<ref>https://spring.io/understanding/HATEOAS Abgerufen am 6. Mai 2018 (englisch)</ref>

Code on Demand:

Dieses optionale Constraint besagt, dass REST-Schnittstellen auch ermöglichen sollten, als Antwort auf API-Anfragen Code zurückzuliefern, der dann von der Client-Anwendung weiterverarbeitet werden kann. Anwendung findet dies beispielsweise bei dynamischen Java-Applets, die dann auf Webseiten eingebettet werden können.

Beispiel REST:

Domain Informationen

Um Informationen über eine bestimmte IP-Adresse oder Domain zu ermitteln, bietet ip-api.comeine RESTful-API an. Dazu stellt der Client zunächst eine reguläre GET-Anfrage an den Server, die Implementierung dabei hängt von der Art und Programmiersprache der Client-Anwendung ab. In python beispielsweise bietet das Modul urllib eine einfache Bibliothek für Internetkommunikation. Alternativ ist es auch möglich, die Anfrage einfach in die Adresszeile eines regulären Internetbrowsers zu kopieren, und dann die unformatierte Antwort im Browserfenster zu begutachten.<ref>API Dokumentation http://ip-api.com/docs/#ip_geolocation_api Abgerufen am 6.Mai 2018 (englisch) </ref>

http://ip-api.com/json/141.20.5.218

In diesem REST-Request ist das Objekt unserer Anfrage (141.20.5.218) als Teil der URL kodiert. Gerade bei Anfragen mit mehrerern Parametern (v.A., wenn beispielsweise auch ein API-Key erforderlich ist) werden die Parameter häufig auch als GET-Parameter übermittelt, die mit einem `?` von dem Rest der URL und mit `&` voneinander getrennt sind.

Wird dieser Request (mit der IP-Adresse der Humboldt-Universität) gesendet, könnte die Antwort folgendermaßen aussehen:

{"as":"AS680 Verein zur Foerderung eines Deutschen Forschungsnetzes e.V.","city":"Berlin","country":"Germany","countryCode":"DE","isp":"Humboldt-Universitaet zu Berlin","lat":52.5167,"lon":13.4,"org":"Humboldt-Universitaet zu Berlin","query":"141.20.5.218","region":"BE","regionName":"Land Berlin","status":"success","timezone":"Europe/Berlin","zip":"12529"}

Hierbei sind sämtliche Informationen im JSON-Format kodiert, was eine leichte Weiterverarbeitung der Ergebnisse ermöglicht.

Wetter API

ür aktuelle Wetterdaten, stellt zum Beispiel openweathermap.com eine umfangreiche RestfulAPI zur Verfügung. Genau wie im ersten Beispiel muss der Client an den Server eine GET-Anfrage mit den vereinbarten Parametern übersenden. In diesem Fall erhält die GET-Anfrage die URL sowie die Parameter Stadt, Ländercode und den API Key.

https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22

Mit dieser Anfrage werden die Wetterdaten von London abgefragt und ebenfalls als Teil der URL kodiert. Anders als im ersten Beispiel werden die Parameter mit einem q vom Rest der URL getrennt: Die Trennung der unterschiedlichen Parameter erfolgt wieder mit einem &.

Als Antwort liefert der Server folgende Daten standardmäßig im JSON Format zurück:

  {"coord":{"lon":-0.13,"lat":51.51},"weather":[{"id":300,"main":"Drizzle","description":"light intensity drizzle","icon":"09d"}],"base":"stations","main": 
  {"temp":280.32,"pressure":1012,"humidity":81,"temp_min":279.15,"temp_max":281.15},"visibility":10000,"wind":{"speed":4.1,"deg":80},"clouds":{"all":90},"dt":1485789600,"sys": 
  {"type":1,"id":5091,"message":0.0103,"country":"GB","sunrise":1485762037,"sunset":1485794875},"id":2643743,"name":"London","cod":200}

Quellen