Dies ist eine gute und knifflige Frage. Das Thema URI-Design ist gleichzeitig der wichtigste Teil einer REST-API und daher ein potenziell langfristiges Engagement gegenüber den Benutzern dieser API .
Da die Entwicklung einer Anwendung und in geringerem Maße ihrer API eine Tatsache des Lebens ist und sogar der Entwicklung eines scheinbar komplexen Produkts wie einer Programmiersprache ähnelt, sollte das URI-Design weniger natürliche Einschränkungen aufweisen und beibehalten werden im Laufe der Zeit . Je länger die Lebensdauer der Anwendung und der API ist, desto größer ist das Engagement für die Benutzer der Anwendung und der API.
Andererseits ist eine andere Tatsache im Leben, dass es schwierig ist, alle Ressourcen und ihre Aspekte vorherzusehen, die durch die API verbraucht würden. Glücklicherweise ist es nicht erforderlich, die gesamte API zu entwerfen, die bis zur Apokalypse verwendet wird . Es reicht aus, alle Ressourcenendpunkte und das Adressierungsschema jeder Ressource und Ressourceninstanz korrekt zu definieren.
Im Laufe der Zeit müssen Sie möglicherweise neue Ressourcen und neue Attribute zu jeder bestimmten Ressource hinzufügen. Die Methode, mit der API-Benutzer auf eine bestimmte Ressource zugreifen, sollte sich jedoch nicht ändern, sobald ein Ressourcenadressierungsschema öffentlich und damit endgültig wird.
Diese Methode gilt für die HTTP-Verbsemantik (z. B. sollte PUT immer aktualisiert / ersetzt werden) und für HTTP-Statuscodes, die in früheren API-Versionen unterstützt werden (sie sollten weiterhin funktionieren, damit API-Clients, die ohne menschliches Eingreifen gearbeitet haben, weiterhin funktionieren können so wie das).
Da die Einbettung der API-Version in die URI das Konzept von Hypermedia als Motor des Anwendungsstatus (in der Dissertation von Roy T. Fieldings angegeben) durch eine Ressourcenadresse / URI stören würde, die sich im Laufe der Zeit ändern würde, würde ich diese API schließen Versionen sollten nicht lange in Ressourcen-URIs aufbewahrt werden. Dies bedeutet, dass Ressourcen-URIs, auf die sich API-Benutzer verlassen können, Permalinks sein sollten .
Sicher, es ist möglich, die API-Version in den Basis-URI einzubetten, aber nur für vernünftige und eingeschränkte Zwecke wie das Debuggen eines API-Clients , der mit der neuen API-Version funktioniert. Solche versionierten APIs sollten zeitlich begrenzt sein und nur begrenzten Gruppen von API-Benutzern (wie bei geschlossenen Betas) zur Verfügung stehen. Ansonsten verpflichten Sie sich, wo Sie nicht sollten.
Einige Gedanken zur Wartung von API-Versionen mit Ablaufdatum. Alle Programmierplattformen / -sprachen, die üblicherweise zur Implementierung von Webdiensten verwendet werden (Java, .NET, PHP, Perl, Rails usw.), ermöglichen die einfache Bindung von Webdienstendpunkten an einen Basis-URI. Auf diese Weise ist es einfach , eine Sammlung von Dateien / Klassen / Methoden zu sammeln und getrennt von verschiedenen API-Versionen zu halten .
Mit dem POV der API-Benutzer ist es auch einfacher, mit einer bestimmten API-Version zu arbeiten und diese zu binden, wenn dies offensichtlich ist, jedoch nur für eine begrenzte Zeit, dh während der Entwicklung.
Mit dem POV des API-Betreuers ist es einfacher, verschiedene API-Versionen parallel zu verwalten, indem Quellcodeverwaltungssysteme verwendet werden, die vorwiegend mit Dateien als kleinste Einheit der (Quellcode-) Versionierung arbeiten.
Bei API-Versionen, die in URI deutlich sichtbar sind, gibt es jedoch eine Einschränkung: Man könnte diesen Ansatz auch ablehnen, da der API-Verlauf im URI-Design sichtbar / aparent wird und daher im Laufe der Zeit Änderungen unterliegt, die gegen die Richtlinien von REST verstoßen. Genau!
Um diesen vernünftigen Einwand zu umgehen, müssen Sie die neueste API-Version unter dem versionlosen API-Basis-URI implementieren. In diesem Fall können API-Client-Entwickler Folgendes auswählen:
Entwickeln Sie gegen die neueste Version (verpflichten Sie sich, die Anwendung so zu warten, dass sie vor eventuellen API-Änderungen geschützt ist, die den schlecht gestalteten API-Client beschädigen könnten ).
an eine bestimmte Version der API binden (was offensichtlich wird), jedoch nur für eine begrenzte Zeit
Wenn API v3.0 beispielsweise die neueste API-Version ist, sollten die folgenden beiden Aliase sein (dh sich für alle API-Anforderungen identisch verhalten):
http: // shonzilla / api / customers / 1234
http: // shonzilla / api /v3.0 / customers / 1234
http: // shonzilla / api / v3 / customers / 1234
Darüber hinaus sollten API-Clients, die weiterhin versuchen, auf die alte API zu verweisen, über die Verwendung der neuesten vorherigen API-Version informiert werden, wenn die von ihnen verwendete API-Version veraltet ist oder nicht mehr unterstützt wird . Zugriff auf eine der veralteten URIs wie diese:
http: // shonzilla / api /v2.2 / customers / 1234
http: // shonzilla / api /v2.0 / customers / 1234
http: // shonzilla / api / v2 / customers / 1234
http: // shonzilla / api /v1.1 / customers / 1234
http: // shonzilla / api / v1 / customers / 1234
sollte einen der 30x HTTP-Statuscodes zurückgeben, die die Umleitung angeben , die in Verbindung mit dem Location
HTTP-Header verwendet wird, der zur entsprechenden Version des Ressourcen-URI umleitet, die noch diese sein muss:
http: // shonzilla / api / customers / 1234
Es gibt mindestens zwei HTTP-Statuscodes für die Umleitung, die für API-Versionsszenarien geeignet sind:
301 Wird permanent verschoben, um anzuzeigen , dass die Ressource mit einem angeforderten URI dauerhaft in einen anderen URI verschoben wird (dies sollte ein Permalink für eine Ressourceninstanz sein, der keine API-Versionsinformationen enthält). Dieser Statuscode kann verwendet werden, um eine veraltete / nicht unterstützte API-Version anzuzeigen und den API-Client darüber zu informieren, dass ein versionierter Ressourcen-URI durch einen Ressourcen-Permalink ersetzt wurde .
302 Gefunden , um anzuzeigen , dass sich die angeforderte Ressource vorübergehend an einem anderen Speicherort befindet, während der angeforderte URI möglicherweise noch unterstützt wird. Dieser Statuscode kann nützlich sein, wenn die URIs ohne Version vorübergehend nicht verfügbar sind und eine Anforderung unter Verwendung der Umleitungsadresse wiederholt werden sollte (z. B. Verweisen auf den URI mit eingebetteter APi-Version), und wir möchten Clients anweisen, ihn weiterhin zu verwenden (dh die Permalinks).
Weitere Szenarien finden Sie im Kapitel Redirection 3xx der HTTP 1.1-Spezifikation
410 Gone
, da eine Umleitung möglicherweise darauf hinweist, dass der neue Speicherort kompatibel ist, wenn dies nicht der Fall ist. Wenn die API lediglich veraltet ist, aber noch vorhanden ist, kann einWarning
HTTP-Header in der Antwort eine Option sein.Die URL sollte NICHT die Versionen enthalten. Die Version hat nichts mit der "Idee" der Ressource zu tun, die Sie anfordern. Sie sollten versuchen, sich die URL als Pfad zum gewünschten Konzept vorzustellen - nicht als Rückgabe des Elements. Die Version schreibt die Darstellung des Objekts vor, nicht das Konzept des Objekts. Wie bereits auf anderen Postern erwähnt, sollten Sie das Format (einschließlich der Version) im Anforderungsheader angeben.
Wenn Sie sich die vollständige HTTP-Anforderung für die URLs mit Versionen ansehen, sieht dies folgendermaßen aus:
Die Kopfzeile enthält die Zeile, die die gewünschte Darstellung enthält ("Accept: application / xml"). Dort sollte die Version hingehen. Jeder scheint die Tatsache zu beschönigen, dass Sie möglicherweise dasselbe in verschiedenen Formaten möchten und dass der Kunde in der Lage sein sollte, nach dem zu fragen, was er möchte. Im obigen Beispiel fordert der Client JEDE XML-Darstellung der Ressource an - nicht wirklich die wahre Darstellung dessen, was er will. Der Server könnte theoretisch etwas zurückgeben, das nichts mit der Anforderung zu tun hat, solange es sich um XML handelt, und es müsste analysiert werden, um zu erkennen, dass es falsch ist.
Ein besserer Weg ist:
Nehmen wir weiter an, die Clients halten das XML für zu ausführlich und möchten jetzt stattdessen JSON. In den anderen Beispielen müssten Sie eine neue URL für denselben Kunden haben, damit Sie am Ende Folgendes erhalten:
(oder etwas ähnliches). Tatsächlich enthält jede HTTP-Anforderung das gesuchte Format:
Mit dieser Methode haben Sie viel mehr Gestaltungsfreiheit und halten tatsächlich an der ursprünglichen Idee von REST fest. Sie können Versionen ändern, ohne Clients zu stören, oder Clients schrittweise ändern, wenn die APIs geändert werden. Wenn Sie die Unterstützung einer Darstellung beenden möchten, können Sie auf die Anforderungen mit HTTP-Statuscode oder benutzerdefinierten Codes antworten. Der Client kann auch überprüfen, ob die Antwort im richtigen Format vorliegt, und das XML validieren.
Es gibt viele andere Vorteile und ich diskutiere einige davon hier in meinem Blog: http://thereisnorightway.blogspot.com/2011/02/versioning-and-types-in-resthttp-api.html
Ein letztes Beispiel, um zu zeigen, wie schlecht das Einfügen der Version in die URL ist. Nehmen wir an, Sie möchten Informationen innerhalb des Objekts und haben Ihre verschiedenen Objekte versioniert (Kunden sind v3.0, Bestellungen sind v2.0 und shipto object ist v4.2). Hier ist die böse URL, die Sie im Client angeben müssen:
quelle
-x
da es von RFC6648 veraltet ist .Wir fanden es praktisch und nützlich, die Version in die URL einzufügen. Auf einen Blick können Sie leicht erkennen, was Sie verwenden. Wir verwenden Alias / foo bis / foo / (neueste Versionen), um die Verwendung zu vereinfachen, kürzere / sauberere URLs usw., wie aus der akzeptierten Antwort hervorgeht.
Die Abwärtskompatibilität für immer aufrechtzuerhalten, ist oft unerschwinglich und / oder sehr schwierig. Wir bevorzugen eine frühzeitige Benachrichtigung über die Ablehnung, Weiterleitungen wie hier vorgeschlagen, Dokumente und andere Mechanismen.
quelle
Ich bin damit einverstanden, dass die Versionierung der Ressourcendarstellung besser dem REST-Ansatz folgt ... Ein großes Problem bei benutzerdefinierten MIME-Typen (oder MIME-Typen, die einen Versionsparameter anhängen) ist jedoch die schlechte Unterstützung für das Schreiben in Accept- und Content-Type-Header in HTML und JavaScript.
Zum Beispiel ist es IMO nicht möglich, mit den folgenden Headern in HTML5-Formularen zu POSTEN, um eine Ressource zu erstellen:
Dies liegt daran , das HTML5 -
enctype
Attribut eine Aufzählung ist also etwas anderes als die üblichenapplication/x-www-formurlencoded
,multipart/form-data
undtext/plain
sind ungültig.... und ich bin mir auch nicht sicher, ob es von allen Browsern in HTML4 unterstützt wird (das ein laxeres Encytpe-Attribut hat, aber ein Problem bei der Browserimplementierung wäre, ob der MIME-Typ weitergeleitet wurde).
Aus diesem Grund denke ich, dass der beste Weg zur Version über den URI ist, aber ich akzeptiere, dass dies nicht der "richtige" Weg ist.
quelle
Fügen Sie Ihre Version in die URI ein. Eine Version einer API unterstützt nicht immer die Typen einer anderen, daher ist das Argument, dass Ressourcen lediglich von einer Version zu einer anderen migriert werden, einfach falsch. Es ist nicht dasselbe wie das Wechseln des Formats von XML zu JSON. Die Typen sind möglicherweise nicht vorhanden oder haben sich semantisch geändert.
Versionen sind Teil der Ressourcenadresse. Sie routen von einer API zu einer anderen. Es ist nicht RESTful, die Adressierung im Header zu verbergen.
quelle
Es gibt einige Stellen, an denen Sie eine Versionierung in einer REST-API durchführen können:
Wie bereits erwähnt, in der URI. Dies kann nachvollziehbar und sogar ästhetisch ansprechend sein, wenn Weiterleitungen und dergleichen gut verwendet werden.
Im Header Accepts: befindet sich die Version im Dateityp. Wie 'mp3' vs 'mp4'. Dies wird auch funktionieren, obwohl IMO es ein bisschen weniger gut funktioniert als ...
In der Ressource selbst. In vielen Dateiformaten sind die Versionsnummern eingebettet, normalerweise im Header. Auf diese Weise kann neuere Software "nur funktionieren", indem alle vorhandenen Versionen des Dateityps verstanden werden, während ältere Software stechen kann, wenn eine nicht unterstützte (neuere) Version angegeben wird. Im Kontext einer REST-API bedeutet dies, dass sich Ihre URIs niemals ändern müssen, sondern nur Ihre Antwort auf die bestimmte Version der Daten, die Sie erhalten haben.
Ich kann Gründe sehen, alle drei Ansätze zu verwenden:
quelle
Die Versionierung Ihrer REST-API erfolgt analog zur Versionierung einer anderen API. Kleinere Änderungen können vorgenommen werden, größere Änderungen erfordern möglicherweise eine völlig neue API. Am einfachsten ist es, jedes Mal von vorne zu beginnen. Dies ist am sinnvollsten, wenn Sie die Version in die URL einfügen. Wenn Sie dem Client das Leben erleichtern möchten, versuchen Sie, die Abwärtskompatibilität aufrechtzuerhalten. Dies können Sie mit Verfall (permanente Umleitung), Ressourcen in mehreren Versionen usw. tun. Dies ist umständlicher und erfordert mehr Aufwand. Aber es ist auch das, was REST in "Coole URIs ändern sich nicht" fördert.
Am Ende ist es genau wie bei jedem anderen API-Design. Wägen Sie den Aufwand gegen die Bequemlichkeit des Kunden ab. Erwägen Sie die Einführung einer semantischen Versionierung für Ihre API, um Ihren Kunden zu verdeutlichen, wie abwärtskompatibel Ihre neue Version ist.
quelle