rest Tutorial
Erste Schritte mit Ruhe
Suche…
Bemerkungen
In diesem Abschnitt erhalten Sie einen Überblick über den Rest und warum ein Entwickler sie verwenden möchte.
Es sollte auch alle großen Themen in Ruhe erwähnen und auf die verwandten Themen verweisen. Da die Dokumentation für den Rest neu ist, müssen Sie möglicherweise erste Versionen dieser verwandten Themen erstellen.
REST-Übersicht
REST steht für Präsentations - S tate T ransfer RE und wurde von Roy Fielding in seiner Doktorarbeit geprägt Baustile und das Design von Netzwerk-basierten Software - Architekturen . Darin identifiziert er spezifische architektonische Prinzipien wie:
Adressierbare Ressourcen: Die wichtigste Abstraktion von Informationen und Daten in REST ist eine Ressource, und jede Ressource muss über einen URI adressierbar sein.
Eine einheitliche, eingeschränkte Schnittstelle: Verwenden Sie eine kleine Anzahl gut definierter Methoden, um unsere Ressourcen zu manipulieren.
Darstellungsorientiert: Eine Ressource, auf die ein URI verweist, kann unterschiedliche Formate haben und unterschiedliche Plattformen benötigen unterschiedliche Formate. Beispielsweise benötigen Browser HTML, JavaScript erfordert JSON- und Java-Anwendungen möglicherweise XML, JSON, CSV, Text usw. Daher interagieren wir mit Diensten Verwendung der Darstellung dieses Dienstes.
Kommunizieren Sie zustandslos: Zustandslose Anwendungen sind einfacher zu skalieren.
Hypermedia als Engine of Application State: Lassen Sie unsere Datenformate Zustandsübergänge in unseren Anwendungen steuern.
Der Satz dieser architektonischen Prinzipien wird als REST bezeichnet. Die Konzepte von REST sind von denen von HTTP inspiriert. Roy Fielding, der uns REST gegeben hat, ist auch einer der Autoren von HTTP-Spezifikationen.
Web Services und RESTful Web Services sind Dienste, die dem Internet für programmgesteuerte Zugriffe ausgesetzt sind. Sie sind Online-API, die wir mit unserem Code aufrufen können. Es gibt zwei Arten von "großen" Web-Services, SOAP- und REST-Web-Services.
RESTful Web Services : Web Services, die unter Verwendung der REST-Architekturkonzepte geschrieben werden, werden als RESTful Web Services bezeichnet. Sie konzentrieren sich auf Systemressourcen und darauf, wie der Status einer Ressource über das HTTP-Protokoll an verschiedene Clients übertragen werden kann.
Dieses Dokument konzentriert sich ausschließlich auf RESTful-Webdienste, daher werden wir nicht auf die Details von SOAP WS eingehen.
Es gibt keine strengen Regeln beim Entwurf von RESTful-Webservices wie
- Kein Protokollstandard
- Kein Standard für Kommunikationskanäle
- Kein Service-Definitionsstandard
Aber für all diese gelten für SOAP strenge Regeln. Alle SOAP-Webdienste folgen der SOAP-Spezifikation, in der festgelegt ist, was jeder SOAP-Webdienst sein soll. Diese Spezifikation wird von einem Komitee entwickelt und verwaltet. Wenn SOAP WS nicht einmal einer einzigen Regel folgt, handelt es sich definitionsgemäß nicht um SOAP.
Konzepte von RESTful Web Services
Es gibt einige Richtlinien, die beim Entwerfen / Entwickeln von RESTful-API zu beachten sind:
- Ressourcenbasierte Standorte / URI
- Ordnungsgemäße Verwendung von HTTP-Methoden
- HATEOAS (Hypermedia als Engine of Application State)
Der Hauptansatz bei der Entwicklung von RESTful-APIs sollte darin bestehen, die API so "RESTful wie möglich" zu machen.
REST über HTTP
REST ist eine protokollagnostische Architektur, die von Roy Fielding in seiner Dissertation vorgeschlagen wurde (Kapitel 5 ist die Präsentation von REST) und verallgemeinert das bewährte Konzept von Webbrowsern als Clients, um Clients in einem verteilten System von Servern zu entkoppeln.
Damit ein Dienst oder eine API REST-fähig ist, muss er sich an die folgenden Einschränkungen halten:
- Kundenserver
- Staatenlos
- Zwischenspeicherbar
- Schichtsystem
- Einheitliche Schnittstelle
- Ressourcenidentifikation
- Darstellung der Ressourcen
- Selbstbeschreibende Nachrichten
- Hypermedia
Neben den in Fieldings Dissertation genannten Einschränkungen müssen die REST-APIs in seinem Blogbeitrag hypertextgesteuert sein . Fielding hat klargestellt, dass das Aufrufen eines Dienstes über HTTP ihn nicht RESTful macht . Ein Dienst sollte daher auch weitere Regeln beachten, die wie folgt zusammengefasst werden:
Die API sollte das zugrunde liegende Protokoll einhalten und nicht gegen dieses verstoßen. Obwohl REST meistens über HTTP verwendet wird, ist es nicht auf dieses Protokoll beschränkt.
Starker Fokus auf Ressourcen und deren Darstellung über Medientypen.
Kunden sollten nicht über erste Kenntnisse oder Annahmen zu den verfügbaren Ressourcen oder deren zurückgegebenen Status ( "typisierte" Ressource ) in einer API verfügen, sondern diese über ausgegebene Anforderungen und analysierte Antworten direkt lernen. Dies gibt dem Server die Möglichkeit, Ressourcen zu verschieben oder umzubenennen, ohne die Client-Implementierung zu beschädigen.
Richardson Reifemodell
Mit dem Richardson Maturity Model können REST-Einschränkungen über HTTP angewendet werden, um RESTful-Webdienste zu erhalten.
Leonard Richardson hat die Anwendungen in diese 4 Schichten unterteilt:
- Stufe 0: Verwendung von HTTP für den Transport
- Stufe 1: Verwendung von URL zur Identifizierung von Ressourcen
- Stufe 2: Verwendung von HTTP-Verben und -Status für die Interaktionen
- Stufe 3: Verwendung von HATEOAS
Da der Fokus auf der Repräsentation des Status einer Ressource liegt, wird die Unterstützung mehrerer Repräsentationen für dieselbe Ressource empfohlen. Eine Darstellung kann daher einen Überblick über den Ressourcenzustand bieten, während eine andere Person die vollständigen Details derselben Ressource zurückgibt.
Beachten Sie auch, dass eine API bei Fielding-Einschränkungen erst dann effektiv REST-fähig ist, wenn die 3. Ebene des RMM implementiert ist .
HTTP-Anfragen und Antworten
Eine HTTP-Anfrage lautet:
- Ein Verb (aka-Methode), meistens eines von GET , POST , PUT , DELETE oder PATCH
- Eine URL
- Header (Schlüssel-Wert-Paare)
- Optional ein Body (auch bekannt als Payload, Daten)
Eine HTTP-Antwort lautet:
- Ein Status, meistens 2xx (erfolgreich) , 4xx ( Clientfehler ) oder 5xx ( Serverfehler ).
- Header (Schlüssel-Wert-Paare)
- Ein Körper (aka Payload, Daten)
Eigenschaften der HTTP-Verben:
- Verben, die einen Körper haben:
POST
,PUT
,PATCH
- Verben, die sicher sein müssen (dh Ressourcen dürfen nicht verändert werden):
GET
- Verben, die idempotent sein müssen (dh, sie dürfen Ressourcen nicht erneut beeinträchtigen, wenn sie mehrfach ausgeführt werden):
GET
(nullipotent),PUT
,DELETE
body safe idempotent
GET ✗ ✔ ✔
POST ✔ ✗ ✗
PUT ✔ ✗ ✔
DELETE ✗ ✗ ✔
PATCH ✔ ✗ ✗
Folglich können HTTP-Verben mit den CRUD-Funktionen verglichen werden :
Beachten Sie, dass eine PUT
Anforderung die Clients PUT
, die gesamte Ressource mit den aktualisierten Werten zu senden . Um eine Ressource teilweise zu aktualisieren, kann ein PATCH
Verb verwendet werden (siehe Teilweise Aktualisierung einer Ressource? ).
Übliche HTTP-Antwortstatus
Erfolg
- 201 (ERSTELLT) : Ressource wurde erstellt
- 202 (AKZEPTIERT) : Anforderung wurde angenommen, der Prozess wird jedoch noch ausgeführt
- 204 (KEIN INHALT) : Anforderung erfüllt und kein zusätzlicher Inhalt
- Ansonsten: 200 (OK)
Umleitung
- 304 (NICHT MODIFIZIERT) : Der Client kann die zwischengespeicherte Version der angeforderten Ressource verwenden
Kundenfehler
- 401 (UNAUTHORIZED) : Eine anonyme Anforderung greift auf eine geschützte API zu
- 403 (FORBIDDEN) : Eine authentifizierte Anfrage hat nicht genügend Rechte, um auf eine geschützte API zuzugreifen
- 404 (NICHT GEFUNDEN) : Ressource nicht gefunden
- 409 (CONFLICT) : Ressourcenstatus in Konflikt (z. B. ein Benutzer, der versucht, ein Konto mit einer bereits registrierten E-Mail zu erstellen)
- 410 (GONE) : wie 404, aber die Ressource war vorhanden
- 412 (PRECONDITION FAILED) : Anforderung versucht, eine Ressource zu ändern, die sich in einem unerwarteten Zustand befindet
- 422 (UNPROCESSABLE ENTITY) : Request-Payload ist syntaktisch gültig, aber semantisch fehlerhaft (z. B. ein erforderliches Feld, das nicht bewertet wurde)
- 423 (LOCKED) : Ressource ist gesperrt
- 424 (FAILED DEPENDENCY) : Die angeforderte Aktion hing von einer anderen fehlgeschlagenen Aktion ab
- 429 (ZU VIELE ANFORDERUNGEN) : Der Benutzer hat in einer bestimmten Zeit zu viele Anforderungen gesendet
- Ansonsten: 400 (SCHLECHTE ANFRAGE)
Serverfehler
- 501 (NICHT IMPLEMENTIERT) : Der Server unterstützt nicht die zur Erfüllung der Anforderung erforderliche Funktionalität
- 503 (SERVICE UNAVAILABLE) : Der Server kann die Anforderung zurzeit aufgrund einer vorübergehenden Überlastung oder einer geplanten Wartung nicht verarbeiten
- 507 (INSUFFICIENT STORAGE) : Der Server kann die für den erfolgreichen Abschluss der Anforderung erforderliche Repräsentation nicht speichern
- Ansonsten: 500 (INTERNER SERVERFEHLER)
Anmerkungen
Nichts hindert Sie daran, einen Körper zu falschen Antworten hinzuzufügen, um die Ablehnung für die Kunden klarer zu machen. Zum Beispiel ist die 422 (UNPROCESSABLE ENTITY) etwas vage: Der Antworttext sollte den Grund dafür angeben, warum die Entität nicht verarbeitet werden konnte.
HATEOAS
Jede Ressource muss Hypermedia für die Ressourcen bereitstellen, mit denen sie verknüpft ist. Ein Link besteht mindestens aus:
- A
rel
(für rel ation, aka name): beschreibt die Beziehung zwischen der Hauptressource und der verknüpften Ressource. - A
href
: Die URL für die verknüpften Ressourcen.
Zusätzliche Attribute können auch verwendet werden, um bei der Abwertung, beim Aushandeln von Inhalten usw. zu helfen.
Cormac Mulhall erklärt, dass der Client entscheiden sollte, welches HTTP-Verb verwendet werden soll, je nachdem, was er versucht . Im Zweifelsfall sollte die API-Dokumentation Ihnen trotzdem helfen, die verfügbaren Interaktionen mit allen Hypermedien zu verstehen.
Medientypen
Medientypen helfen, selbstbeschreibende Meldungen zu erhalten. Sie spielen die Rolle des Vertrages zwischen Clients und Servern, so dass sie Ressourcen und Hypermedien austauschen können.
Obwohl application/json
und application/xml
recht beliebte Medientypen sind, enthalten sie nicht viel Semantik. Sie beschreiben lediglich die im Dokument verwendete Gesamtsyntax. Es sollten speziellere Medientypen verwendet werden, die die HATEOAS-Anforderungen unterstützen (oder durch Medientypen von Anbietern erweitert werden ), z.
Ein Client teilt einem Server mit, welche Medientypen er kennt, indem er seiner Anfrage den Accept
Header hinzufügt, zum Beispiel:
Accept: application/hal+json
Wenn der Server die angeforderte Ressource in einer solchen Darstellung nicht produzieren kann, gibt er 406 (NOT ACCEPTABLE) zurück . Andernfalls wird der Medientyp im Content-Type
Header der Antwort hinzugefügt, die die dargestellte Ressource enthält. Beispiel:
Content-Type: application/hal+json
Staatenlos> stateful
Warum?
Ein Stateful-Server bedeutet, dass die Clientsitzungen in einem lokalen Speicher mit Serverinstanz gespeichert werden (fast immer in Webserversitzungen). Wenn Sie versuchen, horizontal zu skalieren , wird dies zu einem Problem: Wenn Sie mehrere Serverinstanzen hinter einem Load Balancer ausblenden, wird ein Client beim Anmelden zuerst an Instanz Nr. 1 gesendet, beim Abrufen einer geschützten Ressource anschließend an Instanz Nr. 2 Dann wird die zweite Instanz die Anfrage als anonyme behandeln, da die Clientsitzung lokal in Instanz # 1 gespeichert wurde .
Es wurde gefunden, dass Lösungen zur Lösung dieses Problems gefunden werden (z. B. durch Konfigurieren der Sitzungsreplikation und / oder ständigen Sitzung ). Die REST-Architektur schlägt jedoch einen anderen Ansatz vor: Machen Sie den Server nicht zustandslos, sondern stateless . Laut Fielding :
Jede Anfrage vom Client an den Server muss alle Informationen enthalten, die zum Verständnis der Anfrage erforderlich sind, und kann keinen auf dem Server gespeicherten Kontext nutzen. Der Sitzungsstatus wird daher vollständig auf dem Client gespeichert.
Mit anderen Worten, eine Anforderung muss auf dieselbe Weise behandelt werden, unabhängig davon, ob sie an die Instanz Nr. 1 oder die Instanz Nr. 2 gesendet wird . Aus diesem Grund werden zustandslose Anwendungen als einfacher skalierbar betrachtet .
Wie?
Ein gängiger Ansatz ist die tokenbasierte Authentifizierung , insbesondere bei den trendigen JSON-Webtokens . Beachten Sie, dass JWT immer noch einige Probleme hat, insbesondere in Bezug auf die Ungültigerklärung und die automatische Verlängerung des Ablaufs (z. B. die Funktion " Merken" ).
Seitennotizen
Die Verwendung von Cookies oder Headern (oder irgendetwas anderem) hat nichts damit zu tun, ob der Server zustandsbehaftet oder zustandslos ist: Dies sind nur Medien, die hier zum Transportieren von Token (Sitzungskennung für zustandsbehaftete Server, JWT usw.) verwendet werden, nichts weiter.
Wenn eine RESTful-API nur von Browsern verwendet wird, können Cookies ( HttpOnly and Secure ) sehr praktisch sein, da Browser sie automatisch an ausgehende Anforderungen anhängen. Wenn Sie sich für Cookies entscheiden, sollten Sie auf CSRF achten (eine gute Möglichkeit, dies zu verhindern, besteht darin, dass die Clients denselben eindeutigen geheimen Wert sowohl in einem Cookie als auch in einem benutzerdefinierten HTTP-Header generieren und senden ).
Cachefähige API mit bedingten Anforderungen
Mit dem Kopf der Last-Modified
Der Server kann für die Antworten, die Ressourcen enthalten, die im Cache gespeichert werden können, einen Datum-Header mit dem Datum der Last-Modified
bereitstellen. Kunden sollten dieses Datum dann zusammen mit der Ressource speichern.
Jedes Mal, wenn Clients die API zum Lesen der Ressource anfordern, können sie jetzt einen If-Modified-Since
Header hinzufügen, der das Last-Modified
Datum der letzten Änderung enthält, das sie erhalten und gespeichert haben. Der Server muss dann den Header der Anforderung und das aktuelle Datum der letzten Änderung der Ressource vergleichen. Wenn sie gleich sind, gibt der Server eine 304 (NICHT MODIFIZIERT) mit leerem Rumpf zurück: Der anfragende Client sollte die aktuell zwischengespeicherte Ressource verwenden, über die er verfügt.
Wenn Clients die API zum Aktualisieren der Ressource anfordern (dh mit einem unsicheren Verb), können sie einen If-Unmodified-Since
Header hinzufügen. Dies hilft beim Umgang mit Race-Bedingungen: Wenn der Header und das aktuelle Datum der letzten Änderung unterschiedlich sind, gibt der Server eine 412 (PRECONDITION FAILED) zurück . Der Client sollte dann den neuen Status der Ressource lesen, bevor er erneut versucht, die Ressource zu ändern.
Mit dem ETag
Header
Ein ETag (Entity-Tag) ist eine Kennung für einen bestimmten Status einer Ressource. Dies kann ein MD5-Hash der Ressource für eine starke Validierung oder ein domänenspezifischer Bezeichner für eine schwache Validierung sein .
Im Grunde ist der Prozess derselbe wie beim Last-Modified
Header: Der Server stellt einen ETag
Header für die Antworten bereit, die Ressourcen enthalten, die im Cache gespeichert werden können, und die Clients sollten diesen Bezeichner dann zusammen mit der Ressource speichern.
Dann geben Clients einen If-None-Match
Header an, wenn sie die Ressource mit dem neuesten ETag, den sie erhalten und gespeichert haben, lesen möchten. Der Server kann jetzt ein 304 (NOT MODIFIED) zurückgeben, wenn der Header mit dem tatsächlichen ETag der Ressource übereinstimmt.
Wiederum können Clients einen If-Match
Header bereitstellen, wenn sie die Ressource ändern möchten, und der Server muss einen 412-Wert (PRECONDITION FAILED) zurückgeben, wenn der bereitgestellte ETag nicht mit dem tatsächlichen ETag übereinstimmt.
Zusätzliche Bemerkungen
ETag> Datum
Wenn Kunden in ihren Anforderungen sowohl Datum als auch ETag angeben, muss das Datum ignoriert werden. Ab RFC 7232 ( hier und hier ):
Ein Empfänger MUSS
If-Modified-Since
/If-Unmodified-Since
ignorieren, wenn die Anforderung einIf-None-Match
/If-Match
Headerfeld enthält. Die Bedingung inIf-None-Match
/If-Match
gilt als genauerer Ersatz für die Bedingung inIf-Modified-Since
/If-Unmodified-Since
werden nur für die Interaktion mit älteren Intermediären kombiniert das kannIf-None-Match
/If-Match
nicht implementieren.
Flache ETags
Obwohl es offensichtlich ist, dass die letzten Änderungsdaten zusammen mit den Ressourcen auf der Serverseite beibehalten werden, gibt es mit ETag mehrere Ansätze .
Ein üblicher Ansatz besteht darin, flache ETags zu implementieren: Der Server verarbeitet die Anforderung so, als ob keine bedingten Header gegeben wurden, generiert jedoch nur am Ende das ETag der Antwort, die er gerade zurückgibt (z. B. durch Hashing), und vergleicht es mit dem bereitgestellten. Dies ist relativ einfach zu implementieren, da nur ein HTTP-Interceptor benötigt wird (und je nach Server bereits viele Implementierungen vorhanden sind). Erwähnenswert ist jedoch, dass dieser Ansatz zwar Bandbreite einspart, nicht aber die Serverleistung :
Eine tiefere Implementierung des ETag-Mechanismus könnte potenziell viel größere Vorteile bieten - etwa das Beantworten einiger Anforderungen aus dem Cache und die Notwendigkeit, die Berechnung überhaupt durchzuführen -, aber die Implementierung wäre auf jeden Fall weder so einfach noch so steckbar wie der flache Ansatz hier beschrieben.
Häufige Fehler
Warum sollte ich keine Verben in URLs einfügen?
HTTP ist kein RPC : Was HTTP wesentlich von RPC unterscheidet, besteht darin, dass die Anforderungen an Ressourcen gerichtet sind . URL steht immerhin für Uniform Resource Locator, und eine URL ist eine URI : Uniform Resource Idenfitier. Die URL richtet sich an die Ressource, mit der Sie arbeiten möchten , die HTTP-Methode gibt an, was Sie damit tun möchten . HTTP-Methoden werden auch als Verben bezeichnet : Verben in URLs machen dann keinen Sinn. Beachten Sie, dass HATEOAS-Beziehungen auch keine Verben enthalten sollten, da Links auch auf Ressourcen abzielen.
Wie kann ich eine Ressource teilweise aktualisieren?
Wenn PUT
Anforderungen Clients dazu auffordern, die gesamte Ressource mit den aktualisierten Werten zu senden, kann PUT /users/123
nicht verwendet werden, um beispielsweise die E-Mail eines Benutzers einfach zu aktualisieren. Wie von William Durand in Please erklärt. Patch nicht wie ein Idiot. Es stehen verschiedene REST-kompatible Lösungen zur Verfügung:
- Machen Sie die Eigenschaften der Ressource verfügbar und verwenden Sie die
PUT
Methode zum Senden eines aktualisierten Werts, da diePUT
Spezifikation angibt, dass teilweise Inhaltsaktualisierungen möglich sind, indem Sie auf eine separat identifizierte Ressource mit einem Status abzielen, der einen Teil der größeren Ressource überlappt :
PUT https://example.com/api/v1.2/users/123/email
body:
new.email@example.com
- Verwenden Sie eine
PATCH
Anforderung, die Anweisungen enthält, die beschreiben, wie die Ressource geändert werden muss (z. B. nach dem JSON-Patch ):
PATCH https://example.com/api/v1.2/users/123
body:
[
{ "op": "replace", "path": "/email", "value": "new.email@example.com" }
]
- Verwenden Sie eine
PATCH
Anforderung, die eine teilweise Darstellung der Ressource enthält, wie in dem Kommentar von Matt Chapman vorgeschlagen:
PATCH https://example.com/api/v1.2/users/123
body:
{
"email": "new.email@example.com"
}
Was ist mit Aktionen, die nicht in die Welt der CRUD-Operationen passen?
Zitat von Vinay Sahni in Best Practices für das Design einer pragmatischen RESTful-API :
Hier können die Dinge unscharf werden. Es gibt verschiedene Ansätze:
Strukturieren Sie die Aktion so, dass sie wie ein Feld einer Ressource erscheint. Dies funktioniert, wenn für die Aktion keine Parameter verwendet werden. Beispielsweise könnte eine Aktivierungsaktion einem booleschen
activated
Feld zugeordnet und über einen PATCH an die Ressource aktualisiert werden.Behandle es wie eine Subressource mit RESTful-Prinzipien. Mit der API von GitHub können Sie beispielsweise einen Kern mit
PUT /gists/:id/star
und einen Stern mitDELETE /gists/:id/star
.Manchmal haben Sie wirklich keine Möglichkeit, die Aktion einer vernünftigen REST-Struktur zuzuordnen. Beispielsweise ist eine Suche nach mehreren Ressourcen nicht wirklich sinnvoll, um auf den Endpunkt einer bestimmten Ressource angewendet zu werden. In diesem Fall wäre
/search
am sinnvollsten, obwohl es keine Ressource ist. Dies ist in Ordnung - tun Sie einfach das Richtige aus Sicht des API-Konsumenten und stellen Sie sicher, dass es eindeutig dokumentiert ist, um Verwirrung zu vermeiden.
Übliche Praktiken
API ist dokumentiert. Es stehen Tools zur Verfügung, die Sie beim Erstellen Ihrer Dokumentation unterstützen, z. B. Swagger oder Spring REST Docs .
Die API wird entweder über Header oder über die URL versioniert :
https://example.com/api/v1.2/blogs/123/articles
^^^^
- Ressourcen haben mehrere Namen :
https://example.com/api/v1.2/blogs/123/articles
^^^^^ ^^^^^^^^
- URLs verwenden Kebab- Großbuchstaben (Wörter werden durch Leerzeichen getrennt und getrennt):
https://example.com/api/v1.2/quotation-requests
^^^^^^^^^^^^^^^^^^
- HATEOAS stellt eine "Selbst" -Link zu Ressourcen bereit, die auf sich selbst abzielen:
{
...,
_links: {
...,
self: { href: "https://example.com/api/v1.2/blogs/123/articles/789" }
^^^^
}
}
- HATEOAS-Beziehungen verwenden lowerCamelCase (die Wörter werden mit einem Kleinbuchstaben groß geschrieben, dann mit Ausnahme der ersten großgeschrieben und Leerzeichen weggelassen), damit JavaScript-Clients die Punktnotation verwenden können, wobei die JavaScript-Namenskonventionen beim Zugriff auf die Links beachtet werden:
{
...,
_links: {
...,
firstPage: { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=1&pageSize=25" }
^^^^^^^^^
}
}
Blogs-Verwaltung über eine RESTful-HTTP-API
Die folgenden Beispiele verwenden HAL zum Ausdrücken von HATEOAS und verwenden Folgendes:
- CURIE (Compact URI): Wird verwendet, um Links zur API-Dokumentation bereitzustellen
- URI-Vorlagen : URI, der Parameter enthält, die ersetzt werden müssen, bevor der URI aufgelöst wird
Holen Sie sich Blog 123
Anfordern
GET https://example.com/api/v1.2/blogs/123
headers:
Accept: application/hal+json
Antwort
status: 200 (OK)
headers:
Content-Type: application/hal+json
body:
{
"id": 123,
"title": "The blog title",
"description": "The blog description",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123" },
"doc:articles": { "href": "https://example.com/api/v1.2/blogs/123/articles{?pageIndex,pageSize}", "templated": true }
}
}
Erstellen Sie einen neuen Artikel in Blog 123
Anfordern
POST https://example.com/api/v1.2/blogs/123/articles
headers:
Content-Type: application/json
Accept: application/hal+json
X-Access-Token: XYZ
body:
{
"title": "The title 2",
"content": "The content 2"
}
Antwort
status: 201 (CREATED)
headers:
Content-Type: application/hal+json
body:
{
"id": 789,
"title": "The title 2",
"content": "The content 2",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
}
}
Erhalten Sie Artikel 789 von Blog 123
Anfordern
GET https://example.com/api/v1.2/blogs/123/articles/789
headers:
Accept: application/hal+json
Antwort
status: 200 (OK)
headers:
Content-Type: application/hal+json
body:
{
"id": 789,
"title": "The title 2",
"content": "The content 2",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
}
}
Holen Sie sich die vierte Seite von 25 Artikeln des Blogs 123
Anfordern
GET https://example.com/api/v1.2/blogs/123/articles?pageIndex=4&pageSize=25
headers:
Accept: application/hal+json
Antwort
status: 200 (OK)
headers:
Content-Type: application/hal+json
body:
{
"pageIndex": 4,
"pageSize": 25,
"totalPages": 26,
"totalArticles": 648,
"_link": {
"firstPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=1&pageSize=25" },
"previousPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=3&pageSize=25" },
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=4&pageSize=25" },
"nextPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=5&pageSize=25" },
"lastPage": { "href": "https://example.com/api/v1.2/blogs/123/articles?pageIndex=26&pageSize=25" }
},
"_embedded": [
{
...
}, {
"id": 456,
"title": "The title 1",
"content": "The content 1",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/456" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/456/comments{?pageIndex,pageSize}", "templated": true }
}
}, {
"id": 789,
"title": "The title 2",
"content": "The content 2",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
}
}, {
...
}
]
}
Aktualisieren Sie Artikel 789 von Blog 123
Anfordern
PUT https://example.com/api/v1.2/blogs/123/articles/789
headers:
Content-Type: application/json
Accept: application/hal+json
X-Access-Token: XYZ
body:
{
"id": 789,
"title": "The title 2 updated",
"content": "The content 2 updated"
}
Antwort
status: 200 (OK)
headers:
Content-Type: application/hal+json
body:
{
"id": 789,
"title": "The title 2 updated",
"content": "The content 2 updated",
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"self": { "href": "https://example.com/api/v1.2/blogs/123/articles/789" },
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" },
"doc:comments": { "href": "https://example.com/api/v1.2/blogs/123/articles/789/comments{?pageIndex,pageSize}", "templated": true }
}
}
Anmerkungen
- Der Bezeichner, der zur Identifizierung der zu aktualisierenden Ressource verwendet wird, ist der in der URL : Der im Haupttext (falls vorhanden) muss ignoriert werden.
- Wenn eine
PUT
Anforderung die gesamte Ressource aktualisiert, hätte dercontent
der persistierten Ressource entfernt werden müssen, wenn keincontent
gesendet worden wäre.
Artikel 789 des Blogs 123 löschen
Anfordern
DELETE https://example.com/api/v1.2/blogs/123/articles/789
headers:
Accept: application/hal+json
X-Access-Token: XYZ
Antwort
status: 204 (NO CONTENT)
headers:
Content-Type: application/hal+json
body:
{
"_links": {
"curies": [{ "name": "doc", "href": "https://example.com/docs/{rel}", "templated": true }],
"doc:blog": { "href": "https://example.com/api/v1.2/blogs/123", "title": "The blog title" }
}
}
Verstoß gegen REST
<stock>
<add>
<item>
<name>Milk</name>
<quantity>2</quantity>
</item>
</add>
</stock>
Wenn Sie diesen Körper einer Ressource wie /stocks/123
zuordnen, verstößt dies gegen die Idee hinter REST. Während dieser Rumpf put
und alle erforderlichen Informationen enthält, enthält er auch einen Methodenaufruf, der irgendwo add
wenn der Rumpf verarbeitet wird. Im Anschluss an REST würde man den item
nach /stocks/123/items/
.