Versionierung einer REST-API

Versionierung einer REST-API

1. Das Problem

Evolving a REST API ist ein schwieriges Problem, für das viele Optionen verfügbar sind. Dieser Artikel beschreibt einige dieser Optionen.

Weitere Lektüre:

Entdecken Sie die Spring Boot TestRestTemplate

Erfahren Sie, wie Sie mit dem neuen TestRestTemplate in Spring Boot eine einfache API testen.

Read more

REST API mit Jersey und Spring

Aufbau von Restful Web Services mit Jersey 2 und Spring.

Read more

2. Was steht im Vertrag?

Vor allem müssen wir eine einfache Frage beantworten:What is the Contract between the API and the Client?

2.1. URIs Bestandteil des Vertrags?

Betrachten wir zunächstthe URI structure of the REST API - ist das Teil des Vertrags? Sollten Kunden Lesezeichen setzen, fest programmieren und sich im Allgemeinen auf URIs der API verlassen?

Wenn dies der Fall ist, wird die Interaktion des Clients mit dem REST-Service nicht mehr vom Service selbst gesteuert, sondern von denRoy Fielding callsout-of-band-Informationen:

Eine REST-API sollte ohne Vorkenntnisse hinter der ursprünglichen URI (Lesezeichen) und einer Reihe standardisierter Medientypen eingegeben werden, die für die beabsichtigte Zielgruppe geeignet sind.

Also klarURIs are not part of the contract! Der Client sollte nur einen einzigen URI kennen - den Einstiegspunkt in die API. Alle anderen URIs sollten beim Verwenden der API ermittelt werden.

2.2. Medientypen Bestandteil des Vertrages?

Was ist mit den Medientypinformationen, die für die Darstellung von Ressourcen verwendet werden - sind diese Teile des Vertrags zwischen dem Kunden und dem Service?

In order to successfully consume the API, the Client must have prior knowledge of these Media Types. Tatsächlich repräsentiert die Definition dieser Medientypen den gesamten Vertrag.

Daher sollte sich der REST-Service hier am meisten konzentrieren:

Eine REST-API sollte fast den gesamten beschreibenden Aufwand für die Definition der Medientypen verwenden, die zur Darstellung von Ressourcen und zur Steuerung des Anwendungsstatus verwendet werden, oder für die Definition erweiterter Beziehungsnamen und / oder hypertextfähiger Markierungen für vorhandene Standardmedientypen.

DieMedia Type definitions are part of the contract und sollten daher Vorkenntnisse für den Client sein, der die API verwendet. Hier setzt die Standardisierung an.

Wir haben jetzt eine gute Vorstellung davon, was der Vertrag ist. Fahren wir fort mit der tatsächlichen Lösung des Versionsproblems.

3. Hochrangige Optionen

Lassen Sie uns nun die allgemeinen Ansätze zur Versionierung der REST-API diskutieren:

  • URI Versioning - Version des URI-Bereichs mithilfe von Versionsindikatoren

  • Media Type Versioning - Version der Darstellung der Ressource

When we introduce the version in the URI space, the Representations of Resources are considered immutable. Wenn also Änderungen in die API eingeführt werden müssen, muss ein neuer URI-Bereich erstellt werden.

Angenommen, eine API veröffentlicht die folgenden Ressourcen - Benutzer und Berechtigungen:

http://host/v1/users
http://host/v1/privileges

Nehmen wir nun an, dass für eine grundlegende Änderung der API vonusersdie Einführung einer zweiten Version erforderlich ist:

http://host/v2/users
http://host/v2/privileges

When we version the Media Type and extend the language, we go through Content Negotiation based on this header. Die REST-API verwendet benutzerdefiniertevendor MIME media types anstelle von generischen Medientypen wieapplication/json. Wir werden diese Medientypen anstelle der URIs versionieren.

Zum Beispiel:

===>
GET /users/3 HTTP/1.1
Accept: application/vnd.myname.v1+json
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.myname.v1+json
{
    "user": {
        "name": "John Smith"
    }
}

Wir können diese‘Custom Media Types for Rest APIs' article für weitere Informationen und Beispiele zu diesem Thema überprüfen.

Es ist wichtig zu verstehen, dassthe client makes no assumptions about the structure of the responseüber dem liegt, was im Medientyp definiert ist.

Aus diesem Grund sind generische Medientypen nicht ideal. Diesedo not provide enough semantic information und die Verwendung durch den Client erfordern zusätzliche Hinweise, um die tatsächliche Darstellung der Ressource zu verarbeiten.

Eine Ausnahme bildet die Verwendung einer anderen Methode zur eindeutigen Identifizierung der Semantik des Inhalts, z. B. eines XML-Schemas.

4. Vorteile und Nachteile

Nachdem wir nun ein klares Konzept der Vertragsbestandteile zwischen dem Kunden und dem Service sowie einen allgemeinen Überblick über die Optionen zur Versionierung der API haben, wollen wir die Vor- und Nachteile der einzelnen Ansätze erörtern.

Erstensintroducing version identifiers in the URI leads to a very large URI footprint. Dies liegt an der Tatsache, dass jede Änderung in einer der veröffentlichten APIs einen völlig neuen Repräsentationsbaum für die gesamte API einführt. Im Laufe der Zeit wird dies zu einer Belastung für die Wartung und zu einem Problem für den Kunden, der nun mehr Optionen zur Auswahl hat.

Version identifiers in the URI ARE also severely inflexible. Es gibt keine Möglichkeit, die API einer einzelnen Ressource oder einer kleinen Teilmenge der gesamten API einfach weiterzuentwickeln.

Wie bereits erwähnt, ist dies ein Alles-oder-Nichts-Ansatz. Wenn ein Teil der API auf die neue Version verschoben wird, muss die gesamte API mit verschoben werden. Dies macht auch ein Upgrade von Clients von v1 auf v2 zu einem wichtigen Unterfangen - was zu langsameren Upgrades und viel längeren Verfallszeiten für die alten Versionen führt.

HTTP-Caching ist auch bei der Versionierung ein wichtiges Anliegen.

Aus der Sicht von Proxy-Caches in der Mitte hat jeder Ansatz Vor- und Nachteile. Wenn der URI versioniert ist, muss der Cache mehrere Kopien jeder Ressource enthalten - eine für jede Version der API. Dies belastet den Cache und verringert die Cache-Trefferquote, da unterschiedliche Clients unterschiedliche Versionen verwenden.

Außerdem funktionieren einige Mechanismen zur Ungültigmachung des Cache nicht mehr. Wenn der Medientyp derjenige ist, der versioniert ist, müssen sowohl der Client als auch der Service dieVary HTTP header unterstützen, um anzuzeigen, dass mehrere Versionen zwischengespeichert werden.

Abperspective of client caching erfordert die Lösung, die den Medientyp versioniert, jedoch etwas mehr Arbeit als die, bei der URIs die Versionskennung enthalten. Dies liegt daran, dass es einfach einfacher ist, etwas zwischenzuspeichern, wenn sein Schlüssel eine URL als ein Medientyp ist.

Beenden wir diesen Abschnitt mit der Definition einiger Ziele (direkt ausAPI Evolution):

  • Halten Sie kompatible Änderungen von Namen fern

  • Vermeiden Sie neue Hauptversionen

  • macht Änderungen abwärtskompatibel

  • Denken Sie an die Vorwärtskompatibilität

5. Mögliche Änderungen an der API

Als nächstes betrachten wir die Arten von Änderungen an der REST-API - diese werden hier vorgestellt:

  • Darstellungsformat ändert sich

  • Ressourcenänderungen

5.1. Hinzufügen zur Darstellung einer Ressource

Die Formatdokumentation des Medientyps sollte unter Berücksichtigung der Aufwärtskompatibilität erstellt werden. Insbesondere sollte ein Client Informationen ignorieren, die er nicht versteht (was JSON besser macht als XML).

Nunadding information in the Representation of a resource will not break existing clients if these are correctly implemented.

Um unser früheres Beispiel fortzusetzen, ist das Hinzufügen vonamount in der Darstellung vonuser keine bahnbrechende Änderung:

{
    "user": {
        "name": "John Smith",
        "amount": "300"
    }
}

5.2. Entfernen oder Ändern einer vorhandenen Darstellung

Removing, renaming or generally restructuring information in the design of existing representations is a breaking change for clients. Dies liegt daran, dass sie das alte Format bereits verstehen und sich darauf verlassen.

Hier kommt Content Negotiation ins Spiel. Für solche Änderungen giltwe can add a new vendor MIME media type.

Fahren wir mit dem vorherigen Beispiel fort. Angenommen, wir möchten diename deruser infirstname undlastname aufteilen:

===>
GET /users/3 HTTP/1.1
Accept: application/vnd.myname.v2+json
<===
HTTP/1.1 200 OK
Content-Type: application/vnd.myname.v2+json
{
    "user": {
        "firstname": "John",
        "lastname": "Smith",
        "amount": "300"
    }
}

Insofern stellt dies eine inkompatible Änderung für den Kunden dar - er muss die neue Repräsentation anfordern und die neue Semantik verstehen. Der URI-Bereich bleibt jedoch stabil und wird nicht beeinflusst.

5.3. Wichtige semantische Änderungen

These are changes in the meaning of the Resources, the relations between them or what the map to in the backend. Für diese Art von Änderungen ist möglicherweise ein neuer Medientyp erforderlich, oder es muss eine neue Geschwisterressource neben der alten veröffentlicht und eine Verknüpfung verwendet werden, um darauf zu verweisen.

Während dies so klingt, als würden Versionskennungen in der URI erneut verwendet, besteht der wichtige Unterschied darin, dass die neue Ressourceis published independently of any other Resources in the APInicht die gesamte API im Stammverzeichnis teilt.

The REST API should adhere to the HATEOAS constraint. Demnach sollten die meisten URIs von Clients entdeckt und nicht fest codiert werden. Das Ändern eines solchen URI sollte nicht als inkompatible Änderung angesehen werden. Der neue URI kann den alten ersetzen, und Clients können den URI erneut erkennen und weiterhin funktionieren.

Es ist jedoch anzumerken, dass die Verwendung von Versionskennungen in der URI aus all diesen Gründen problematisch ist,it is not un-RESTfuljedoch in keiner Weise.

6. Fazit

Dieser Artikel versuchte einen Überblick über das sehr vielfältige und schwierige Problem vonevolving a REST Service zu geben. Wir erörterten die beiden gemeinsamen Lösungen, die Vor- und Nachteile der einzelnen Lösungen und die Möglichkeiten, diese Ansätze im Kontext von REST zu bewerten.

Der Artikel schließt mit der Begründung für die zweite Lösung -versioning the media types, während die möglichen Änderungen an einer RESTful-API untersucht werden.

Die vollständige Implementierung dieses Tutorials finden Sie inGitHub project.

7. Weitere Lektüre

In der Regel sind diese Lese-Ressourcen im gesamten Artikel verlinkt, aber in diesem Fall gibt es einfach zu viele gute: