REST API - warum PUT DELETE POST GET verwenden?

155

Also habe ich einige Artikel zum Erstellen von REST-APIs durchgesehen. Und einige von ihnen schlagen vor, alle Arten von HTTP-Anforderungen zu verwenden: wie PUT DELETE POST GET. Wir würden zum Beispiel index.php erstellen und die API folgendermaßen schreiben:

$method = $_SERVER['REQUEST_METHOD'];
$request = split("/", substr(@$_SERVER['PATH_INFO'], 1));

switch ($method) {
  case 'PUT':
    ....some put action.... 
    break;
  case 'POST':
    ....some post action.... 
    break;
  case 'GET':
    ....some get action.... 
    break;
  case 'DELETE':
    ....some delete action.... 
    break;
}

OK, selbstverständlich - ich weiß (noch) nicht viel über Webdienste. Wäre es nicht einfacher, JSON- Objekte einfach über reguläres POSToder GET(das den Methodennamen und alle Parameter enthält) zu akzeptieren und dann auch in JSON zu antworten. Wir können einfach über PHPs serialisieren / deserialisieren json_encode()und json_decode()mit diesen Daten machen, was wir wollen, ohne mit verschiedenen HTTP-Anforderungsmethoden umgehen zu müssen.

Vermisse ich etwas

UPDATE 1:

Ok - nachdem ich verschiedene APIs durchgesehen und viel über XML-RPC , JSON-RPC , SOAP und REST gelernt hatte , kam ich zu dem Schluss, dass diese Art von API solide ist. Tatsächlich verwendet Stack Exchange diesen Ansatz auf ihren Websites ziemlich genau, und ich denke, dass diese Leute wissen, was sie mit Stack Exchange API tun .

Stann
quelle
4
Warum eine JSON-Nutzlast erzwingen? Was ist, wenn es kein JSON gibt und es ein einfaches altes GET ist?
Mike DeSimone

Antworten:

200

Die Idee von RE Präsentations S tate T ransfer geht es nicht um Daten auf einfachste Weise möglich , den Zugriff.

Sie haben vorgeschlagen, Post-Anfragen für den Zugriff auf JSON zu verwenden. Dies ist eine absolut gültige Methode für den Zugriff auf / die Bearbeitung von Daten.

REST ist eine Methode für den sinnvollen Zugriff auf Daten. Wenn Sie eine Anfrage in REST sehen, sollte sofort klar sein, was mit den Daten passiert.

Beispielsweise:

GET: /cars/make/chevrolet

wird wahrscheinlich eine Liste von Chevy-Autos zurückgeben. Eine gute REST-API kann sogar einige Ausgabeoptionen in den Querystring einbinden, wie ?output=jsonoder ?output=htmldie es dem Accessor ermöglichen würden, zu entscheiden, in welchem ​​Format die Informationen codiert werden sollen.

Nach einem wenig darüber nachzudenken , wie man vernünftigerweise incorporate Typisierung in einen REST - API, habe ich festgestellt , dass der beste Weg , um die Art der Daten , über die bereits vorhandene Dateierweiterung würde explizit angeben, wie etwa .js, .json, .html, oder .xml. Eine fehlende Dateierweiterung würde standardmäßig das Standardformat verwenden (z. B. JSON). Eine nicht unterstützte Dateierweiterung kann einen 501 Not ImplementedStatuscode zurückgeben .

Ein anderes Beispiel:

POST: /cars/
{ make:chevrolet, model:malibu, colors:[red, green, blue, grey] }

wird wahrscheinlich einen neuen Chevy Malibu in der Datenbank mit den dazugehörigen Farben erstellen. Ich sage wahrscheinlich, da die REST-API nicht direkt mit der Datenbankstruktur verknüpft sein muss. Es ist nur eine Maskierungsschnittstelle, damit die wahren Daten geschützt werden (denken Sie an Accessoren und Mutatoren für eine Datenbankstruktur).

Jetzt müssen wir uns dem Thema Idempotenz zuwenden . Normalerweise implementiert REST CRUD über HTTP. HTTP verwendet GET, PUT, POSTund DELETEfür die Anforderungen.

Eine sehr vereinfachte Implementierung von REST könnte das folgende CRUD-Mapping verwenden:

Create -> Post
Read   -> Get
Update -> Put
Delete -> Delete

Bei dieser Implementierung gibt es ein Problem: Post ist als nicht idempotente Methode definiert. Dies bedeutet, dass nachfolgende Aufrufe derselben Post-Methode zu unterschiedlichen Serverzuständen führen. Get, Put und Delete sind idempotent. Dies bedeutet, dass ein mehrmaliger Aufruf zu einem identischen Serverstatus führen sollte.

Dies bedeutet, dass eine Anfrage wie:

Delete: /cars/oldest

könnte tatsächlich implementiert werden als:

Post: /cars/oldest?action=delete

Wohingegen

Delete: /cars/id/123456

führt zu demselben Serverstatus, wenn Sie ihn einmal oder 1000 Mal aufrufen.

Eine bessere Möglichkeit, das Entfernen des oldestArtikels zu handhaben, besteht darin, Folgendes anzufordern:

Get: /cars/oldest

und verwenden Sie die IDaus den resultierenden Daten, um eine deleteAnfrage zu stellen:

Delete: /cars/id/[oldest id]

Ein Problem bei dieser Methode wäre, wenn /carszwischen der /oldestAnforderung und der Ausgabe ein weiteres Element hinzugefügt würde delete.

zzzzBov
quelle
3
@Andre ist eine Kombination aus mehreren Gründen: Das Befolgen der HTTP-Richtlinien bedeutet, dass Sie (wahrscheinlich) weniger Abwärtskompatibilitätsprobleme haben, wenn sich die Dinge ändern. Die Verwendung eines HTML-Formulars über POST warnt den Benutzer vor mehreren Übermittlungen derselben Daten (dies dient dazu, eine nicht idempotente Transaktion zu verhindern). Das Befolgen einer genau definierten Best Practice ist die beste Vorgehensweise. Rest ist nicht für eine bestimmte Implementierung definiert, sodass Sie ihn nach Belieben verwenden können. Ich würde vorschlagen, alle HTTP-Fehlercodes und Anforderungsmethoden zu nutzen, aber Sie dürfen es tun, wie Sie wollen
zzzzBov
4
Das Problem mit dieser Antwort (es ist eine anständige Antwort, aber nicht vollständig) ist, dass sie nicht die Hauptfrage anspricht, die er gestellt hat: Warum Sie HTTP-Verben und den URI anstelle von benutzerdefinierten JSON-Daten verwenden (möglicherweise eine Art von JSON-basierte API-Aufrufsyntax). Sie können Ihre benutzerdefinierte JSON-Syntax so gestalten, dass "sofort ... angezeigt wird, was mit den Daten geschieht". Was Sie nicht tun können, ist einfach integrierte Funktionen und Netzwerkebenen über HTTP zu verwenden, wie Sie es mit einer API können, die alle REST-Konventionen befolgt. Natürlich nicht, dass meine Antwort perfekt ist;)
Merlyn Morgan-Graham
4
@Andre: Die Beispiele, die der Wiki-Eintrag verwendet, sind Authentifizierung, Caching und Aushandlung von Inhaltstypen. Jetzt, wo ich mehr darüber nachdenke, können Sie diese möglicherweise mit Schnittstellen im RPC-Stil verwenden, aber die Versuchung besteht häufig darin, Ihr eigenes System von Grund auf neu zu implementieren oder eine Integration in ein vorhandenes System zu codieren. Mit REST können Sie die integrierte Integration verwenden und auf dem Webserver verwalten. Dies bedeutet eine lockere Kopplung, was bedeutet, dass Sie weniger implementieren müssen, und bedeutet, dass Ihre App viel flexibler ist, um Optionen in Zukunft mit geringeren Auswirkungen auf Code und Tests zu ändern.
Merlyn Morgan-Graham
10
Wie wäre es mit GET: / cars / älteste anstelle von DELETE: / cars / älteste, gefolgt von einem DELETE? Auf diese Weise haben Sie zwei separat idempotente Befehle.
Neil
3
+1; Ich bin damit einverstanden, dass dies eine gute Antwort ist (ich gehe es noch einmal aus Spaß und Gewinn durch). POST: /cars/oldestein Ersatz für ein DELETE zu sein, macht nicht viel Sinn. So etwas wie - POST: /cars/oldest/deletekönnte, obwohl ich denke, dass mir Neils Lösung besser gefällt. Der einzige Vorteil, den ein direktes Löschen gegenüber seiner Lösung "get-id-delete-id" bietet, ist die Atomizität. Ich möchte eine klare geschäftliche Rechtfertigung mit einem nicht erfundenen Szenario, bevor ich so etwas implementiere. Sie müssen nicht alle Verben für alle Objekte / URLs unterstützen.
Merlyn Morgan-Graham
39

Dies ist eine Sicherheits- und Wartbarkeitsfrage.

sichere Methoden

Wann immer möglich, sollten Sie "sichere" (unidirektionale) Methoden wie GET und HEAD verwenden, um potenzielle Sicherheitslücken zu begrenzen.

idempotente Methoden

Wann immer möglich, sollten Sie "idempotente" Methoden wie GET, HEAD, PUT und DELETE verwenden, die keine Nebenwirkungen haben können und daher weniger fehleranfällig / leichter zu kontrollieren sind.

Quelle

Markus
quelle
1
Entschuldigung, aber wie sind die idempotenten Methoden PUT und DELETE? Sie beeinflussen den Status des Servers und seiner Daten!
Mahmoud Al-Qudsi
27
@Computer: Wenn Sie denselben PUT oder denselben DELETE-Vorgang ausführen, erhalten Sie denselben Endzustand. Das ist es, was "idempotent" bedeutet.
Ignacio Vazquez-Abrams
4
Zur weiteren Verdeutlichung: Eine Operation F ist idempotent, wenn sowohl ihre einzelne Anwendung als auch ihre mehreren aufeinander folgenden Anwendungen dasselbe Ergebnis zurückgeben. Genauer gesagt ist F genau dann idempotent, wenn F (x) = F (F (x)). Zum Beispiel ist Löschen idempotent, denn wenn Sie ein Element einmal oder mehrmals löschen, ist das Ergebnis dasselbe: Das Element wird nur einmal mit der ersten Anwendung zum Löschen gelöscht, und in der zweiten oder dritten Anwendung zum Löschen geschieht nichts.
Qartal
1
In Bezug auf die Erstellung werden jedoch (wahrscheinlich) zwei Datensätze erstellt, wenn Sie einen neuen Datensatz mit einem Befehl create erstellen und denselben Befehl erneut ausgeben (obwohl beide dieselben Informationen widerspiegeln).
Qartal
qartal - Ihre funktionale Definition für idempotent sollte 'F (X) = F (X) F (X)' sein. Gute Möglichkeit, es auszudrücken.
Gerard ONeill
26

Kurz gesagt, REST betont Substantive gegenüber Verben. Wenn Ihre API komplexer wird, fügen Sie mehr Dinge hinzu als mehr Befehle.

Neil
quelle
2
Ich hatte ein bisschen Probleme, mich darum zu kümmern. Dieser Beitrag ( lornajane.net/posts/2013/… ), dass das Verb von der HTTP-Anfrage stammen sollte, damit der URI dann nur Substantive enthalten sollte, hat es ein bisschen für mich
geklärt
9

Sie haben gefragt :

Wäre es nicht einfacher, ein JSON-Objekt einfach über normales $ _POST zu akzeptieren und dann auch in JSON zu antworten?

Aus der Wikipedia auf REST :

RESTful-Anwendungen maximieren die Nutzung der bereits vorhandenen, genau definierten Schnittstelle und anderer integrierter Funktionen, die vom ausgewählten Netzwerkprotokoll bereitgestellt werden, und minimieren das Hinzufügen neuer anwendungsspezifischer Funktionen

Nach dem, was ich (wenig) gesehen habe, glaube ich, dass dies normalerweise erreicht wird, indem die Verwendung vorhandener HTTP-Verben maximiert und ein URL-Schema für Ihren Dienst entworfen wird, das so leistungsfähig und selbstverständlich wie möglich ist.

Benutzerdefinierte Datenprotokolle (auch wenn sie auf Standardprotokollen wie SOAP oder JSON aufbauen) werden nicht empfohlen und sollten minimiert werden, um der REST-Ideologie am besten zu entsprechen.

SOAP RPC über HTTP hingegen ermutigt jeden Anwendungsentwickler, ein neues und willkürliches Vokabular von Substantiven und Verben (z. B. getUsers (), savePurchaseOrder (...)) zu definieren, das normalerweise dem HTTP-Verb 'POST' überlagert wird. Dies ignoriert viele der vorhandenen Funktionen von HTTP wie Authentifizierung, Caching und Aushandlung von Inhaltstypen und kann dazu führen, dass der Anwendungsdesigner viele dieser Funktionen im neuen Vokabular neu erfindet.

Die tatsächlichen Objekte, mit denen Sie arbeiten, können in einem beliebigen Format vorliegen. Die Idee ist, so viel HTTP wie möglich wiederzuverwenden, um Ihre Vorgänge verfügbar zu machen, die der Benutzer für diese Ressource ausführen möchte (Abfragen, Statusverwaltung / Mutation, Löschen).

Sie haben gefragt :

Vermisse ich etwas

Über REST und die URI-Syntax / HTTP-Verben selbst gibt es noch viel mehr zu wissen. Zum Beispiel sind einige der Verben idempotent, andere nicht. Ich habe in Ihrer Frage nichts darüber gesehen, also habe ich nicht versucht, mich darauf einzulassen. Die anderen Antworten und Wikipedia haben beide viele gute Informationen.

Außerdem gibt es viel zu lernen über die verschiedenen Netzwerktechnologien, die auf HTTP basieren und die Sie nutzen können, wenn Sie eine wirklich erholsame API verwenden. Ich würde mit der Authentifizierung beginnen.

Merlyn Morgan-Graham
quelle
8

In Bezug auf die Verwendung der Erweiterung zum Definieren des Datentyps. Ich habe festgestellt, dass die MailChimp-API dies tut, halte dies jedoch nicht für eine gute Idee.

GET /zzz/cars.json/1

GET /zzz/cars.xml/1

Mein Sound scheint eine gute Idee zu sein, aber ich denke, ein "älterer" Ansatz ist besser - die Verwendung von HTTP-Headern

GET /xxx/cars/1
Accept: application/json

Auch HTTP-Header sind viel besser für die datenübergreifende Kommunikation (falls jemals jemand sie benötigen würde)

POST /zzz/cars
Content-Type: application/xml     <--- indicates we sent XML to server
Accept: application/json          <--- indicates we want get data back in JSON format  
Pawel Cioch
quelle
4

Vermisse ich etwas

Ja. ;-);

Dieses Phänomen besteht aufgrund der einheitlichen Schnittstellenbeschränkung . REST verwendet bereits vorhandene Standards, anstatt das Rad neu zu erfinden. Der HTTP-Standard hat sich bereits als hoch skalierbar erwiesen (das Web funktioniert eine Weile). Warum sollten wir etwas reparieren, das nicht kaputt ist?!

Hinweis: Die einheitliche Schnittstellenbeschränkung ist wichtig, wenn Sie die Clients vom Dienst entkoppeln möchten. Es ähnelt dem Definieren von Schnittstellen für Klassen, um sie voneinander zu entkoppeln. Ofc. Hier besteht die einheitliche Schnittstelle aus Standards wie HTTP , MIME-Typen , URI , RDF , Vokabeln für verknüpfte Daten , Hydra- Vokabeln usw.

inf3rno
quelle
2

Gute Semantik ist wichtig für die Programmierung.

Die Verwendung weiterer Methoden neben GET / POST ist hilfreich, da dies die Lesbarkeit Ihres Codes verbessert und die Wartung erleichtert.

Warum?

Weil Sie wissen, dass GET Daten von Ihrer API abruft. Sie wissen, dass POST Ihrem System neue Daten hinzufügt. Sie wissen, dass PUT Aktualisierungen vornehmen wird. DELETE löscht Zeilen usw. usw.

Normalerweise strukturiere ich meine RESTFUL-Webdienste so, dass ich einen Funktionsrückruf habe, der den gleichen Namen wie die Methode hat.

Ich benutze PHP, also benutze ich function_exists (ich denke es heißt). Wenn die Funktion nicht existiert, werfe ich eine 405 (METHODE NICHT ERLAUBT).

HumbleWebDev
quelle
2

Bill Venners: In Ihrem Blog-Beitrag mit dem Titel "Warum REST fehlgeschlagen ist" sagten Sie, dass wir alle vier HTTP-Verben benötigen - GET, POST, PUT und DELETE - und beklagten, dass Browser-Anbieter nur GET und POST benötigen. "Warum brauchen wir alle vier? Verben? Warum reichen GET und POST nicht aus?

Elliotte Rusty Harold: In HTTP gibt es vier grundlegende Methoden: GET, POST, PUT und DELETE. GET wird die meiste Zeit verwendet. Es wird für alles verwendet, was sicher ist und keine Nebenwirkungen verursacht. GET kann mit einem Lesezeichen versehen, zwischengespeichert, verknüpft und über einen Proxyserver übertragen werden. Es ist eine sehr mächtige Operation, eine sehr nützliche Operation.

Im Gegensatz dazu ist POST vielleicht die leistungsstärkste Operation. Es kann alles machen. Es gibt keine Grenzen, was passieren kann, und deshalb muss man sehr vorsichtig damit sein. Sie setzen kein Lesezeichen. Sie zwischenspeichern es nicht. Sie holen es nicht vor. Mit einem POST machen Sie nichts, ohne den Benutzer zu fragen. Willst du das machen Wenn der Benutzer die Taste drückt, können Sie Inhalte veröffentlichen. Sie werden jedoch nicht alle Schaltflächen auf einer Seite anzeigen und sie nach dem Zufallsprinzip drücken. Im Gegensatz dazu können Browser alle Links auf der Seite anzeigen und vorab abrufen oder diejenigen vorab abrufen, von denen sie glauben, dass sie am wahrscheinlichsten als Nächstes befolgt werden. Tatsächlich haben einige Browser, Firefox-Erweiterungen und verschiedene andere Tools versucht, dies zu dem einen oder anderen Zeitpunkt zu tun.

PUT und DELETE befinden sich in der Mitte zwischen GET und POST. Der Unterschied zwischen PUT oder DELETE und POST besteht darin, dass PUT und DELETE * idempotent sind, während POST dies nicht ist. PUT und DELETE können bei Bedarf wiederholt werden. Angenommen, Sie versuchen, eine neue Seite auf eine Site hochzuladen. Angenommen, Sie möchten eine neue Seite unter erstellen http://www.example.com/foo.htmlGeben Sie also Ihren Inhalt ein und fügen Sie ihn unter dieser URL ein. Der Server erstellt diese Seite unter der von Ihnen angegebenen URL. Nehmen wir nun an, Ihre Netzwerkverbindung wird aus irgendeinem Grund unterbrochen. Sie sind sich nicht sicher, ob die Anfrage durchgekommen ist oder nicht? Vielleicht ist das Netzwerk langsam. Möglicherweise gab es ein Proxy-Server-Problem. Es ist also vollkommen in Ordnung, es noch einmal oder noch einmal zu versuchen - so oft Sie möchten. Weil das zehnmalige Einfügen desselben Dokuments in dieselbe URL nicht anders ist als das einmalige Einfügen. Gleiches gilt für DELETE. Sie können etwas zehnmal LÖSCHEN, und das entspricht dem einmaligen Löschen.

Im Gegensatz dazu kann POST dazu führen, dass jedes Mal etwas anderes passiert. Stellen Sie sich vor, Sie verlassen einen Online-Shop, indem Sie auf die Schaltfläche "Kaufen" klicken. Wenn Sie diese POST-Anfrage erneut senden, können Sie möglicherweise ein zweites Mal alles in Ihrem Warenkorb kaufen. Wenn Sie es erneut senden, haben Sie es ein drittes Mal gekauft. Aus diesem Grund müssen Browser sehr vorsichtig sein, wenn sie POST-Vorgänge ohne ausdrückliche Zustimmung des Benutzers wiederholen, da POST zwei Dinge verursachen kann, wenn Sie es zweimal tun, drei Dinge, wenn Sie es dreimal tun. Bei PUT und DELETE gibt es einen großen Unterschied zwischen null und eins, aber keinen Unterschied zwischen einer und zehn.

Bitte besuchen Sie die URL für weitere Details. http://www.artima.com/lejava/articles/why_put_and_delete.html

Aktualisieren:

Idempotente Methoden Eine idempotente HTTP-Methode ist eine HTTP-Methode, die ohne unterschiedliche Ergebnisse mehrmals aufgerufen werden kann. Es spielt keine Rolle, ob die Methode nur einmal oder zehnmal aufgerufen wird. Das Ergebnis sollte das gleiche sein. Dies gilt wiederum nur für das Ergebnis, nicht für die Ressource selbst. Dies kann weiterhin manipuliert werden (wie ein Aktualisierungszeitstempel, vorausgesetzt, diese Informationen werden nicht in der (aktuellen) Ressourcendarstellung geteilt.

Betrachten Sie die folgenden Beispiele:

a = 4;

a ++;

Das erste Beispiel ist idempotent: Egal wie oft wir diese Anweisung ausführen, a wird immer 4 sein. Das zweite Beispiel ist nicht idempotent. Das 10-fache Ausführen führt zu einem anderen Ergebnis als das 5-fache Ausführen. Da beide Beispiele den Wert von a ändern, sind beide nicht sichere Methoden.

Bimal Das
quelle
1
Sollte POST für das Beispiel einer neuen Seite nicht auf diese Weise verwendet werden, während PUT für ein Update verwendet wird? Das Erstellen einer neuen Seite ist ein Prozess, bei dem jedes Mal ein neues Ergebnis erstellt wird, während dieselbe Bearbeitung beliebig oft wiederholt werden kann, wobei jedes Mal dasselbe Ergebnis angezeigt wird. Gute Formulierung und Erklärung.
Spyryto
0

Grundsätzlich ist REST ( Wiki ):

  1. Client-Server-Architektur
  2. Staatenlosigkeit
  3. Cachefähigkeit
  4. Schichtsystem
  5. Code on Demand (optional)
  6. Einheitliche Schnittstelle

REST ist kein Protokoll, es sind Prinzipien. Verschiedene Uris und Methoden - jemand, der als Best Practices bezeichnet wird.

MAX
quelle