RESTful-Webservices (REST-API-Design)

Das Schaubild eines RESTful Webservices

Neben den bekannten WS-*-Stack (SOAP, WSDL, WS-*-Universum) gibt es noch weitere Möglichkeiten, einen Webservice zu implementieren. Dieses ist zum Beispiel der REST-Architekturstil. REST steht hier für REpresentational State Transfer. Dieser Beitrag führt in die maßgeblichen Prinzipien der RESTful-Webservices ein und beschreibt das Erstellen einer REST-API.

Der REST-Architekturstil

Die REST-Architekturstil wurde von Roy Thomas Fielding im Jahr 2000 in seiner Dissertation für verteilte Hypermedia Systeme formuliert. Roy Fielding ist einer der Hauptautoren der Spezifikation des Hypertext-Transfer Protokolls (HTTP/1.1, RFC 2616). Der REST-Architekturstil nutzt das HTTP-Protokoll vollständig – im Gegensatz zu den Webservices des WS-*-Stacks, die ein SOAP over HTTP-Protokoll einsetzen und das unterliegende HTTP-Protokoll nur rudimentär verwenden. Das SOAP-Protokoll wiederum basiert auf XML.

Die RESTful-Webservices

Der REST-Architekturstil wird bei der Integration oder der Kommunikation zwischen Anwendungen verwendet. Der Aufruf eines RESTful-Webservices wird nicht durch einen Anwender in einem Browser ausgelöst. Obwohl es bei einem Webservice per HTTP GET durchaus vorstellbar ist, die Daten als eine HTML-Seite zu präsentieren. Allerdings könnten aus einer Webanwendung heraus ein AJAX (Asynchronous JavaScript and XML) Aufruf gegen einen RESTful-Webservice erfolgen.

Die RESTful-Webservices sind statuslos und liefern die Daten in unterschiedliche Repräsentationen (Formate) an den Aufrufer. Die Daten werden in mit einer URI eindeutig identifiziert und als Ressource bezeichnet. Durch den statuslosen Zustand der Kommunikation können alle Caching Mechanismen von HTTP-Servern (Gültigkeitszeitraum, Validieren, ETag, etc.) verwendet werden. Das ist ein wesentliches Element des REST-Architekturstils.

In einer REST-Architektur wird der Aufrufer bzw. Client häufig als Consumer und die Gegenseite bzw. Server wird als Provider bezeichnet. Diese Begriffe sind dadurch entstanden, weil z. B. ein Server beide Seiten einer REST-Kommunikation einnehmen kann.

Ressourcen und ihre Repräsentationen (REST-API-Design)

Was ist eine Ressource?

Eine Ressource ist eine semantische Entität und wird über eine langlebige URI (Uniform Resource Identifier) identifiziert bzw. adressiert. Die URI ist im RFC 3986 definiert. Sie kann eine oder mehrere Repräsentationen (Datenformate, wie z. B. Text, XML, JSON, PDF, HTML, ATOM, RSS/RDF, etc.) besitzen.

Ein Beispiel ist die Abfrage einer Adresse oder Person, die als vCard (elektronische Visitenkarte, application/vcard, RFC 2426) geliefert wird.

Wie wird eine Ressource identifiziert (Aufbau der URI)?

Die ID einer Ressource, die URI, sagt nicht über die Verwendung oder eine Veränderung der Ressource aus. In der URI ist keine Informationen enthalten, die Auskunft darüber gibt, was mit der Ressource geschehen soll oder geschah.

Eine URI dient genau zur Identifizierung einer Ressource.

(1) https://api.frank-rahn.de/customers/4711
(2) https://api.frank-rahn.de/drivers/a33
(3) https://api.frank-rahn.de/products/1

Durch die erste URI (1) wird der Kunden mit der Kundennummer 4711 und mit der letzten URI (3) das Produkt mit der Produktnummer 1 identifiziert. In der Mitte (2) wird der Fahrer A33 identifiziert.

  • Tipp: Die Namen oder Bezeichner im URI-Pfad in Plural angeben.

Die Namen im URI-Pfad sollten immer in Plural angegeben werden. Dieses ist für Programmierer der REST-API einfacher umzusetzen. Werden diese URIs in einer Liste aufgeführt und sortiert, dann stehen die zusammengehörigen URIs zusammen.

Der hierarchische Aufbau einer URI ist nicht notwendig. Eine URI muss im Wesentlichen eine Ressource eindeutig identifizieren, dieses kann durchaus kryptisch erfolgen.

https://api.frank-rahn.de/things/a5s4711
  • Tipp: Keine Dateierweiterung in die URI.

Bei klassischen Webanwendungen werden Downloads überwiegend mit Links auf Dateien angeboten. Eine REST-API kennt keine künstlichen Dateierweiterungen in der URI. Das Format der Antwort wird in dem Header-Feld Content-Type kommuniziert.

Tipps für das URI-Design

In diesem Kapitel sind einige Tipps für den Entwurf von URIs für eine REST-API.

  • Tipp: URIs ohne abschließenden Schrägstrich.

Eine URI sollte nicht mit einem Schrägstrich / enden. Dieses zusätzliche Zeichen fügt der URI keinen semantischen Wert hinzu und sollte weggelassen werden.

Klassische Webanwendungen werden die folgenden URIs nicht unterscheiden. In einer REST-Architektur stellen die unterschiedlichen URIs zwei verschiedenen Ressourcen dar.

(1) https://api.frank-rahn.de/customers/4711
(2) https://api.frank-rahn.de/customers/4711/

Eine fehlertolerante Schnittstelle leitet die zweite URI (2) auf die erste URI (1) um.

  • Tipp: Bindestriche erhöhen die Lesbarkeit einer URI.

In einer URI können Bindestriche - verwendet werden, um die Lesbarkeit von URIs zu verbessern.

Leerzeichen und Unterstriche in einem Namen oder Bezeichner sollten durch Bindestriche ersetzt werden.

  • Tipp: Keine Unterstriche in der URI verwenden.

Eine URI wird in Browsern oder Editoren oft unterstrichen dargestellt. Dadurch können Unterstriche _ nicht erkannt und sollten durch Bindestriche ersetzt werden.

Ein eindeutiger Schlüssel (Primary Key) aus der Datenbank kann Teil der URI sein. Allerdings sollte eine Ressource nicht direkt einem Datensatz entsprechen. Sondern aus einem serviceorientiertem Entwurfes oder einem API-Design hervorgehen.

Die folgende URI ist ungültig, falls sie keine einzelne Ressource identifiziert, sondern eine Menge von Ressourcen.

https://api.frank-rahn.de/customers/1967/05

Die folgende URI ist gültig, wenn sie eine Liste von gleichen Ressource identifiziert und die URI die Liste als Ressource referenziert.

https://api.frank-rahn.de/customers/1967/05

Der Unterschied der beiden URIs liegt in der Bezeichnung des Ergebnisses. Die Liste von gleichen Ressourcen ist wiederum eine Ressource.

  • Tipp: Eine URI sollte kleingeschrieben werden.

Um Verwechselung von URIs zu vermeiden, sollte keine Großschreibung verwendet werden.

Das Protokoll und der Hostname in einer URL dürfen großgeschrieben werden – während beim Pfad zwischen Groß- und Kleinschreibung unterschieden wird. Aber auch das sollte unterlassen werden.

https://api.frank-rahn.de/drivers/a33
HTTPS://API.FRANK-RAHN.DE/drivers/a33
https://api.frank-rahn.de/drivers/a33
https://api.frank-rahn.de/Drivers/A33

Was sind verschachtelte Ressourcen?

Die Ressourcen können verschachtelt (nested resources) werden. Die verschachtelten Ressourcen sind eng gekoppelte Ressourcen im Sinne von Eltern-Kind-Beziehung (1:N). Die Kinder sind an ihren Eltern gebunden, so dass ihre Verwendung ohne Eltern keinen Sinn macht.

  • Tipp: Eine hierarchische Beziehung wird in der URI durch einen Schrägstrich angezeigt.

Das Verschachteln oder die Hierarchie der Ressourcen, wird in der URI mit einem Schrägstrich / ausgedrückt. Dieses erhöht die Übersichtlichkeit wie auch die Verständlichkeit der URI und beeinflusst die Identifizierung nicht.

https://api.frank-rahn.de/customers/4711/orders/1

In diesem Beispiel wird die Bestellung mit der Nummer 1 des Kunden mit der ID 4711 referenziert.

URIs mit Query-Parametern

Wenn eine URI eine Ressource identifiziert, die wiederum eine Liste von Ressourcen darstellt, können Query-Parametern zum Einsatz kommen.

https://api.frank-rahn.de/customers?search=Hans%20M%C3%BCller

Query-Parameter für die Suche (Searching)

Die Suche soll die Anzahl der angefragten Ressourcen in der zurückgegebenen Liste einschränken. Dazu wird ein Query-String angegeben. Dessen Syntax eine Übereinstimmung in den Ressourcen ermöglicht.

https://api.frank-rahn.de/customers?search=Hans%20M%C3%BCller
https://api.frank-rahn.de/customers?q=Hans%20M%C3%BCller
https://api.frank-rahn.de/customers?s=Hans%20M%C3%BCller

Query-Parameter für das Filtern (Filtering)

Das Filtern soll, wie die Suche, die Anzahl der angefragten Ressourcen in der zurückgegebenen Liste einschränken. Dazu werden einige Attribute der Ressourcen mit erwarteten Werten angegeben. Mehrere Werte werden mit Komma getrennt.

https://api.frank-rahn.de/customers?name=Rahn&city=K%C3%B6ln
https://api.frank-rahn.de/customers?keys=4711,4712

Query-Parameter für das Sortieren (Sorting)

Das Sortieren soll die Reihenfolge der abgefragten Ressourcen in der zurückgegebenen Liste beeinflussen. Der Sortierparameter enthält die Namen der Attribute, nach denen sortiert wird, getrennt durch ein Komma. Zusätzlich kann mit die Sortierung „+“ (Aufsteigend, Ascending) oder „-“ (Absteigend, Descending) gesteuert werden.

https://api.frank-rahn.de/customers?sort=+name,-age

Query-Parameter für die Paginierung (Paging)

Die Paginierung begrenzt die Anzahl der abgefragten Ressourcen in der zurückgegebenen Liste. Dazu kann die Liste in Seiten (Page) zerstückelt oder die Anzahl der Treffer (Limitation) limitiert werden.

https://api.frank-rahn.de/customers?page=0&count=20
https://api.frank-rahn.de/customers?page=1&size=20
https://api.frank-rahn.de/customers?page=2&per-page=20
https://api.frank-rahn.de/customers?limit=20

Query-Parameter für das Selektieren von Feldern

Mit diesem Parameter kann die Menge der zurückgelieferten Daten verringert werden. Dazu werden einzelne Attribute aus den Ressourcen ausgegrenzt. Mehrere Attribute werden mit Komma getrennt.

https://api.frank-rahn.de/customers?fields=firstname,name,age

Versionierung einer Ressource (URI Versioning)

Wie werden verschiedene Versionen von Ressourcen unterschieden? Hier bieten sich mehrere Strategien (API Strategy) an. Die Auswahl der Versionierungsstrategie sollte vor dem Einsatz der REST-API festgelegt werden. Eine nachträgliche Änderung ist meistens mit erheblichen Aufwänden verbunden. Vor allem, wenn sich bestehende bzw. permanente URIs ändern.

Zusätzlich müssen die folgenden Teile der Versionsinformationen betrachtet werden:

  • Major (Hauptversion)
  • Minor (Unterversion)
  • Patch (Bugfix)

Wann ist die Rückwärtskompatiblität einer Version gebrochen? Die Antwort auf diese Frage ist wichtig, wenn Ressourcen gecacht werden sollen. Da die verschiedenen Versionen eindeutig unterschieden werden müssen.

Einbetten der Version in die Basis-URI

Die Version wird Teil der Basis-URI (Base-URI). Diese Variante der Versionierung wird sehr häufig verwendet, da sie einfach umzusetzen ist.

(1) https://api.frank-rahn.de/customers/4711
(2) https://api.frank-rahn.de/v1/customers/4711
(3) https://api.frank-rahn.de/v1.0/customers/4711
(4) https://api.frank-rahn.de/v1.1/customers/4711

Konsequenzen:

  • Die URI ist von einem API Gateway einfach umzuleiten.
  • Die Änderung der Version verhindert eine permanente URL.
    Eine Versionierung einer Ressource bedeutet nicht die Änderung ihrer Identität, sondern eine Änderung in der Darstellung. Die URI und ihre Identität sollte dieselbe bleiben.
  • Wenn eine Version nicht mehr verwendet werden darf, muss beim Zugriff auf diese URI eine Umleitung auf eine gültige Ressource erfolgen. Dieses kann mit einem HTTP-Statuscode 3xx stattfinden. Leider kann die referenzierte Ressource eine geänderte Semantik besitzen.
  • Die Ressourcen mit diesen URIs können gecacht werden.
  • Wenn eine Ressource eine neue Version benötigt, bekommen alle Ressourcen unter dieser Basis-URI eine neue Version (Siehe die nächste Konsequenz).
  • Die URIs aus dem Beispiel identifizieren unterschiedliche Ressourcen, die ggf. gleich sind.
    • Bei der Beispiel-URI (1) ist es unklar, welche Version die Ressource besitzt.
    • Die Beispiel-URI (2) und (3) zeigen auf die gleiche Ressource, besitzen aber eine unterschiedliche Identität.
    • Die Beispiel-URI (4) und (3) können auf die gleiche Ressource zeigen, wenn die Version durch eine völlig andere Ressource erzwungen wurde (Siehe vorherige Konsequenz).
  • Wenn eine URI auf eine verschachtelte Ressource zeigt, müssen mehrere Versionen in der URI angegeben werden.
    https://api.frank-rahn.de/v1/customers/4711/v1.1/addresses/1

Einbetten der Version in den Query-Parameters

Die Version ist in einem Query-Parameter enthalten.

(5) https://api.frank-rahn.de/customers/4711
(6) https://api.frank-rahn.de/customers/4711?version=1
(7) https://api.frank-rahn.de/customers/4711?version=1.0
(8) https://api.frank-rahn.de/customers/4711?version=1.1

Neben den im vorherigen Kapitel betrachteten Konsequenzen, zeigen sich zusätzlich die folgenden Konsequenzen.

Konsequenzen:

  • Ein Query-Parameter steuert gewöhnlich die Suche bzw. Abfrage und nicht die Herausgabe einer einzelnen Ressource.
    Mit einem Query-Parameter kann die Herausgabe einer Liste von Ressourcen gesteuert werden.
  • Typischerweise wird eine Ressource (eine Liste von …), in deren URI ein Query-Parameter enthalten, ist nicht gecacht.
  • Die URIs aus dem Beispiel identifizieren unterschiedliche Ressourcen, die ggf. gleich sind.
    • Bei der Beispiel-URI (5) ist es unklar, welche Version die Ressource besitzt.
    • Die Beispiel-URI (6) und (7) zeigen auf die gleiche Ressource, besitzen aber eine unterschiedliche Identität.
    • Die Beispiel-URI (8) und (7) können auf die gleiche Ressource zeigen, wenn diese Version durch eine völlig andere Ressource erzwungen wurde.

Einbetten der Version in den MIME-Typ (Media Type Versioning)

Die Version ist Teil des MIME-Typs bzw. Media-Types. Dazu wird ein eigener MIME-Typ (RFC 6838: VND Content Type) definiert, der die Version enthält. Dieser MIME-Typ wird jeweils in der Anfrage im HTTP-Header Feld Accept und in der Antwort im HTTP-Header Feld Content-Type mitgegeben.

Accept: application/vnd.rahn.v1+json
Accept: application/vnd.rahn.v1.0+json
Accept: application/vnd.rahn.v1.1+json
Accept: application/vnd.rahn+json; version=1
Accept: application/vnd.rahn+json; version=1.0
Accept: application/vnd.rahn+json; version=1.1

Diese MIME-Typen können bei der IANA (Internet Assigned Numbers Authority) registriert werden: IANA-Application for a Media Type.

Neben den im vorherigen Kapitel betrachteten Konsequenzen, zeigen sich zusätzlich die folgenden Konsequenzen.

Konsequenzen:

  • Die Änderung der Version verhindert nicht eine permanente URL.
    Die URI aus den vorhergehenden Beispielen erzeugten immer eine neue Identität. Dieses ist bei dieser Variante nicht der Fall. Jede existierende URI zeigt immer auf die gleiche Ressource.
  • Wenn eine Ressource eine neue Version benötigt, muss nur ein neue MIME-Typ verwendet oder definiert werden.
    Alle anderen Ressourcen unter der gleichen Basis-URI sind nicht betroffen.
  • Die URI für eine verschachtelte Ressource wird klarer, da sie keinerlei Versionen enthält.
    https://api.frank-rahn.de/customers/4711/addresses/1
    Der MIME-Typ betrifft die konkret zurückgelieferte Ressource.
  • Das Cachen der Ressource ist anspruchsvoller, aber möglich.
  • Der MIME-Typ beschreibt normalerweise das Format und nicht die Version der Ressource.
  • Die Standard MIME-Typen werden nicht verwendet.
    Das kann zu Problemen führen, da einige Anwendungen mit spezifischen MIME-Typen nicht umgehen können. Aber ein spezifischer MIME-Typ kann semantische Informationen und Hinweise enthalten. Die bei der Verarbeitung der Ressource hilfreich sein können.

Einbetten der Version in den HTTP-Header (X-API-Version)

Die Version wird im HTTP-Header im Attribut X-API-Version festgelegt.

Beispiel einer Anfrage:

GET /customers/4711 HTTP/1.1
Host: api.frank-rahn.de 
X-API-Version: >=1.0, <2.0 
Accept: application/json 
...
HTTP/1.1 200 OK 
X-API-Version: 1.1 
...

Wenn der Header nicht gesetzt ist, wird die letzte Version der API verwendet. Alternativ kann der Provider auch einen HTTP-Statuscode 412 Precondition Failed senden.

HTTP/1.1 425 Precondition Failed 
...

Es gibt einige alternative Schreibweisen.

  • Version (Dieser Header wird schon verwendet)
  • API-Version
  • Accept-Version
  • {Vendor}-API-Version

Diese Versionierung ähnelt dem Verfahren aus dem vorherigen Kapitel. Die folgenden Konsequenzen müssen berücksichtigt werden.

Konsequenzen:

  • Die Standard MIME-Typen werden verwendet.
  • Es kann eine andere Version geliefert werden, als gewünscht war.
  • Der Header kann durch einen bösartigen Proxy entfernt werden.
  • Diese Lösung ist nicht Browser-freundlich und erzwingt eine spezielle Implementierung des Consumers.

Erweiterung von untergeordneten Ressourcen (Nested Resource Expansion)

Wenn eine Ressource abgefragt wird, kann sie untergeordnete Ressourcen beinhalten.

GET /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
Accept: application/json
...
{
  "firstname": "Frank",
  "name": "Rahn",
  "href": "https://api.frank-rahn.de/drivers/4711",
  "_expandable": {
    "cars": "https://api.frank-rahn.de/cars/k-fr-0001",
    "companies": "https://api.frank-rahn.de/companies/1"
  }
}

In diesem Beispiel werden die Autodaten nur verlinkt und müssen in einer zweiten Abfrage nachgelesen werden. In einigen Fällen werden die Autodaten aber direkt benötigt. Dann sollen diese in einer einzelnen Abfrage gelesen werden (Eager Loading). Dazu steht der _expand Parameter zur Verfügung.

In folgendem Beispiel werden die Autodaten direkt durch den _expand=car Parameter mitgeladen.

GET /drivers/4711?_expand=car HTTP/1.1
Host: api.frank-rahn.de
Accept: application/json
...
{
  "firstname": "Frank",
  "name": "Rahn",
  "href": "https://api.frank-rahn.de/drivers/4711",
  "_expandable": {
    "cars": {
      "registration": "K-FR 1",
      "vendor": ...,
      "href": "https://api.frank-rahn.de/cars/k-fr-0001"
    },
    "companies": "https://api.frank-rahn.de/companies/1"
  }
}

Dieses reduziert die Anzahl der API-Aufrufe sowie den Traffic zum API-Server.

Weitere Beispiele:

Die Content Negotiation

Eine alternative Repräsentation einer Ressource wird durch die Content Negotiation zu Verfügung gestellt.

Die Antwort einer REST-Anfrage kann auf unterschiedlichen Content Anforderungen reagieren. Dazu wird das HTTP-Header Feld Accept: text/plain ausgewertet und die Repräsentation in gewünschten Format in der Antwort (HTTP-Header Feld Content-Type: test/plain) berücksichtigt werden. Allerdings ist zu Beachten, dass diese Anforderung als ein Wunsch betrachtet wird und die Antwort anders aussehen kann.

Ein detailliertes Beispiel ist im Abschnitt Content Negotiation zu finden.

Hypermedia (Verlinkung)

Unter REST werden die Verweise (Links) auf andere Ressourcen mit URIs dargestellt. Diese Verweise werden auch mit Hyperlinks, Hypermedia, Verlinkung oder als Verknüpfung bezeichnet.

<?xml version="1.0" encoding="UTF-8"?>
<driver href="https://api.frank-rahn.de/drivers/a33">
  <name>Rahn</name>
  <firstname>Frank</firstname>
  <company href="https://api.frank-rahn.de/companies/1" />
  <cars>
    <car href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </cars>
</driver>
<?xml version="1.0" encoding="UTF-8"?>
<driver xmlns:atom="http://www.w3.org/2005/Atom">
  <name>Rahn</name>
  <firstname>Frank</firstname>
  <links>
    <atom:link rel="self" href="https://api.frank-rahn.de/drivers/a33" />
    <atom:link rel="company" href="https://api.frank-rahn.de/companies/1" />
    <atom:link rel="car" href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </links>
</driver>
customer=https://api.frank-rahn.de/customers/4711
bank=Musterbank AG
account=https://api.frank-rahn.de/banks/de/37010099/accounts/0123456789
{
  "driver": {
    "href": "https://api.frank-rahn.de/drivers/a33",
    "cars": {
      "car": {
        "href": "https://api.frank-rahn.de/cars/k-fr-0001"
      }
    },
    "company": {
      "href": "https://api.frank-rahn.de/companies/1"
    },
    "firstname": "Frank",
    "name": "Rahn"
  }
}
{
  "firstname": "Frank",
  "name": "Rahn",
  "_links": { 
    "self": {
      "href": "https://api.frank-rahn.de/drivers/a33"
    }
  },
  "_embedded": {
    "cars": [
      "car": {
        "_links": {
          "self": {
            "href": "https://api.frank-rahn.de/cars/k-fr-0001"
          }
        }
      }
    ],
    "company": {
      "_links": {
        "self": {
          "href": "https://api.frank-rahn.de/companies/1"
        }
      }
    }
  }
}

Mit diesen URIs kann direkt zwischen den Ressourcen navigiert werden. Zusätzlich können z. B. Distributed Caching realisiert werden, welche erst durch die URIs und die Hyperlinks möglich sind.

<?xml version="1.0" encoding="UTF-8" ?>
<driverservice href="https://api.frank-rahn.de">
  <link rel="drivers" href="https://api.frank-rahn.de/drivers" />
  <link rel="cars" href="https://api.frank-rahn.de/cars" />
  <link rel="companies" href="https://api.frank-rahn.de/companies" />
  <link rel="banks" href="https://api.frank-rahn.de/banks" />
</driverservice>

Diese Beschreibung von Services kann auch im HTTP-Header (RFC 5988 – Web Linking) platziert werden.

HTTP/1.1 200 OK
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Link: <https://api.frank-rahn.de/users/4711>; rel="self"; title="this"
Link: <https://api.frank-rahn.de/drivers>; rel="drivers"
Link: <https://api.frank-rahn.de/cars>; rel="cars"
Link: <https://api.frank-rahn.de/companies>; rel="companies"
Link: <https://api.frank-rahn.de/banks>; rel="banks"
...

Wobei diese Möglichkeit meistens bei Navigation bei Listen angewendet wird.

HTTP/1.1 200 OK
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Link: <https://api.frank-rahn.de/page/3/>; rel="canonical"
Link: <https://api.frank-rahn.de/>; rel="first"
Link: <https://api.frank-rahn.de/page/2/>; rel="previous"
Link: <https://api.frank-rahn.de/page/3/>; rel="self"; title="this"
Link: <https://api.frank-rahn.de/page/4/>; rel="next"
Link: <https://api.frank-rahn.de/page/7/>; rel="last"
...

Gleichförmige (uniforme) Schnittstellen

Der REST-Architekturstil vereinheitlicht (uniforme) die Schnittstellen der Ressourcen auf eine überschaubare und – bezüglich des zu erwartenden Verhaltens – standardisierte Menge von Vorgängen.

Diese Vorgänge sind Teil des Anwendungsprotokolls HTTP/1.1 (RFC 2616).

HTTP-Methoden

Eine HTTP-Methode definiert einen beabsichtigten Vorgang, der auf eine Ressource ausgeführt wird. Ein Vorgang kann eine Ressource abrufen, verändern oder löschen (Interaktionen).

Die HTTP-Methoden werden auch Verben oder Operationen genannt.

Zurzeit werden im Internet nur die HTTP-Methoden GET und POST genutzt, da nur sie von den Browsern unterstützt werden.

Aber es gibt noch weitere HTTP-Methoden, wie z. B. PUT und DELETE, die in einer REST-Architektur verwendet werden können.

Die am häufigsten verwendeten HTTP-Methoden sind GET, PUT, DELETE und POST, es gibt aber auch andere Methoden wie PATCH, HEAD, OPTIONS, TRACE und CONNECT.

Die Eigenschaften von HTTP-Methoden

  • safe
    Der Aufruf dieser Operation hat keine Nebenwirkungen, d. h. die Ressource erfährt durch den Abruf keine Änderung. Das heißt aber nicht, dass der Webservice intern eine Zustandsänderung vorgenommen hat. Dieses können Logeinträge oder das Fortschreiben von statistischen Aufzeichnungen sein. Wichtig aus Sicht des Architekturstils REST ist es, dass für den Consumer die Ressource sich nicht geändert hat.
  • idempotent
    Das mehrfache Aufrufen dieser Operation führt immer zum gleichen Ergebnis.
    Mathematisch: ƒ(ƒ(x)) = ƒ ∘ ƒ(x) = ƒ(x) 😉
    Wenn nun der Consumer keine Antwort auf eine Anfrage erhalten hat, kann er diese Anfrage bei idempotenten Operationen einfach wiederholen. Er muss nicht prüfen, ob die Operation schon verarbeitet worden ist, das muss er nur bei den nicht idempotenten Operationen.

HTTP-Methode GET

Die Anforderung einer Ressource, die durch eine URI identifiziert wird, ohne das die Ressource dadurch eine Veränderung erfährt. Der Provider liefert die Repräsentation einer Ressource.

Diese HTTP-Methode GET ist safe und idempotent.

GET /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
Accept: application/xml
...
HTTP/1.1 200 OK
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Last-Modified: Tue, 11 Sep 2007 19:43:31 GMT+1
Etag: "701d69fe-131-477f657c8529b"
Content-Language: de
Content-Type: application/xml
Content-Length: 284
 
<?xml version="1.0" encoding="UTF-8"?>
<driver id="https://api.frank-rahn.de/drivers/4711">
  <name>Rahn</name>
  <firstname>Frank</firstname>
  <company href="https://api.frank-rahn.de/companies/1" />
  <cars>
    <car href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </cars>
</driver>

Query-Parameter dürfen nur verwendet werden, wenn das Ergebnis eine eindeutige identifizierte Ressource ist.

GET /math/functions/sin?angle=3 HTTP/1.1
Host: api.frank-rahn.de
Accept: text/plain
...

Dieses ist meistens der Fall, wenn das Ergebnis selbst als Ressource gewertet wird, z. B. eine Liste von Ressourcen oder das Ergebnis einer Berechnung unter der Beachtung der Eigenschaften safe und idempotent.

Der folgende Aufruf ist nicht zulässig, da dieser Aufruf nicht safe und nicht idempotent ist. Wird diese Anfrage wiederholt an einen Provider gesendet, so unterscheiden sich im folgenden Beispiel die Antworten.

GET /drivers?id=4711&action=delete HTTP/1.1
Host: api.frank-rahn.de
Accept: text/html
...

Durch die Eigenschaften safe und idempotent können Bookmarks bzw. Caches relativ einfach aufgebaut werden, da der wiederholte Aufruf keinen Schaden anrichten kann. Die Verantwortung dazu liegt nicht bei Consumer, sondern ausschließlich beim Provider.

Einschränkungen:

  • Die Länge einer URL ist begrenzt. Zu viele Daten in der URL können zu Kürzungen, Fehlern oder Sicherheitslücken führen. Es wird empfohlen, die Länge in angemessenen Grenzen zu halten und alternative Methoden (z. B. die HTTP-Methode POST) für große Nutzlasten in Betracht zu ziehen.
  • Da die Daten in der URL offengelegt werden, ist es wichtig, die Aufnahme von sensiblen Informationen in die Query-Parameter zu vermeiden. Hier muss die EU-DSGVO berücksichtigt werden. Diese Daten können mit der HTTP-Methode POST in den Payload der Anfrage verschoben werden.

HTTP-Methode PUT

Die Anfrage der HTTP-Methode PUT aktualisiert die bestehende identifizierte Ressource mit den mitgelieferten Daten. Sollte die Ressource noch nicht existieren, wird sie unter der URI angelegt.

Die Ressource wird vom Consumer in einer gültigen Repräsentation gesendet und ersetzt die bestehende Ressource.

Die HTTP-Methode PUT ist idempotent. Eine teilweise Aktualisierung der Ressource wird mit der HTTP-Methode PATCH erreicht.

PUT /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
Content-Type: application/xml
Content-Length: 242
...

<?xml version="1.0" encoding="UTF-8"?>
<driver>
  <name>Rahn</name>
  <firstname>Frank</firstname>
  <company href="https://api.frank-rahn.de/companies/1" />
  <cars>
    <car href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </cars>
</driver>
HTTP/1.1 201 Created
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
...

Einschränkungen:

  • Mit dieser Methode kann die Ressource nicht teilweise aktualisiert werden – immer nur vollständig.

HTTP-Methode PATCH

Die Anfrage der HTTP-Methode PATCH modifiziert nur einen Teil der angegebenen Ressource. Gegenüber der HTTP-Methode PUT wird die Ressource nicht komplett überschrieben. Diese HTTP-Methode ist im RFC 5789 (PATCH Method for HTTP) beschrieben.

Die HTTP-Methode PATCH ist weder safe noch idempotent.

PATCH /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
Content-Type: application/xml
...

<?xml version="1.0" encoding="UTF-8"?>
<driver>
  <firstname>Martin</firstname>
</driver>
HTTP/1.1 204 No Content
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Last-Modified: Tue, 11 Sep 2007 19:43:31 GMT+1 
Etag: "701d69fe-131-477f657c8529b"
...
HTTP/1.1 200 OK
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Last-Modified: Tue, 11 Sep 2007 19:43:31 GMT+1
Etag: "701d69fe-131-477f657c8529b"
Content-Language: de
Content-Type: application/xml
Content-Length: 284
 
<?xml version="1.0" encoding="UTF-8"?>
<driver id="https://api.frank-rahn.de/drivers/4711">
  <name>Rahn</name>
  <firstname>Martin</firstname>
  <company href="https://api.frank-rahn.de/companies/1" />
  <cars>
    <car href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </cars>
</driver>

HTTP-Methode DELETE

Das Löschen bzw. das Entfernen der identifizierten Ressource. Falls die Ressource nicht existiert, wird kein Fehler ausgelöst, da das gewünschte Ergebnis schon erreicht ist.

Um eine bestimmte Ressource zu löschen, muss die Ressource mit der URL eindeutig identifiziert werden können.

Es ist von entscheidender Bedeutung, die Genauigkeit und Integrität des Mechanismus zur Identifizierung der Ressourcen sicherzustellen, um ein versehentliches Löschen anderer Ressourcen zu verhindern.

Nach dem Verarbeiten der HTTP-Methode DELETE liefert die HTTP-Methode GET ein HTTP/1.1 404 Not Found.

Ob die Ressource tatsächlich aus der Datenbank gelöscht oder nur als gelöscht bzw. storniert markiert wurde, liegt in der Verantwortung des Providers bzw. der zugrundeliegenden Fachlichkeit. Die Ressource darf nur nicht mehr unter der ursprünglichen URI geliefert werden.

Die HTTP-Methode DELETE ist idempotent.

Das mehrfache Löschen darf keinen Fehler liefern und die Ressource darf von außen nicht mehr erreicht werden.

DELETE /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
...
HTTP/1.1 204 No Content
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
...
GET /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
...
HTTP/1.1 404 Not Found
Date: Tue, 11 Sep 2007 19:44:31 GMT+1
Server: Apache/2.2
...

Einschränkungen:

  • In manchen Fällen kann das Löschen einer Ressource kaskadierende Auswirkungen auf zugehörige Ressourcen haben. Es ist wichtig, das Verhalten und mögliche kaskadierende Aktionen im Design und in der Dokumentation der API zu beschreiben.

HTTP-Methode POST

Es werden durch die POST-Methode Daten zur Verarbeitung an den Provider gesendet. Es können eine oder mehrere Ressourcen geändert, erzeugen oder gelöscht werden. Die zugehörigen Daten hängen der Anfrage an (Payload). Wenn eine neue Ressource erzeugt wird, wird die entsprechenden URI in der Antwort per Location Attribut zurückgegeben.

Diese HTTP-Methode POST bietet die meiste Flexibilität und kann bzw. darf Seiteneffekte haben, da sie weder safe noch idempotent ist.

Der Consumer hat eine gewisse Verantwortung, da die HTTP-Methode POST keine Garantien liefert. Der Consumer sollte also wissen, was er anstellt.

POST /drivers HTTP/1.1
Host: api.frank-rahn.de
Content-Type: application/xml
Content-Length: 242
...
 
<?xml version="1.0" encoding="UTF-8"?>
<driver>
  <name>Rahn</name>
  <firstname>Frank</firstname>
  <company href="https://api.frank-rahn.de/companies/1" />
  <cars>
    <car href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </cars>
</driver>
HTTP/1.1 200 OK
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Last-Modified: Tue, 11 Sep 2007 19:43:31 GMT+1
Etag: "701d69fe-131-477f657c8529b"
Location: https://api.frank-rahn.de/drivers/4712
...

Einschränkungen:

  • Das wiederholte Senden der gleichen Anfrage kann zu unbeabsichtigten Nebenwirkungen führen. Es ist wichtig, bei der Verarbeitung der Daten die Datenintegrität gewährleistet wird.
  • POST-Methoden dürfen nicht gecacht werden.

HTTP-Methode HEAD

Die HTTP-Methode HEAD fragt den HTTP-Header zu der identifizierten Ressource ab. Diese Anfrage liefert den gleichen Header, wie die HTTP-Methode GET, nur ohne Daten.

Die HTTP-Methode HEAD ist safe und idempotent.

HEAD /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
...
HTTP/1.1 204 No Content
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Last-Modified: Tue, 11 Sep 2007 19:43:31 GMT+1
Etag: "701d69fe-131-477f657c8529b"
Content-Language: de
Content-Type: application/xml
Content-Length: 284

HTTP-Methode OPTIONS

Die HTTP-Methode OPTIONS prüfen, welche HTTP-Methoden auf der identifizierten Ressource zur Verfügung stehen.

Die HTTP-Methode OPTIONS ist idempotent.

OPTIONS /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
...
HTTP/1.1 200 OK
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Allow: GET,HEAD,POST,OPTIONS,TRACE
Content-Length: 0
Content-Type: text/plain

HTTP-Methode TRACE

Die HTTP-Methode TRACE liefert die Anfrage so zurück, wie der Provider sie empfangen hat. So kann überprüft werden, ob und wie die Anfrage auf dem Weg zum Provider verändert worden ist.

Die HTTP-Methode TRACE ist idempotent.

TRACE /drivers/4711 HTTP/1.1
Host: api.frank-rahn.de
...
HTTP/1.1 200 OK
...

HTTP-Methode CONNECT

Diese HTTP-Methode CONNECT wird von Proxyservern implementiert, die in der Lage sind, SSL Tunnel zur Verfügung zu stellen.

HTTP-Statuscodes

Die Antwort eines RESTful-Webservices beinhaltet einen HTTP-Statuscode und ggf. die angeforderte Ressource. In den folgenden Kapiteln werden die wichtigsten Statuscodes für RESTful-Webservices beschrieben.

HTTP-Statuscodes 2xx

Mit einem HTTP-Statuscode aus der 200-Gruppe wird ein Erfolg signalisiert.

  • 200 OK
    Signalisiert den Erfolg eines Zugriffes oder Änderung.
  • 201 Created
    Bestätigt das Anlegen einer Ressource.
  • 204 No Content
    Bestätigt eine Änderung, liefert aber keine Daten zurück.

HTTP-Statuscodes 3xx

Der HTTP-Statuscode aus der 300-Gruppe leiten die Bearbeitung an den Consumer zurück.

  • 301 Moved Permanently
    Die Ressource hat eine andere Identität angenommen. Die neue URI befindet sich im HTTP-Attribut Location.
  • 303 See Other
    Verweis auf eine andere Ressource. Diese URI befindet sich im HTTP-Attribut Location.

HTTP-Statuscodes 4xx

Mit einem HTTP-Statuscode aus der 400-Gruppe signalisiert der Provider, dass er die Anfrage nicht interpretieren oder durchführen konnte. Wobei der Fehler durch den Consumer ausgelöst wurde.

  • 400 Bad Request
    Die Anfrage konnte vom Webservice aufgrund einer fehlerhaften Syntax nicht verstanden werden. Der Consumer muss die Anfrage korrigieren.
  • 401 Unauthorized
    Die Anfrage enthielt keine Informationen zur Authentifizierung oder mit den gelieferten Informationen kann keine Authentifizierung durchgeführt werden.
  • 403 Forbidden
    Die Ausführung der Anfrage wurde wegen fehlender Berechtigungen verweigert.
  • 404 Not Found
    Die URI ist ungültig. Sie referenziert keine Ressource.
  • 405 Method Not Allowed
    Die URI referenziert eine bekannte Ressource, aber die Methode kann auf diese Ressource nicht angewendet werden.
  • 409 Conflict
    Die Anfrage wurde unter einer falschen Annahme gestellt. Bei PUT: Die Ressource wurde zwischenzeitlich geändert.
  • 410 Gone
    Die Ressource war unter der URI zu finden, wird aber hier nicht mehr bereitgestellt.
  • 412 Precondition Failed
    Eine in der Anfrage übertragene Voraussetzung wurde nicht erfüllt.
  • 415 Unsupported Media Type
    Der Content einer Anfrage wurde mit einem nicht erlaubten Format übertragen.
  • 422 Unprocessable Entity
    Der Content der Anfrage konnte nicht verarbeitet werden, z. B. durch semantische Fehler.

HTTP-Statuscodes 5xx

Ein HTTP-Statuscode aus der 500-Gruppe zeigt einen Fehler im Webservice an.

  • 500 Internal Server Error
    Ein allgemeiner Fehler im Webservice bzw. Provider ist aufgetreten.

Die Beschreibungen der restlichen Statuscodes gibt es bei der Wikipedia.

Content Negotiation

Die Antwort auf eine REST-Anfrage kann unterschiedliche Repräsentationen bzw. Content Formate liefern. Dazu wird das HTTP-Header-Feld Accept ausgewertet und aus dieser Wunschliste eine Repräsentation für die Antwort (HTTP-Header-Feld: Content-Type) ausgewählt. Dieser Vorgang wird Content Negotiation genannt. Hier entscheidet letztlich der RESTful-Webservice, welche Repräsentation er liefert.

Dabei stehen alle möglichen MIME-Typen zur Verfügung (text/plain, text/html, text/xml, text/rdf, text/rss, text/x-vcard, application/xml, application/json, application/pdf, …).

In der Form application/vnd.frankrahn.drivers+xml kann auf einen nicht standardisierten XML MIME-Typ verwiesen werden.

Syntax ::= "application/vnd." <Hersteller> "." <XML-Schema> "+xml" (BNF)

Im folgenden Beispiel kann eine XML- oder eine HTML-Repräsentation in der Antwort geliefert werden, dabei ist die XML-Repräsentation höher priorisiert (q=1.0) und die Version (schemaVerion=1.1) des zu verwendenden XML-Schemas festgelegt.

GET /customers/4711/orders HTTP/1.1
Host: api.frank-rahn.de
Accept: application/xml;schemaVersion=1.1;q=1.0, text/html;q=0.5
Accept-Language: de;q=1.0, en;q=0.7
...

Der RESTful-Webservice liefert die angeforderte Ressource als eine XML-Repräsentation.

HTTP/1.1 200 OK
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Last-Modified: Tue, 11 Sep 2007 19:43:31 GMT+1
Etag: "701d69fe-131-477f657c8529b"
Content-Language: de
Content-Type: application/xml; charset=utf-8
Content-Length: 284
 
<?xml version="1.0" encoding="UTF-8"?>
<driver id="https://api.frank-rahn.de/drivers/4711">
  <name>Rahn</name>
  <firstname>Frank</firstname>
  <company href="https://api.frank-rahn.de/companies/1" />
  <cars>
    <car href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </cars>
</driver>

Mit der folgenden Antwort zeigt der RESTful-Webservice an, dass er die Ressource nicht in einer der gewünschten Repräsentationen liefern kann.

HTTP/1.1 406 Not Acceptable
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
...

Distributed Caching (Validation/Expiry)

Um die Effizienz von Anwendungen zu steigern, werden häufig Caches eingesetzt. Bei einer REST-Architektur können die Ressourcen mit etablierten Verfahren des Anwendungsprotokolls HTTP gecacht werden.

Dazu bietet das HTTP-Protokoll einige Attribute im Zusammenhang mit dem Distributed Caching an:

  • Last-Modified: Zeitstempel
    Wird vom Webservice in der Antwort geliefert und ermöglicht das Caching erst.
  • If-Modified-Since: Zeitstempel
    Wird bei einer erneuten Anfrage gesetzt und nur, falls die Ressource nach diesem Datum verändert worden ist, wird sie auch gesendet.
  • ETag: "Entity-Tag"
    Wird vom Webservice mit der Antwort geliefert.
  • If-None-Match: "Entity-Tag"
    Wird bei einer erneuten Anfrage gesetzt und falls der aktuelle Entity-Tag der Ressource nicht passt, wird sie gesendet.

Im folgenden Beispiel wird eine Ressource abgefragt …

GET /customers/4711/orders HTTP/1.1
Host: api.frank-rahn.de
Accept: application/xml;schemaVersion=1.1;q=1.0, text/html;q=0.5
Accept-Language: de;q=1.0, en;q=0.7
...

… und auch erfolgreich geliefert.

HTTP/1.1 200 OK
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Last-Modified: Tue, 11 Sep 2007 19:43:31 GMT+1
Etag: "701d69fe-131-477f657c8529b"
Content-Language: de
Content-Type: application/xml; charset=utf-8
Content-Length: 284
 
<?xml version="1.0" encoding="UTF-8"?>
<driver href="https://api.frank-rahn.de/drivers/4711">
  <name>Rahn</name>
  <firstname>Frank</firstname>
  <company href="https://api.frank-rahn.de/companies/1" />
  <cars>
    <car href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </cars>
</driver>

In einer späteren Abfrage der gleichen Ressource wird das HTTP-Attribut If-Modified-Since mitgeliefert …

GET /customers/4711/orders HTTP/1.1
Host: api.frank-rahn.de
Accept: application/xml;schemaVersion=1.1;q=1.0, text/html;q=0.5
Accept-Language: de;q=1.0, en;q=0.7
If-Modified-Since: Tue, 11 Sep 2007 19:43:31 GMT+1
...

… und die Antwort liefert die angeforderte Ressource nicht mehr, da sie aktuell ist.

HTTP/1.1 304 Not Modified
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Etag: "701d69fe-131-477f657c8529b"
...

Dieses Verfahren wird erst durch die Eigenschaften safe und idempotent der HTTP-Methode GET ermöglicht, da der Abruf einer Ressource, die Ressource selber, nicht verändern darf.

Asynchrone Kommunikation

Standardmäßig ist die Kommunikation mit dem HTTP-Protokoll durch den Ablauf des Request/Response Zyklus synchronisiert. Allerdings kann durch den HTTP-Statuscode HTTP/1.1 202 Accepted und der Rückgabe einer URI im HTTP-Attribut Location für das Ergebnis eine asynchrone Kommunikation aufgebaut werden.

Der HTTP-Statuscode besagt, dass die Anfrage zu einem späteren Zeitpunkt bearbeitet wird und unter der angegebenen URI abgeholt werden kann.

POST /drivers HTTP/1.1
Host: api.frank-rahn.de
Content-Type: application/xml
Content-Length: 242
...
 
<?xml version="1.0" encoding="UTF-8"?>
<driver>
  <name>Rahn</name>
  <firstname>Frank</firstname>
  <company href="https://api.frank-rahn.de/companies/1" />
  <cars>
    <car href="https://api.frank-rahn.de/cars/k-fr-0001" />
  </cars>
</driver>

Die Antwort enthält einen Verweis auf die erzeugte Ressource.

HTTP/1.1 202 Accepted
Date: Tue, 11 Sep 2007 19:43:31 GMT+1
Server: Apache/2.2
Location: https://api.frank-rahn.de/drivers/4712
...

Die erfolgreiche Ausführung des Webservices wird allerdings nicht garantiert. Eine vorschnelle Abfrage GET /drivers/4712 HTTP/1.1 wird ein HTTP/1.1 404 Not Found liefern.

Reliable Messaging

Wenn eine Anfrage an einen Service-Provider gesendet wird, aber nie eine Antwort zurückkommt, kann man sich nicht sicher sein, dass die Anfrage tatsächlich angekommen ist. Eine Lösung kann durch das wiederholte Senden erreicht werden. Dieses kann bei idempotenten HTTP-Methoden ohne Bedenken durchgeführt werden. Aber bei den HTTP-Methoden, die nicht idempotent sind, müssen zusätzliche Mechanismen (z. B. Message-Id, Zeitstempel, …) angewendet werden, so dass der Service-Provider doppelte Anfragen erkennen kann.

Cookies

Als Cookies werden Textinformationen bezeichnet, die von Webserver auf dem Computer des Benutzers über den Browser beständig gespeichert werden. Darin werden z. B. Passwörter und Angaben über den aktuellen Benutzer abgelegt. In einer späteren Sitzung werden die Cookies direkt an den Webserver gesendet.

Die Cookies sind in einer REST-Architektur nur zulässig, wenn sie allgemeine Informationen, wie z. B. Tokens, Tickets oder Session-Ids, bei Aufrufen von Webservices transportieren.

Redirection, Compression, Chunking

Die HTTP-Eigenschaft Redirection leitet mit einem HTTP-Statuscodes 3xx an eine andere URI weiter. Diese Umleitung kann permanent sein oder zeitlich begrenzt.

Durch die HTTP-Eigenschaft Compression kann der Consumer eine Kompression der Antwort wünschen. Er liefert in der Anfrage im HTTP-Attribut Accept-Encoding die möglichen Komprimierungsverfahren mit. Der Webservice kann sich ein Verfahren aus der Liste aussuchen und verwenden. Dieses zeigt er im HTTP-Attribut Content-Encoding an. Falls er kein geeignetes Verfahren findet, komprimiert er die Antwort nicht.

Die HTTP-Eigenschaft Chunking teilt eine Anfrage oder Antwort in mehrere Teile auf. Dieses wird mit dem HTTP-Attribut Transfer-Encoding: chunked angezeigt. Durch das Aufteilen können große Datenmengen besser versendet werden. Dieses Verfahren kann auch für Streaming verwendet werden, wenn ein kontinuierlicher Fluss von Daten (Datenstrom) gesendet werden muss.

Beispiele von RESTful-Webservice Schnittstellen

Die Schnittstellen eines RESTful-Webservice müssen formal definiert werden. Dieses kann beispielsweise über eine WSDL, ein XML Schema (XSD) oder eine beliebige Beschreibungssprache erfolgen.

Im folgenden Beispiel wird die RESTful-Webservice Schnittstelle einer Kundenverwaltung dargestellt.

Ein weiteres Beispiel ist der Beitrag Spring mit RESTful-Webservice.

Schnittstelle zu den Kunden
URI /customers
POST Erzeuge einen neuen Kunden.
GET Liefert eine Liste mit alle Kunden. Die Parameter beeinflussen das Ergebnis und können miteinander kombiniert werden.

Query-Parameters:
  • search={Zeichenkette}
    Liefere nur die Kunden, die dem Suchkriterium entsprechen (Filter).
  • state=open-orders
    Liefere nur die Kunden mit offene Bestellungen (Filter).
  • keys={Liste von Kundennummern}
    Liefert eine Liste von Kunden zurück, deren Kundennummer in der Komma separierten Liste enthalten sind (Filter).
  • page={Seitenummer: 1}
    Liefere nur die angegebene Seite mit Kunden (Pagination).
  • count={Anzahl: 20}
    Legt die Anzahl der Treffer pro Seite fest (Pagination).
  • sort={Sortierung}
    Sortiere die Kunden nach dem angegebenen Kriterium (Sortierung).
  • fields={Liste von Felder}
    Schränke die zurückgelieferten Felder des Kunden ein (Felder).
PUT
DELETE
HEAD
Schnittstelle zu einem bestimmten Kunden
URI /customers/{Kundennummer}
POST
GET Liefere den Kunden mit der Kundennummer.
PUT Ändere den Kunden mit der Kundennummer.
DELETE Lösche den Kunden mit der Kundennummer.
HEAD
Schnittstelle zu den Bestellungen eines bestimmten Kunden
URI /customers/{Kundennummer}/orders
POST Erzeuge eine neue Bestellung des Kunden mit der Kundennummer.
GET Listet alle Bestellungen des Kunden mit der Kundennummer auf.
PUT
DELETE Lösche alle Bestellungen des Kunden mit der Kundennummer.
HEAD
Schnittstelle zu einer einzelnen Bestellung eines bestimmten Kunden
URI /customers/{Kundennummer}/orders/{Bestellungsnummer}
/orders/{Bestellungsnummer}
POST
GET Liefere die Bestellung des Kunden.
PUT Ändere die Bestellung des Kunden.
DELETE Lösche die Bestellung des Kunden.
HEAD
Schnittstelle zu einer speziellen Bestellung eines Kunden
URI /customers/{Kundennummer}/orders/date/{Bestellungsdatum}
POST
GET Liefere die Bestellungen des Kunden mit dem Datum.
PUT
DELETE
HEAD

Unter dem Link URI Template (RFC 6570) finden Sie eine Beschreibung, wie URIs mit Variablen zu definieren sind.

Zustandslose Kommunikation

Die Kommunikation mit einem RESTful-Webservice erfolgt immer zustandslos, d. h. der Provider verwaltet keinen Kontext über die Interaktion mit einem Consumer. Dadurch ergeben sich erhebliche Vorteile für die Skalierung und Ausfallsicherheit solcher Systeme, da diese Systeme auf mehrere Provider verteilt werden können. Es können auch zusätzliche Dienste, wie HTTP-Proxies oder Browser-Cache, für die Steigerung der Performanz dazwischen geschaltet werden.

Es wird zwischen den zwei Zuständen Anwendungs- und Ressourcenzustand unterschieden.

Der komplexe Anwendungszustand existiert nur auf dem Consumer. Durch eine Repräsentation einer Ressource wird der Consumer in einen Anwendungszustand versetzt.

Der Zustand der Ressource wird ausschließlich auf dem Provider verwaltet. Es erfolgt kein Abgleich zwischen den Zuständen. Der Provider verwaltet keine speziellen Daten (z. B. im Session-Kontext per Cookies) zu einem Consumer. Dieser muss bei einer Anfrage alle notwendigen Daten mitgeben oder die Daten (z. B. ein Warenkorb) werden in einer eigenen (temporären?) Ressourcen zwischen gespeichert.

Somit kann ein Provider zwischen zwei Aufrufen durch gestartet werden, ohne dass dieses eine Auswirkung hat oder eine Behinderung darstellt.

Die Literaturempfehlung

Frank Rahn
Letzte Artikel von Frank Rahn (Alle anzeigen)
0 Kommentare

Hinterlasse einen Kommentar

An der Diskussion beteiligen?
Hinterlasse uns deinen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Ihre E-Mail-Adresse wird nicht veröffentlicht. Ihr Kommentar wird verschlüsselt an meinen Server gesendet. Erforderliche Felder sind mit * markiert.

Weitere Informationen und Widerrufshinweise finden Sie in meiner Datenschutzerklärung.