Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Eine RESTful-Web-API-Implementierung ist eine Web-API, die Architekturprinzipien für representational State Transfer (REST) verwendet, um eine zustandslose, lose gekoppelte Schnittstelle zwischen einem Client und einem Dienst zu erreichen. Eine Web-API, die RESTful ist, unterstützt das standardmäßige HTTP-Protokoll, um Vorgänge für Ressourcen auszuführen und Darstellungen von Ressourcen zurückzugeben, die Hypermedia-Links und HTTP-Vorgangsstatuscodes enthalten.
Eine RESTful-Web-API sollte mit den folgenden Prinzipien übereinstimmen:
Plattformunabhängigkeit, was bedeutet, dass Clients die Web-API unabhängig von der internen Implementierung aufrufen können. Um die Unabhängigkeit der Plattform zu erreichen, verwendet die Web-API HTTP als Standardprotokoll, stellt eine klare Dokumentation bereit und unterstützt ein vertrautes Datenaustauschformat wie JSON oder XML.
Lose Kopplung, was bedeutet, dass der Client und der Webdienst unabhängig voneinander weiterentwickelt werden können. Der Client muss die interne Implementierung des Webdiensts nicht kennen, und der Webdienst muss die interne Implementierung des Clients nicht kennen. Um eine lose Kopplung in einer RESTful-Web-API zu erreichen, verwenden Sie nur Standardprotokolle, und implementieren Sie einen Mechanismus, mit dem der Client und der Webdienst das Format der auszutauschenden Daten vereinbaren können.
In diesem Artikel werden bewährte Methoden für das Entwerfen von RESTful-Web-APIs beschrieben. Außerdem werden allgemeine Entwurfsmuster und Überlegungen zum Erstellen von Web-APIs behandelt, die leicht zu verstehen, flexibel und verwaltet werden können.
REST-Web-API-Designkonzepte
Um eine RESTful-Web-API zu implementieren, müssen Sie die folgenden Konzepte verstehen.
Uniform Resource Identifier (URI): REST-APIs sind für Ressourcen ausgelegt, die jede Art von Objekt, Daten oder Dienst sind, auf die der Client zugreifen kann. Jede Ressource wird durch einen URI dargestellt, der diese Ressource eindeutig identifiziert. Der URI für eine bestimmte Kundenbestellung kann z.B. wie folgt aussehen:
https://api.contoso.com/orders/1
Die Ressourcendarstellung definiert, wie eine Ressource, die durch ihren URI identifiziert wird, codiert und über das HTTP-Protokoll in einem bestimmten Format, z. B. XML oder JSON, transportiert wird. Clients, die eine bestimmte Ressource abrufen möchten, müssen den URI der Ressource in der Anforderung an die API verwenden. Die API gibt eine Ressourcendarstellung der Daten zurück, die der URI angibt. Beispielsweise kann ein Client eine GET-Anforderung an den URI-Bezeichner
https://api.contoso.com/orders/1
stellen, um den folgenden JSON-Text zu empfangen:{"orderId":1,"orderValue":99.9,"productId":1,"quantity":1}
Die einheitliche Schnittstelle ist, wie RESTful-APIs eine lose Kopplung zwischen Client- und Dienstimplementierungen erzielen. Bei REST-APIs, die auf HTTP basieren, umfasst die einheitliche Schnittstelle die Verwendung von Standard-HTTP-Verben zum Ausführen von Vorgängen wie
GET
, ,POST
, ,PUT
undPATCH
DELETE
auf Ressourcen.Zustandsloses Anforderungsmodell: RESTful-APIs verwenden ein zustandsloses Anforderungsmodell, was bedeutet, dass HTTP-Anforderungen unabhängig sind und in beliebiger Reihenfolge auftreten können. Aus diesem Grund ist es nicht möglich, vorübergehende Zustandsinformationen zwischen Anforderungen beizubehalten. Informationen werden ausschließlich in den Ressourcen selbst gespeichert, und jede Anforderung sollte eine atomare Operation sein. Ein zustandsloses Anforderungsmodell unterstützt eine hohe Skalierbarkeit, da keine Affinität zwischen Clients und bestimmten Servern beibehalten werden muss. Das zustandslose Modell kann die Skalierbarkeit jedoch ebenfalls einschränken, da es Herausforderungen mit der Skalierbarkeit des Back-End-Speichers von Webdiensten gibt. Weitere Informationen zu Strategien zum Skalieren eines Datenspeichers finden Sie unter "Datenpartitionierung".
Hypermedia-Links: REST-APIs können von Hypermedialinks gesteuert werden, die in jeder Ressourcendarstellung enthalten sind. Der folgende Codeblock zeigt beispielsweise eine JSON-Darstellung einer Reihenfolge. Es enthält Links, um den Kunden abzurufen oder zu aktualisieren, der der Bestellung zugeordnet ist.
{ "orderID":3, "productID":2, "quantity":4, "orderValue":16.60, "links": [ {"rel":"product","href":"https://api.contoso.com/customers/3", "action":"GET" }, {"rel":"product","href":"https://api.contoso.com/customers/3", "action":"PUT" } ] }
Definieren von RESTful-Web-API-Ressourcen-URIs
Eine RESTful-Web-API ist um Ressourcen herum organisiert. Um Ihren API-Entwurf um Ressourcen zu organisieren, definieren Sie Ressourcen-URIs, die den Geschäftsentitäten zugeordnet sind. Wenn möglich, basieren Ressourcen-URIs auf Substantiven (die Ressource) und nicht auf Verben (die Vorgänge der Ressource).
In einem E-Commerce-System können z. B. die primären Geschäftseinheiten Kunden und Bestellungen sein. Zum Erstellen einer Bestellung sendet ein Client die Bestellinformationen in einer HTTP POST-Anforderung an den Ressourcen-URI. Die HTTP-Antwort auf die Anforderung gibt an, ob die Auftragserstellung erfolgreich ist.
Der URI zum Erstellen der Bestellressource kann etwa wie folgt aussehen:
https://api.contoso.com/orders // Good
Vermeiden Sie die Verwendung von Verben in URIs zum Darstellen von Vorgängen. Der folgende URI wird beispielsweise nicht empfohlen:
https://api.contoso.com/create-order // Avoid
Entitäten werden häufig in Sammlungen wie Kunden oder Bestellungen gruppiert. Eine Auflistung ist eine separate Ressource von den Elementen innerhalb der Auflistung, daher sollte sie über einen eigenen URI verfügen. Der folgende URI könnte z.B. die Sammlung von Bestellungen darstellen:
https://api.contoso.com/orders
Nachdem der Client die Sammlung abgerufen hat, kann er eine GET-Anforderung an den URI jedes Elements stellen. Um beispielsweise Informationen zu einer bestimmten Bestellung zu erhalten, führt der Client eine HTTP GET-Anforderung für den URI https://api.contoso.com/orders/1
aus, um den folgenden JSON-Textkörper als Ressourcendarstellung der internen Bestelldaten zu erhalten:
{"orderId":1,"orderValue":99.9,"productId":1,"quantity":1}
Benennungskonventionen für Ressourcen-URI
Wenn Sie eine RESTful-Web-API entwerfen, ist es wichtig, dass Sie die richtigen Benennungs- und Beziehungskonventionen für Ressourcen verwenden:
Verwenden Sie Substantive für Ressourcennamen. Verwenden Sie Substantive, um Ressourcen darzustellen. Verwenden Sie z. B.
/orders
statt/create-order
. Die Methoden HTTP GET, POST, PUT, PATCH und DELETE bedeuten bereits die verbale Aktion.Verwenden Sie plurale Substantive, um Sammlungs-URIs zu benennen. Im Allgemeinen ist es hilfreich, Nomen in Pluralform für URIs zu verwenden, die auf Sammlungen verweisen. Es wird empfohlen, URIs für Sammlungen und Elemente in einer Hierarchie zu organisieren. Beispielsweise
/customers
ist der Pfad zur Sammlung des Kunden und/customers/5
der Pfad zum Kunden mit einer ID, die 5 entspricht. Dieser Ansatz trägt dazu bei, die Web-API intuitiv zu halten. Außerdem können viele Web-API-Frameworks Anforderungen basierend auf parametrisierten URI-Pfaden weiterleiten, sodass Sie eine Route für den Pfad/customers/{id}
definieren können.Berücksichtigen Sie die Beziehungen zwischen verschiedenen Ressourcentypen und wie Sie diese Zuordnungen verfügbar machen können. Beispielsweise könnte
/customers/5/orders
alle Bestellungen für Kunde 5 darstellen. Sie können die Beziehung auch in der anderen Richtung angehen, indem Sie die Zuordnung von einer Bestellung zu einem Kunden darstellen. In diesem Szenario kann der URI sein/orders/99/customer
. Eine zu umfangreiche Erweiterung dieses Modells kann jedoch aufwendig zu implementieren sein. Ein besserer Ansatz besteht darin, Links im Textkörper der HTTP-Antwortnachricht einzuschließen, damit Clients problemlos auf verwandte Ressourcen zugreifen können. Verwenden Sie Hypertext als Engine of Application State (HATEOAS), um die Navigation zu verwandten Ressourcen zu ermöglichen , um diesen Mechanismus ausführlicher zu beschreiben.Halten Sie Beziehungen einfach und flexibel. In komplexeren Systemen sind Sie möglicherweise geneigt, URIs bereitzustellen, die es dem Client ermöglichen, durch mehrere Ebenen von Beziehungen zu navigieren, z. B.
/customers/1/orders/99/products
. Dieses Maß an Komplexität kann jedoch schwierig zu verwalten sein und ist unflexibel, wenn sich die Beziehungen zwischen Ressourcen in der Zukunft ändern. Versuchen Sie stattdessen, URIs relativ einfach zu halten. Nachdem eine Anwendung über einen Verweis auf eine Ressource verfügt, sollten Sie diesen Verweis verwenden können, um Elemente im Zusammenhang mit dieser Ressource zu finden. Sie können die vorangehende Abfrage durch den URI/customers/1/orders
ersetzen, um alle Bestellungen des Kunden 1 zu finden, und dann/orders/99/products
verwenden, um die Produkte in dieser Bestellung zu finden.Tipp
Vermeiden Sie, dass Ressourcen-URIs erforderlich sind, die komplexer als Sammlung/Element/Auflistung sind.
Vermeiden Sie eine große Anzahl kleiner Ressourcen. Alle Webanforderungen setzen eine Last auf dem Webserver auf. Je mehr Anforderungen, desto größer die Last. Web-APIs, die eine große Anzahl kleiner Ressourcen verfügbar machen, werden als chatty-Web-APIs bezeichnet. Versuchen Sie, diese APIs zu vermeiden, da eine Clientanwendung mehrere Anforderungen senden muss, um alle benötigten Daten zu finden. Erwägen Sie stattdessen die Denormalisierung der Daten und kombinieren Sie verwandte Informationen zu größeren Ressourcen, die über eine einzelne Abfrage abgerufen werden können. Sie müssen diesen Ansatz jedoch trotzdem gegen den Aufwand des Abrufens von Daten abwägen, die der Client nicht benötigt. Das Abrufen großer Objekte kann die Latenz einer Anforderung erhöhen und mehr Bandbreitenkosten verursachen. Weitere Informationen zu diesen leistungsbezogenen Antimustern finden Sie unter Zu viele E/A-Vorgänge und Irrelevante Abrufe.
Vermeiden Sie das Erstellen von APIs, die die interne Struktur einer Datenbank spiegeln. REST dient zum Modellieren von Geschäftsentitäten und den Operationen, die eine Anwendung auf diese Entitäten ausführen kann. Ein Client sollte nicht für die interne Implementierung verfügbar gemacht werden. Sind Ihre Daten beispielsweise in einer relationalen Datenbank gespeichert, muss die Web-API nicht jede Tabelle als Sammlung von Ressourcen verfügbar machen. Dieser Ansatz erhöht die Angriffsfläche und kann zu Datenlecks führen. Stellen Sie sich die Web-API stattdessen als eine Abstraktion der Datenbank vor. Führen Sie bei Bedarf eine Zuordnungsebene zwischen der Datenbank und der Web-API ein. Diese Ebene stellt sicher, dass Clientanwendungen von Änderungen am zugrunde liegenden Datenbankschema isoliert sind.
Tipp
Es ist möglicherweise nicht möglich, jeden Vorgang, der von einer Web-API implementiert wird, einer bestimmten Ressource zuzuordnen. Sie können diese Szenarien ohne Ressourcen über HTTP-Anforderungen verarbeiten, die eine Funktion aufrufen und die Ergebnisse als HTTP-Antwortnachricht zurückgeben.
Beispielsweise kann eine Web-API, die einfache Rechnervorgänge wie Addieren und Subtrahieren implementiert, URIs bereitstellen, die diese Vorgänge als Pseudoressourcen verfügbar machen und die Abfragezeichenfolge verwenden, um die erforderlichen Parameter anzugeben. Eine GET-Anforderung an den URI /add?operand1=99&operand2=1 gibt eine Antwortnachricht mit dem Textkörper mit dem Wert 100 zurück.
Sie sollten jedoch diese URIs sparsam verwenden.
Definieren von RESTful-Web-API-Methoden
RESTful-Web-API-Methoden richten sich an die Vom HTTP-Protokoll definierten Anforderungsmethoden und Medientypen. In diesem Abschnitt werden die am häufigsten verwendeten Anforderungsmethoden und die Medientypen beschrieben, die in RESTful-Web-APIs verwendet werden.
HTTP-Anforderungsmethoden
Das HTTP-Protokoll definiert viele Anforderungsmethoden, die die Aktion angeben, die Sie für eine Ressource ausführen möchten. Die am häufigsten verwendeten Methoden in RESTful-Web-APIs sind GET, POST, PUT, PATCH und DELETE. Jede Methode entspricht einem bestimmten Vorgang. Wenn Sie eine RESTful-Web-API entwerfen, achten Sie darauf, dass die Methoden konsistent mit der Protokolldefinition, der Ressource, auf die zugegriffen wird, und der ausgeführten Aktion verwendet werden.
Es ist wichtig zu beachten, dass die Auswirkung einer bestimmten Anforderungsmethode davon abhängen sollte, ob es sich bei der Ressource um eine Sammlung oder ein einzelnes Element handelt. Die folgende Tabelle enthält einige Konventionen, die die meisten RESTful-Implementierungen verwenden.
Wichtig
In der folgenden Tabelle wird eine Beispiel-E-Commerce-Entität customer
verwendet. Eine Web-API muss nicht alle Anforderungsmethoden implementieren. Die von ihr implementierten Methoden hängen vom jeweiligen Szenario ab.
Ressource | BEREITSTELLEN | ABRUFEN | STELLEN | LÖSCHEN |
---|---|---|---|---|
/Kunden | Neuen Kunden erstellen | Alle Kunden abrufen | Massenaktualisierung aller Kunden | Alle Kunden entfernen |
/Kunden/1 | Fehler | Details für Kunden 1 abrufen | Details von Kunde 1 aktualisieren, falls vorhanden | Kunde 1 entfernen |
/Kunden/1/Bestellungen | Neue Bestellung für Kunden 1 erstellen | Alle Bestellungen für Kunde 1 abrufen | Massenaktualisierung von Bestellungen für Kunde 1 | Alle Bestellungen für Kunde 1 entfernen |
GET-Anforderungen
Eine GET-Anforderung ruft eine Darstellung der Ressource am angegebenen URI ab. Der Text der Antwortnachricht enthält die Details der angeforderten Ressource.
Eine GET-Anforderung sollte einen der folgenden HTTP-Statuscodes zurückgeben:
HTTP-Statuscode | Ursache |
---|---|
200 (OK) | Die Methode hat die Ressource erfolgreich zurückgegeben. |
204 (Kein Inhalt) | Der Antworttext enthält keinen Inhalt, z. B. wenn eine Suchanforderung keine Übereinstimmungen in der HTTP-Antwort zurückgibt. |
404 (Nicht gefunden) | Die angeforderte Ressource kann nicht gefunden werden. |
POST-Anforderungen
Eine POST-Anforderung sollte eine Ressource erstellen. Der Server weist der neuen Ressource einen URI zu und gibt diesen URI an den Client zurück.
Wichtig
Bei POST-Anforderungen sollte ein Client nicht versuchen, einen eigenen URI zu erstellen. Der Client sollte die Anfrage an die URI der Collection senden, und der Server sollte der neuen Ressource eine URI zuweisen. Wenn ein Client versucht, einen eigenen URI zu erstellen und eine POST-Anforderung an einen bestimmten URI ausgibt, gibt der Server HTTP-Statuscode 400 (BAD REQUEST) zurück, um anzugeben, dass die Methode nicht unterstützt wird.
In einem RESTful-Modell werden POST-Anforderungen verwendet, um der Auflistung, die der URI identifiziert, eine neue Ressource hinzuzufügen. Eine POST-Anforderung kann jedoch auch verwendet werden, um Daten zur Verarbeitung an eine vorhandene Ressource zu übermitteln, ohne dass eine neue Ressource erstellt wird.
Eine POST-Anforderung sollte einen der folgenden HTTP-Statuscodes zurückgeben:
HTTP-Statuscode | Ursache |
---|---|
200 (OK) | Die Methode hat eine Verarbeitung durchgeführt, erstellt aber keine neue Ressource. Das Ergebnis des Vorgangs kann im Antworttext enthalten sein. |
201 (Erstellt) | Die Ressource wurde erfolgreich erstellt. Der URI der neuen Ressource ist im Location-Header der Antwort enthalten. Der Antworttext enthält eine Darstellung der Ressource. |
204 (Kein Inhalt) | Der Antworttext enthält keinen Inhalt. |
400 (Ungültige Anforderung) | Der Client hat ungültige Daten in die Anforderung eingefügt. Der Antworttext kann weitere Informationen zum Fehler oder einen Link zu einem URI enthalten, der weitere Details bereitstellt. |
405 (Methode unzulässig) | Der Client hat versucht, eine POST-Anforderung an einen URI zu senden, der POST-Anforderungen nicht unterstützt. |
PUT-Anforderung
Eine PUT-Anforderung sollte eine vorhandene Ressource aktualisieren, wenn sie vorhanden ist, oder in einigen Fällen eine neue Ressource erstellen, wenn sie nicht vorhanden ist. So stellen Sie eine PUT-Anforderung vor:
- Der Client gibt den URI für die Ressource an und enthält einen Anforderungstext, der eine vollständige Darstellung der Ressource enthält.
- Der Client führt die Anforderung aus.
- Wenn eine Ressource mit diesem URI bereits vorhanden ist, wird sie ersetzt. Andernfalls wird eine neue Ressource erstellt, wenn die Route sie unterstützt.
PUT-Methoden werden auf Ressourcen angewendet, die einzelne Elemente sind, z. B. ein bestimmter Kunde, anstelle von Sammlungen. Ein Server kann Aktualisierungen über PUT unterstützen, die Erstellung jedoch möglicherweise nicht. Ob die Erstellung über PUT unterstützt werden soll, hängt davon ab, ob der Client einen URI sinnvoll und zuverlässig einer Ressource zuweisen kann, bevor er vorhanden ist. Wenn dies nicht möglich ist, verwenden Sie POST, um Ressourcen zu erstellen und lassen Sie den Server die URI zuordnen. Verwenden Sie dann PUT oder PATCH, um den URI zu aktualisieren.
Wichtig
PUT-Anforderungen müssen idempotent sein, was bedeutet, dass das Senden derselben Anforderung mehrmals dazu führt, dass dieselbe Ressource mit denselben Werten geändert wird. Wenn ein Client eine PUT-Anforderung erneut sendet, sollten die Ergebnisse unverändert bleiben. Im Gegensatz dazu sind POST- und PATCH-Anforderungen nicht garantiert idempotent.
Eine PUT-Anforderung sollte einen der folgenden HTTP-Statuscodes zurückgeben:
HTTP-Statuscode | Ursache |
---|---|
200 (OK) | Die Ressource wurde erfolgreich aktualisiert. |
201 (Erstellt) | Die Ressource wurde erfolgreich erstellt. Der Antworttext kann eine Darstellung der Ressource enthalten. |
204 (Kein Inhalt) | Die Ressource wurde erfolgreich aktualisiert, der Antworttext enthält jedoch keinen Inhalt. |
409 (Konflikt) | Die Anforderung konnte aufgrund eines Konflikts mit dem aktuellen Status der Ressource nicht abgeschlossen werden. |
Tipp
Erwägen Sie das Implementieren von HTTP PUT-Massenvorgängen, die Stapelaktualisierungen für mehrere Ressourcen in einer Auflistung durchführen können. Die PUT-Anforderung sollte den URI der Auflistung angeben. Der Anforderungstext sollte die Details der zu ändernden Ressourcen angeben. Dieser Ansatz kann dazu beitragen, die Chattigkeit zu reduzieren und die Leistung zu verbessern.
PATCH-Anfragen
Eine PATCH-Anforderung führt eine partielle Aktualisierung einer vorhandenen Ressource durch. Der Client gibt den URI für die Ressource an. Der Anforderungstext gibt eine Reihe von Änderungen an, die auf die Ressource angewendet werden sollen. Diese Methode kann effizienter sein als PUT-Anforderungen zu verwenden, da der Client nur die Änderungen und nicht die gesamte Darstellung der Ressource sendet. PATCH kann auch eine neue Ressource erstellen, indem eine Reihe von Updates für eine leere oder NULL-Ressource angegeben wird, wenn der Server diese Aktion unterstützt.
Bei einer PATCH-Anforderung sendet der Client eine Reihe von Aktualisierungen an eine vorhandene Ressource in Form eines Patchdokuments. Der Server verarbeitet das Patch-Dokument, um die Aktualisierung durchzuführen. Das Patchdokument gibt nur eine Reihe von Änderungen an, die angewendet werden sollen, anstatt die gesamte Ressource zu beschreiben. Die Spezifikation für die PATCH-Methode RFC 5789 definiert kein bestimmtes Format für Patchdokumente. Das Format muss vom Medientyp in der Anforderung abgeleitet werden.
JSON ist eines der am häufigsten verwendeten Datenformate für Web-APIs. Die beiden wichtigsten JSON-basierten Patchformate sind JSON-Patch und JSON-Zusammenführungspatch.
JSON-Merge-Patch ist einfacher als JSON-Patch. Das Patchdokument weist dieselbe Struktur wie die ursprüngliche JSON-Ressource auf, enthält jedoch nur die Teilmenge der Felder, die geändert oder hinzugefügt werden sollen. Außerdem kann ein Feld gelöscht werden, indem im Patch-Dokument null
als Feldwert angegeben wird. Diese Spezifikation bedeutet, dass der Zusammenführungspatch nicht geeignet ist, wenn die ursprüngliche Ressource explizite Nullwerte aufweisen kann.
Beispiel: Angenommen, die ursprüngliche Ressource weist die folgende JSON-Darstellung auf:
{
"name":"gizmo",
"category":"widgets",
"color":"blue",
"price":10
}
Hier ist ein möglicher JSON-Zusammenführungspatch für diese Ressource:
{
"price":12,
"color":null,
"size":"small"
}
Dieser Merge-Patch weist den Server an, price
zu aktualisieren, color
zu löschen, und size
hinzuzufügen. Die Werte für name
und category
werden nicht geändert. Weitere Informationen zum JSON-Zusammenführungspatch finden Sie unter RFC 7396. Der Medientyp für JSON Merge Patch lautet application/merge-patch+json
.
Der Zusammenführungspatch eignet sich nicht, wenn die ursprüngliche Ressource explizite NULL-Werte aufgrund der besonderen Bedeutung null
des Patchdokuments enthalten kann. Das Patchdokument gibt auch nicht die Reihenfolge an, in der der Server die Updates anwenden soll. Ob diese Bestellung von Bedeutung ist, hängt von den Daten und der Domäne ab. JSON-Patch, der in RFC 6902 definiert ist, ist flexibler, da er die Änderungen als Sequenz der anzuwendenden Vorgänge angibt, einschließlich hinzufügen, entfernen, ersetzen, kopieren und testen, um Werte zu überprüfen. Der Medientyp für JSON Patch ist application/json-patch+json
.
Eine PATCH-Anforderung sollte einen der folgenden HTTP-Statuscodes zurückgeben:
HTTP-Statuscode | Ursache |
---|---|
200 (OK) | Die Ressource wurde erfolgreich aktualisiert. |
400 (Ungültige Anforderung) | Falsch formatiertes Patch-Dokument. |
409 (Konflikt) | Das Patch-Dokument ist gültig, aber die Änderungen können auf die Ressource in ihrem aktuellen Zustand nicht angewendet werden. |
415 (Nicht unterstützter Medientyp) | Das Format des Patch-Dokuments wird nicht unterstützt. |
DELETE-Anfragen
Eine DELETE-Anforderung entfernt die Ressource am angegebenen URI. Eine DELETE-Anforderung sollte einen der folgenden HTTP-Statuscodes zurückgeben:
HTTP-Statuscode | Ursache |
---|---|
204 (KEIN INHALT) | Die Ressource wurde erfolgreich gelöscht. Der Prozess wurde erfolgreich verarbeitet, und der Antworttext enthält keine weiteren Informationen. |
404 (NICHT GEFUNDEN) | Die Ressource ist nicht vorhanden. |
MIME-Typen für Ressourcen
Ressourcendarstellung ist die Art und Weise, wie eine Ressource, die durch den URI identifiziert wird, codiert und über das HTTP-Protokoll in einem bestimmten Format, z. B. XML oder JSON, transportiert wird. Clients, die eine bestimmte Ressource abrufen möchten, müssen den URI in der Anforderung an die API verwenden. Die API antwortet, indem eine Ressourcendarstellung der durch den URI angegebenen Daten zurückgegeben wird.
Im HTTP-Protokoll werden Ressourcendarstellungsformate mithilfe von Medientypen, auch ALS MIME-Typen bezeichnet, angegeben. Bei nichtbinären Daten unterstützen die meisten Web-APIs JSON (Medientyp = application/json
) und möglicherweise XML (Medientyp = application/xml
).
Der Inhaltstypheader in einer Anforderung oder Antwort gibt das Ressourcendarstellungsformat an. Im folgenden Beispiel wird eine POST-Anforderung veranschaulicht, die JSON-Daten enthält:
POST https://api.contoso.com/orders
Content-Type: application/json; charset=utf-8
Content-Length: 57
{"Id":1,"Name":"Gizmo","Category":"Widgets","Price":1.99}
Wenn der Server den Medientyp nicht unterstützt, muss er den HTTP-Statuscode 415 (Nicht unterstützter Medientyp) zurückgeben.
Eine Clientanforderung kann einen Accept-Header enthalten, der eine Liste der Medientypen enthält, die der Client vom Server in der Antwortnachricht akzeptiert. Zum Beispiel:
GET https://api.contoso.com/orders/2
Accept: application/json, application/xml
Wenn der Server keinem der aufgeführten Medientypen entsprechen kann, sollte der HTTP-Statuscode 406 (Nicht akzeptabel) zurückgegeben werden.
Implementieren asynchroner Methoden
Manchmal erfordert eine POST-, PUT-, PATCH- oder DELETE-Methode eine Verarbeitung, die zeitaufwendig ist. Wenn Sie auf den Abschluss warten, bevor Sie eine Antwort an den Client senden, kann dies zu einer inakzeptablen Latenz führen. In diesem Fall sollten Sie die Methode asynchron machen. Eine asynchrone Methode sollte HTTP-Statuscode 202 (Akzeptiert) zurückgeben, um anzugeben, dass die Anforderung zur Verarbeitung akzeptiert wurde, aber unvollständig ist.
Machen Sie einen Endpunkt verfügbar, der den Status einer asynchronen Anforderung zurückgibt, damit der Client den Status überwachen kann, indem er den Statusendpunkt abruft. Nehmen Sie den URI des Statusendpunkts in den Location-Header der 202-Antwort auf. Zum Beispiel:
HTTP/1.1 202 Accepted
Location: /api/status/12345
Wenn der Client eine GET-Anforderung an diesen Endpunkt sendet, muss die Antwort auf den aktuellen Status der Anforderung enthalten. Optional kann es eine geschätzte Zeit für den Abschluss oder einen Link zum Abbrechen des Vorgangs enthalten.
HTTP/1.1 200 OK
Content-Type: application/json
{
"status":"In progress",
"link": { "rel":"cancel", "method":"delete", "href":"/api/status/12345" }
}
Wenn der asynchrone Vorgang eine neue Ressource erstellt, muss der Statusendpunkt nach Abschluss des Vorgangs den Statuscode 303 (See Other [Siehe anderswo]) zurückgeben. Nehmen Sie in die 303-Antwort einen Location-Header auf, der den URI der neuen Ressource angibt:
HTTP/1.1 303 See Other
Location: /api/orders/12345
Weitere Informationen finden Sie unter Asynchrone Unterstützung für lang andauernde Anforderungen bereitstellen und Asynchrones Request-Reply-Muster.
Implementierung von Datenpaginierung und -filterung
Um den Datenabruf zu optimieren und die Nutzlastgröße zu reduzieren, implementieren Sie die Daten paginierung und abfragebasierte Filterung in Ihrem API-Design. Mit diesen Techniken können Clients nur eine Teilmenge der benötigten Daten anfordern, wodurch die Leistung verbessert und die Bandbreitennutzung reduziert werden kann.
Die Paginierung unterteilt große Datasets in kleinere, verwaltbare Blöcke. Verwenden Sie Abfrageparameter wie
limit
, um die Anzahl der zurückzugebenden Elemente festzulegen, undoffset
, um den Ausgangspunkt festzulegen. Stellen Sie sicher, dass Sie auch aussagekräftige Standardwerte fürlimit
undoffset
bereitstellen, z. B.limit=25
undoffset=0
. Zum Beispiel:GET /orders?limit=25&offset=50
limit
: Gibt die maximale Anzahl der zurückzugebenden Elemente an.Tipp
Um Denial-of-Service-Angriffe zu verhindern, sollten Sie eine Obergrenze für die Anzahl der zurückgegebenen Elemente erzwingen. Wenn Ihr Dienst beispielsweise
max-limit=25
setzt und ein Clientlimit=1000
anfordert, kann Ihr Dienst entweder 25 Elemente oder einen HTTP-BAD-REQUEST-Fehler zurückgeben, abhängig von der API-Dokumentation.offset
: Gibt den Startindex für die Daten an.
Durch das Filtern können Clients das Dataset durch Anwenden von Bedingungen verfeinern. Die API kann es dem Client ermöglichen, den Filter in der Abfragezeichenfolge des URI zu übergeben:
GET /orders?minCost=100&status=shipped
-
minCost
: Filtert Bestellungen mit minimalen Kosten von 100. -
status
: Filtert Bestellungen mit einem bestimmten Status.
-
Berücksichtigen Sie die folgenden bewährten Methoden:
Das Sortieren ermöglicht Clients das Sortieren von Daten mithilfe eines
sort
Parameters wiesort=price
.Wichtig
Der Sortieransatz kann sich negativ auf das Zwischenspeichern auswirken, da Abfragezeichenfolgenparameter Teil des Ressourcenbezeichners sind, den viele Cacheimplementierungen als Schlüssel für zwischengespeicherte Daten verwenden.
Mit der Feldauswahl für clientdefinierte Projektionen können Clients nur die Felder angeben, die sie benötigen, indem sie einen
fields
Parameter wiefields=id,name
verwenden. Sie können z. B. einen Abfragezeichenfolgenparameter verwenden, der eine durch Trennzeichen getrennte Liste von Feldern akzeptiert, z. B. "/orders?fields=ProductID,Quantity".
Ihre API muss die angeforderten Felder überprüfen, um sicherzustellen, dass der Client darauf zugreifen darf und keine Felder verfügbar macht, die normalerweise nicht über die API verfügbar sind.
Unterstützung von Teilantworten
Einige Ressourcen enthalten große binärfelder, z. B. Dateien oder Bilder. Um Probleme zu überwinden, die durch unzuverlässige und unterbrochene Verbindungen verursacht werden, und um die Reaktionszeiten zu verbessern, sollten Sie den teilweisen Abruf großer binärer Ressourcen unterstützen.
Um Teilantworten zu unterstützen, sollte die Web-API den Accept-Ranges Header für GET-Anforderungen für große Ressourcen unterstützen. Dieser Header gibt an, dass der GET-Vorgang partielle Anforderungen unterstützt. Die Clientanwendung kann GET-Anforderungen senden, die eine Teilmenge einer Ressource zurückgeben, die als Bytebereich angegeben ist.
Erwägen Sie auch die Implementierung von HTTP HEAD-Anforderungen für diese Ressourcen. Eine HEAD-Anforderung ähnelt einer GET-Anforderung, gibt jedoch nur die HTTP-Header zurück, welche die Ressource beschreiben, sowie einen leeren Nachrichtentext. Eine Clientanwendung kann eine HEAD-Anforderung ausgeben, um zu bestimmen, ob eine Ressource mithilfe von partiellen GET-Anforderungen abgerufen wird. Zum Beispiel:
HEAD https://api.contoso.com/products/10?fields=productImage
Hier ist eine Beispielantwortnachricht:
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 4580
Der Content-Length-Header gibt die Gesamtgröße der Ressource an, und der Accept-Ranges-Header gibt an, dass der entsprechende GET-Vorgang Teilergebnisse unterstützt. Die Clientanwendung kann diese Informationen verwenden, um das Bild in kleineren Blöcken abzurufen. Die erste Anforderung ruft die ersten 2.500 Bytes mithilfe der Bereichskopfzeile ab:
GET https://api.contoso.com/products/10?fields=productImage
Range: bytes=0-2499
Die Antwortmeldung gibt an, dass diese Antwort teilweise ist, indem der HTTP-Statuscode 206 zurückgegeben wird. Der Header "Content-Length" gibt die tatsächliche Anzahl der im Nachrichtentext zurückgegebenen Bytes und nicht die Größe der Ressource an. Der Header "Content-Range" gibt an, welcher Teil der Ressource zurückgegeben wird (Bytes 0-2499 von 4580):
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 2500
Content-Range: bytes 0-2499/4580
[...]
Eine nachfolgende Anforderung von der Clientanwendung kann den Rest der Ressource abrufen.
Implementieren von HATEOAS
Einer der Hauptgründe für die Verwendung von REST ist die Möglichkeit, den gesamten Satz von Ressourcen ohne vorherige Kenntnisse des URI-Schemas zu navigieren. Jede HTTP GET-Anforderung sollte die erforderlichen Informationen zurückgeben, um die Ressourcen zu finden, die direkt mit dem angeforderten Objekt verbunden sind, über Hyperlinks, die in der Antwort enthalten sind. Die Anforderung sollte auch Informationen erhalten, die die für jede dieser Ressourcen verfügbaren Vorgänge beschreiben. Dieses Prinzip wird als Hypertext als Antrieb des Anwendungszustands (HATEOAS, Hypertext as the Engine of Application State) bezeichnet. Das System ist effektiv ein endlicher Zustandsautomat, und die Antwort auf jede Anforderung enthält die informationen, die erforderlich sind, um von einem Zustand zu einem anderen zu wechseln. Es sollten keine weiteren Informationen erforderlich sein.
Hinweis
Es gibt keine allgemeinen Standards, die definieren, wie das HATEOAS-Prinzip modelliert werden soll. Die Beispiele in diesem Abschnitt veranschaulichen eine mögliche proprietäre Lösung.
Um beispielsweise die Beziehung zwischen einem Auftrag und einem Kunden zu behandeln, kann die Darstellung eines Auftrags Links enthalten, die die verfügbaren Vorgänge für den Kunden der Bestellung identifizieren. Der folgende Codeblock ist eine mögliche Darstellung:
{
"orderID":3,
"productID":2,
"quantity":4,
"orderValue":16.60,
"links":[
{
"rel":"customer",
"href":"https://api.contoso.com/customers/3",
"action":"GET",
"types":["text/xml","application/json"]
},
{
"rel":"customer",
"href":"https://api.contoso.com/customers/3",
"action":"PUT",
"types":["application/x-www-form-urlencoded"]
},
{
"rel":"customer",
"href":"https://api.contoso.com/customers/3",
"action":"DELETE",
"types":[]
},
{
"rel":"self",
"href":"https://api.contoso.com/orders/3",
"action":"GET",
"types":["text/xml","application/json"]
},
{
"rel":"self",
"href":"https://api.contoso.com/orders/3",
"action":"PUT",
"types":["application/x-www-form-urlencoded"]
},
{
"rel":"self",
"href":"https://api.contoso.com/orders/3",
"action":"DELETE",
"types":[]
}]
}
In diesem Beispiel enthält das links
-Array eine Reihe von Links. Jeder Link stellt einen Vorgang für eine verknüpfte Entität dar. Die Daten für jeden Link beinhalten die Beziehung („Kunde“), den URI (https://api.contoso.com/customers/3
), die HTTP-Methode und die unterstützten MIME-Typen. Die Clientanwendung benötigt diese Informationen, um den Vorgang aufzurufen.
Das links
Array enthält auch selbstverweisende Informationen zur abgerufenen Ressource. Diese Links haben die Beziehung selbst.
Die zurückgegebenen Verknüpfungen können sich je nach Status der Ressource ändern. Die Idee, dass Hypertext der Motor des Anwendungszustands ist, beschreibt dieses Szenario.
Implementieren der Versionsverwaltung
Eine Web-API bleibt nicht statisch. Wenn sich die Geschäftsanforderungen ändern, werden neue Ressourcensammlungen hinzugefügt. Wenn neue Ressourcen hinzugefügt werden, können sich die Beziehungen zwischen Ressourcen ändern, und die Struktur der Daten in Ressourcen kann geändert werden. Das Aktualisieren einer Web-API zur Behandlung neuer oder anderer Anforderungen ist ein einfacher Prozess, aber Sie müssen die Auswirkungen berücksichtigen, die solche Änderungen auf Clientanwendungen haben, die die Web-API nutzen. Der Entwickler, der eine Web-API entwickelt und implementiert, hat die volle Kontrolle über diese API, hat jedoch nicht das gleiche Maß an Kontrolle über Clientanwendungen, die von Partnerorganisationen erstellt wurden. Es ist wichtig, vorhandene Clientanwendungen weiterhin zu unterstützen, während neue Clientanwendungen neue Features und Ressourcen verwenden können.
Eine Web-API, die die Versionsverwaltung implementiert, kann angeben, welche Features und Ressourcen verfügbar sind, und eine Clientanwendung kann Anforderungen senden, die an eine bestimmte Version eines Features oder einer Ressource weitergeleitet werden. In den folgenden Abschnitten sind verschiedene Ansätze mit ihren jeweiligen Vor- und Nachteilen beschrieben.
Keine Versionsverwaltung
Dieser Ansatz ist am einfachsten und kann für einige interne APIs funktionieren. Wesentliche Änderungen können als neue Ressourcen oder neue Verknüpfungen dargestellt werden. Das Hinzufügen von Inhalten zu vorhandenen Ressourcen stellt möglicherweise keine schwerwiegende Änderung dar, da Client-Anwendungen, die diese Inhalte nicht erwarten, sie ignorieren.
Beispielsweise sollte eine Anforderung an den URI https://api.contoso.com/customers/3
die Details eines einzelnen Kunden zurückgeben, die die Felder id
, name
und address
enthalten, die von der Clientanwendung erwartet werden.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"id":3,"name":"Fabrikam, Inc.","address":"1 Microsoft Way Redmond WA 98053"}
Hinweis
Der Einfachheit halber enthalten die in diesem Abschnitt gezeigten Beispielantworten keine HATEOAS-Links.
Wenn das DateCreated
Feld dem Schema der Kundenressource hinzugefügt wird, sieht die Antwort wie folgt aus:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"id":3,"name":"Fabrikam, Inc.","dateCreated":"2025-03-22T12:11:38.0376089Z","address":"1 Microsoft Way Redmond WA 98053"}
Vorhandene Clientanwendungen funktionieren möglicherweise weiterhin ordnungsgemäß, wenn sie nicht erkannte Felder ignorieren können. In der Zwischenzeit können neue Clientanwendungen entwickelt werden, um dieses neue Feld zu verarbeiten. Drastischere Änderungen am Ressourcenschema, einschließlich Feldentfernungen oder Umbenennungen, können jedoch auftreten. Oder die Beziehungen zwischen Ressourcen können sich ändern. Diese Updates können einschneidende Änderungen darstellen, die verhindern, dass vorhandene Clientanwendungen einwandfrei funktionieren. Berücksichtigen Sie in diesen Szenarien einen der folgenden Ansätze:
- URI-Versionsverwaltung
- Abfragezeichenfolgenversionsverwaltung
- Header-Versionsverwaltung
- Medientypversionsverwaltung
URI-Versionsverwaltung
Bei jeder Änderung der Web-API oder des Ressourcenschemas fügen Sie eine für jede Ressource eine Versionsnummer für den URI hinzu. Die zuvor vorhandenen URIs sollten weiterhin normal ausgeführt werden, indem Ressourcen zurückgegeben werden, die ihrem ursprünglichen Schema entsprechen.
Das address
-Feld im vorherigen Beispiel wird zum Beispiel in Unterfelder umstrukturiert, die jeden Bestandteil der Adresse enthalten, wie streetAddress
, city
, state
und zipCode
. Diese Version der Ressource kann über einen URI freigegeben werden, der eine Versionsnummer enthält, z.B. https://api.contoso.com/v2/customers/3
.
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"id":3,"name":"Fabrikam, Inc.","dateCreated":"2025-03-22T12:11:38.0376089Z","address":{"streetAddress":"1 Microsoft Way","city":"Redmond","state":"WA","zipCode":98053}}
Dieser Versionsverwaltungsmechanismus ist einfach, hängt jedoch vom Server ab, um die Anforderung an den entsprechenden Endpunkt weiterzuleiten. Es kann jedoch unübersichtlich werden, da die Web-API durch mehrere Iterationen reift und der Server viele verschiedene Versionen unterstützen muss. Aus sicht eines Puristen rufen die Clientanwendungen in allen Fällen dieselben Daten ab (Kunde 3), sodass sich der URI nicht je nach Version unterscheiden sollte. Dieses Schema erschwert auch die Implementierung von HATEOAS, da alle Links die Versionsnummer in ihre URIs einschließen müssen.
Abfragezeichenfolgen-Versionsverwaltung
Anstatt mehrere URIs bereitzustellen, können Sie die Version der Ressource angeben, indem Sie einen Parameter im Abfragestring verwenden, der an die HTTP-Anforderung angefügt wird, z. B. https://api.contoso.com/customers/3?version=2
. Der Versionsparameter sollte standardmäßig einen aussagekräftigen Wert aufweisen, z. B. 1, wenn ältere Clientanwendungen ihn weglassen.
Dieser Ansatz hat den semantischen Vorteil, dass dieselbe Ressource immer aus demselben URI abgerufen wird. Diese Methode hängt jedoch vom Code ab, der die Anforderung verarbeitet, um die Abfragezeichenfolge zu analysieren und die entsprechende HTTP-Antwort zurückzusenden. Dieser Ansatz erschwert auch die Implementierung von HATEOAS auf die gleiche Weise wie der URI-Versionsverwaltungsmechanismus.
Hinweis
Einige ältere Webbrowser und Proxys speichern Antworten auf Anfragen, die eine Zeichenfolge in der URI enthalten, nicht zwischen. Nicht zwischengespeicherte Antworten können die Leistung für Webanwendungen beeinträchtigen, die eine Web-API verwenden und in einem älteren Webbrowser ausgeführt werden.
Header-Versionierung
Anstatt die Versionsnummer als Abfragezeichenfolgenparameter anzufügen, können Sie einen benutzerdefinierten Header implementieren, der die Version der Ressource angibt. Dieser Ansatz erfordert, dass die Clientanwendung den entsprechenden Header zu allen Anforderungen hinzufügt. Der Code, der die Clientanforderung verarbeitet, kann jedoch einen Standardwert wie Version 1 verwenden, wenn der Versionsheader weggelassen wird.
In den folgenden Beispielen wird ein benutzerdefinierter Header mit dem Namen Custom-Header verwendet. Der Wert dieses Headers gibt die Version der Web-API an.
Version 1:
GET https://api.contoso.com/customers/3
Custom-Header: api-version=1
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"id":3,"name":"Fabrikam, Inc.","address":"1 Microsoft Way Redmond WA 98053"}
Version 2:
GET https://api.contoso.com/customers/3
Custom-Header: api-version=2
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"id":3,"name":"Fabrikam, Inc.","dateCreated":"2025-03-22T12:11:38.0376089Z","address":{"streetAddress":"1 Microsoft Way","city":"Redmond","state":"WA","zipCode":98053}}
Ähnlich wie bei URI-Versionsverwaltung und Abfragezeichenfolgenversionsverwaltung müssen Sie den entsprechenden benutzerdefinierten Header in alle Links einschließen, um HATEOAS zu implementieren.
Versionsverwaltung des Medientyps
Wenn eine Clientanwendung eine HTTP GET-Anforderung an einen Webserver sendet, sollte sie einen Accept-Header verwenden, um das Format des Inhalts anzugeben, den er verarbeiten kann. In der Regel besteht der Zweck des Accept-Headers darin, der Clientanwendung anzugeben, ob der Textkörper der Antwort XML, JSON oder ein anderes gängiges Format sein soll, das der Client analysieren kann. Es ist jedoch möglich, benutzerdefinierte Medientypen zu definieren, die Informationen enthalten, mit denen die Clientanwendung angeben kann, welche Version einer Ressource sie erwartet.
Das folgende Beispiel zeigt eine Anforderung, die einen Accept-Header mit dem Wert application/vnd.contoso.v1+json
angibt. Das vnd.contoso.v1
Element gibt dem Webserver an, dass es Version 1 der Ressource zurückgeben soll. Das json
Element gibt an, dass das Format des Antworttexts JSON sein soll:
GET https://api.contoso.com/customers/3
Accept: application/vnd.contoso.v1+json
Der Code, der die Anforderung verarbeitet, ist für die Verarbeitung des Accept-Headers verantwortlich und berücksichtigt sie so weit wie möglich. Die Clientanwendung kann mehrere Formate im Accept-Header angeben, wodurch der Webserver das am besten geeignete Format für den Antworttext auswählen kann. Der Webserver bestätigt das Format der Daten im Antworttext mithilfe des Content-Type-Headers:
HTTP/1.1 200 OK
Content-Type: application/vnd.contoso.v1+json; charset=utf-8
{"id":3,"name":"Fabrikam, Inc.","address":"1 Microsoft Way Redmond WA 98053"}
Wenn der Accept-Header keine bekannten Medientypen angibt, kann der Webserver eine HTTP 406 -Antwortnachricht (Nicht akzeptabel) generieren oder eine Nachricht mit einem Standardmedientyp zurückgeben.
Dieser Versionsverwaltungsmechanismus ist einfach und gut für HATEOAS geeignet, der den MIME-Typ verwandter Daten in Ressourcenverknüpfungen enthalten kann.
Hinweis
Wenn Sie eine Versionsverwaltungsstrategie auswählen, gibt es insbesondere Auswirkungen im Zusammenhang mit der Zwischenspeicherung von Webservern. Die URI-Versionsverwaltungs- und Abfragezeichenfolgenversionsschemas sind cachefreundlich, da die gleiche URI- oder Abfragezeichenfolgenkombination jedes Mal auf dieselben Daten verweist.
Die Versionsverwaltungsmechanismen für Kopfzeilen und Medientypen erfordern in der Regel mehr Logik, um die Werte im benutzerdefinierten Header oder den Accept-Header zu untersuchen. In einer umfangreichen Umgebung können zahlreiche Clients, die verschiedene Versionen einer Web-API verwenden, zu einer erheblichen Menge von doppelt vorhandenen Daten in einem serverseitigen Cache führen. Dieses Problem kann akut werden, wenn eine Clientanwendung über einen Proxy mit einem Webserver kommuniziert, der zwischenspeichert und nur eine Anforderung an den Webserver weiterleitet, wenn sie derzeit keine Kopie der angeforderten Daten im Cache enthält.
Mehrinstanzenfähige Web-APIs
Eine mehrinstanzenfähige Web-API-Lösung wird von mehreren Mandanten gemeinsam genutzt, z. B. von unterschiedlichen Organisationen, die über eigene Benutzergruppen verfügen.
Die Mehrinstanzenfähigkeit wirkt sich erheblich auf den Web-API-Entwurf aus, da dadurch festgelegt wird, wie Ressourcen über mehrere Mandanten hinweg innerhalb einer einzigen Web-API abgerufen und ermittelt werden. Entwerfen Sie eine API mit Mehrinstanzenfähigkeit, um die Notwendigkeit einer zukünftigen Umgestaltung zu vermeiden, um Isolation, Skalierbarkeit oder mandantenspezifische Anpassungen zu implementieren.
Eine gut durchdachte API sollte klar definieren, wie Mandanten in Anforderungen identifiziert werden, ob über Unterdomänen, Pfade, Header oder Token. Diese Struktur sorgt für eine konsistente und dennoch flexible Benutzererfahrung für alle Benutzer innerhalb des Systems. Weitere Informationen finden Sie unter Zuordnen von Anforderungen an Mandanten in einer mehrinstanzenfähigen Lösung.
Mehrinstanzenfähigkeit wirkt sich auf die Endpunktstruktur, die Anforderungsverarbeitung, die Authentifizierung und Autorisierung aus. Dieser Ansatz beeinflusst auch, wie API-Gateways, Lastenausgleichsgeräte und Back-End-Dienste Anforderungen weiterleiten und verarbeiten. Die folgenden Strategien sind gängige Methoden zum Erreichen von Mehrinstanzenfähigkeit in einer Web-API.
Verwenden Sie eine auf Subdomänen oder Domänen basierende Isolierung (DNS-Level Tenancy)
Dieser Ansatz leitet Anforderungen mithilfe von mandantenspezifischen Domänen weiter. Wildcarddomänen verwenden Unterdomänen für Flexibilität und Einfachheit. Benutzerdefinierte Domänen, die es Mandanten ermöglichen, ihre eigenen Domänen zu verwenden, bieten eine bessere Kontrolle und können auf bestimmte Anforderungen zugeschnitten werden. Beide Methoden basieren auf der richtigen DNS-Konfiguration, einschließlich A
und CNAME
Datensätzen, um den Datenverkehr an die entsprechende Infrastruktur zu leiten. Wildcarddomänen vereinfachen die Konfiguration, aber benutzerdefinierte Domänen bieten eine mehr Markenerfahrung.
Bewahren Sie den Hostnamen zwischen dem Reverseproxy und den Back-End-Diensten auf, um Probleme wie die URL-Umleitung zu vermeiden und die Bereitstellung interner URLs zu verhindern. Mit dieser Methode wird das richtige Routing von mandantenspezifischem Datenverkehr sichergestellt und die interne Infrastruktur geschützt. Die DNS-Auflösung ist entscheidend, um die Datenaufbewahrung zu erreichen und die Einhaltung gesetzlicher Vorschriften zu gewährleisten.
GET https://adventureworks.api.contoso.com/orders/3
Übergeben mandantenspezifischer HTTP-Header
Mandanteninformationen können über benutzerdefinierte HTTP-Header wie X-Tenant-ID
oder X-Organization-ID
oder über hostbasierte Header wie Host
oder X-Forwarded-Host
übergeben werden, oder sie können aus JSON Web Token (JWT)-Ansprüchen extrahiert werden. Die Wahl hängt von den Routingfunktionen Ihres API-Gateways oder Reverseproxys ab, wobei headerbasierte Lösungen ein Layer 7 (L7)-Gateway erfordern, das jede Anforderung prüft. Diese Anforderung erhöht den Verarbeitungsaufwand, wodurch die Berechnungskosten erhöht werden, wenn datenverkehrsskaliert wird. Die headerbasierte Isolation bietet jedoch wichtige Vorteile. Sie ermöglicht die zentralisierte Authentifizierung, wodurch die Sicherheitsverwaltung über mehrere Mandanten-APIs vereinfacht wird. Durch die Verwendung von SDKs oder API-Clients wird der Mandantenkontext zur Laufzeit dynamisch verwaltet, wodurch die komplexität der clientseitigen Konfiguration reduziert wird. Außerdem führt die Beibehaltung des Mandantenkontexts in Headern zu einem übersichtlicheren, mehr RESTful-API-Design, indem mandantenspezifische Daten im URI vermieden werden.
Ein wichtiger Aspekt für das headerbasierte Routing besteht darin, dass die Zwischenspeicherung erschwert wird, insbesondere, wenn Cacheebenen ausschließlich auf URI-basierten Schlüsseln basieren und keine Konten für Header aufweisen. Da die meisten Cachemechanismen für URI-Nachschlagevorgänge optimiert werden, kann die Verwendung von Headern zu fragmentierten Cacheeinträgen führen. Fragmentierte Einträge reduzieren Cachetreffer und erhöhen die Back-End-Last. Noch wichtiger ist, wenn eine Caching-Schicht keine Antworten nach Headern unterscheidet, kann sie zwischengespeicherte Daten bereitstellen, die für einen Mandanten vorgesehen sind, und ein Risiko für Datenlecks für andere schaffen.
GET https://api.contoso.com/orders/3
X-Tenant-ID: adventureworks
oder
GET https://api.contoso.com/orders/3
Host: adventureworks
oder
GET https://api.contoso.com/orders/3
Authorization: Bearer <JWT-token including a tenant-id: adventureworks claim>
Mandantenspezifische Informationen über den URI-Pfad übergeben
Bei diesem Ansatz werden Mandanten-IDs innerhalb der Ressourcenhierarchie angefügt und vom API-Gateway oder Reverseproxy verwendet, um den entsprechenden Mandanten basierend auf dem Pfadsegment zu identifizieren. Die pfadbasierte Isolation ist effektiv, kompromittiert jedoch das RESTful-Design der Web-API und führt komplexere Routinglogik ein. Es erfordert häufig Musterabgleich oder reguläre Ausdrücke, um den URI-Pfad zu analysieren und zu kanonisieren.
Im Gegensatz dazu vermittelt die headerbasierte Isolation Mandanteninformationen über HTTP-Header als Schlüsselwertpaare. Beide Ansätze ermöglichen eine effiziente Infrastrukturfreigabe, um die Betriebskosten zu senken und die Leistung in großen, mehrstufigen Web-APIs zu verbessern.
GET https://api.contoso.com/tenants/adventureworks/orders/3
Aktivieren von verteiltem Tracing und Trace-Kontext in APIs
Da verteilte Systeme und Microservice-Architekturen zum Standard werden, steigt die Komplexität moderner Architekturen. Die Verwendung von Headern, z. B. Correlation-ID
, X-Request-ID
oder X-Trace-ID
, zum Verteilen des Ablaufverfolgungskontexts in API-Anforderungen ist eine bewährte Methode, um die End-to-End-Sichtbarkeit zu erreichen. Dieser Ansatz ermöglicht eine nahtlose Nachverfolgung von Anforderungen, während sie vom Client zu Back-End-Diensten fließen. Dies erleichtert die schnelle Identifizierung von Fehlern, überwacht die Latenz und ordnet API-Abhängigkeiten über Dienste hinweg zu.
APIs, die die Einbeziehung von Ablaufverfolgungs- und Kontextinformationen unterstützen, verbessern ihre Observability-Level und Debugging-Funktionen. Durch die Aktivierung der verteilten Ablaufverfolgung ermöglichen diese APIs ein genaueres Verständnis des Systemverhaltens und erleichtern das Nachverfolgen, Diagnostizieren und Beheben von Problemen in komplexen Umgebungen mit mehreren Diensten.
GET https://api.contoso.com/orders/3
Correlation-ID: 0f8fad5b-d9cb-469f-a165-70867728950e
HTTP/1.1 200 OK
...
Correlation-ID: 0f8fad5b-d9cb-469f-a165-70867728950e
{...}
Web-API-Reifegradmodell
Im Jahr 2008 schlug Leonard Richardson vor, was jetzt als Richardson Maturity Model (RMM) für Web-APIs bekannt ist. Das RMM definiert vier Reifestufen für Web-APIs und basiert auf den Prinzipien von REST als architekturbezogener Ansatz beim Entwerfen von Webdiensten. Im RMM wird die API, da sich der Reifegrad erhöht, stärker RESTful und folgt genauer den Prinzipien von REST.
Diese Ebenen sind die folgenden:
- Ebene 0: Definieren Sie einen URI, und alle Vorgänge sind POST-Anforderungen an diesen URI. Simple Object Access Protocol-Webdienste befinden sich in der Regel auf dieser Ebene.
- Ebene 1: Erstellen Sie separate URIs für einzelne Ressourcen. Diese Ebene ist noch nicht RESTful, beginnt aber mit dem RESTful-Design.
- Ebene 2: Verwenden Sie HTTP-Methoden, um Vorgänge für Ressourcen zu definieren. In der Praxis stimmen viele veröffentlichte Web-APIs ungefähr mit dieser Ebene überein.
- Ebene 3: Verwenden Sie Hypermedia (HATEOAS). Diese Ebene ist wirklich eine RESTful-API gemäß der Definition von Fielding.
OpenAPI Initiative
Die OpenAPI Initiative wurde von einem Branchenkonsortium erstellt, um REST-API-Beschreibungen für alle Anbieter zu standardisieren. Die Standardisierungsspezifikation wurde Swagger genannt, bevor sie unter der OpenAPI-Initiative eingeführt und in die OpenAPI Specification (OAS) umbenannt wurde.
Möglicherweise möchten Sie OpenAPI für Ihre RESTful-Web-APIs übernehmen. Berücksichtigen Sie die folgenden Punkte:
Das OAS enthält eine Reihe von Meinungsrichtlinien für das REST-API-Design. Die Richtlinien sind für die Interoperabilität vorteilhaft, erfordern jedoch, dass Ihr Design den Spezifikationen entspricht.
OpenAPI fördert einen Vertrags-first-Ansatz anstelle eines Implementierungs-first-Ansatzes. "Contract-first" bedeutet, dass Sie zuerst den API-Vertrag (die Schnittstelle) entwerfen und dann Code schreiben, der den Vertrag implementiert.
Tools wie Swagger (OpenAPI) können Clientbibliotheken oder Dokumentationen aus API-Verträgen generieren. Ein Beispiel finden Sie in ASP.NET Core Web API-Dokumentation mit Swagger/OpenAPI.
Nächste Schritte
- Ausführliche Empfehlungen zum Gestalten von REST-APIs auf Azure finden Sie hier.
- Sehen Sie sich eine Checkliste von Elementen an, die Sie beim Entwerfen und Implementieren einer Web-API berücksichtigen sollten.
- Erstellen Sie Software as a Service- und Multitenant-Lösungsarchitekturen in Azure.