Heim  >  Artikel  >  REST- und HTTP-Semantik

REST- und HTTP-Semantik

百草
百草Original
2024-09-11 14:18:20977Durchsuche

Roy Fielding hat REST als seine Doktorarbeit erstellt. 

REST- und HTTP-Semantik

Nachdem ich es gelesen habe, würde ich es auf drei Grundelemente reduzieren:

  1. Ein Dokument, das den Objektstatus beschreibt

  2. Ein Transportmechanismus zur Übertragung des Objektzustands zwischen Systemen hin und her

  3. Eine Reihe von Operationen, die am Zustand ausgeführt werden sollen

Obwohl Roy sich ausschließlich auf HTTP konzentrierte, verstehe ich nicht, warum nicht ein anderer Transport verwendet werden könnte. Hier sind einige Beispiele:

  • Mounten Sie eine WebDAV-Freigabe (WebDAV ist eine HTTP-Erweiterung und verwendet daher immer noch HTTP). Kopieren Sie eine Tabelle (.xls, .xlsx, .csv, .ods) in den bereitgestellten Ordner, wobei jede Zeile den neuen/aktualisierten Status enthält. Der Vorgang des Kopierens in die Freigabe gibt den Upserting-Vorgang an, der Name der Datei gibt den Datentyp an und die Spalten sind die Felder. Der Server antwortet mit (Dokumentname)-status.(Dokumentsuffix), das einen Schlüssel für jede Zeile, einen Status und möglicherweise eine Fehlermeldung bereitstellt. In diesem Fall macht es keinen Sinn, Daten anzufordern.

  • Verwenden Sie gRPC. Das übertragene Objekt ist das Dokument, HTTP ist der Transport und der Name der Remote-Methode ist die Operation. Daten können sowohl bereitgestellt als auch angefordert werden.

  • Verwenden Sie FTP. Ähnlich wie WebDAV ist es dateibasiert. Der PUT-Befehl führt ein Upsering aus und der GET-Befehl fordert an. GET stellt nur einen Dateinamen bereit und stellt daher im Allgemeinen alle Daten des angegebenen Typs bereit. Es ist möglich, spezielle Dateinamen zuzulassen, die auf einen hartcodierten Filter hinweisen, um eine Teilmenge von Daten abzurufen.

Wenn ich REST-Implementierungen in freier Wildbahn sehe, folgen sie oft nicht dem grundlegenden HTTP Semantik, und ich habe nie eine Erklärung dafür gesehen, sondern nur eine Menge unterschiedlicher Meinungen. Keines davon, das ich gefunden habe, bezog sich auf den RFC. Die meisten scheinen zu glauben, dass:

  • POST = Erstellen

  • PUT = Das gesamte Dokument aktualisieren

  • PATCH = Einen Teil eines Dokuments aktualisieren

  • GET = Das gesamte Dokument abrufen

Dies steht im Widerspruch zu den HTTP-Angaben zu POST und PUT :

  • PUT ist „erstellen“ oder „aktualisieren“. GET gibt im Allgemeinen alles zurück, was zuletzt PUT war. Wenn PUT erstellt wird, MUSS es 201 Erstellt zurückgeben. Wenn PUT aktualisiert wird, MUSS es 200 OK oder 204 No Content zurückgeben. Der RFC schlägt vor, dass der Inhalt für 200 OK eines PUT der Status der Aktion sein sollte. Ich denke, dass es im Fall von SQL in Ordnung wäre, die neue Zeile aus einer SELECT-Anweisung zurückzugeben. Dies hat den Vorteil, dass alle generierten Spalten an den Aufrufer zurückgegeben werden, ohne dass ein separater GET durchgeführt werden muss.

  • POST verarbeitet eine Ressource gemäß ihrer eigenen Semantik. In älteren RFCs hieß es, dass POST für Untergebene einer Ressource bestimmt sei. Alle Versionen geben das Beispiel der Veröffentlichung eines Artikels auf einer Mailingliste; In allen Versionen heißt es, dass „201 Created“ zurückgegeben werden sollte, wenn eine Ressource erstellt wird.

Ich würde behaupten, dass „POST“ eigentlich Folgendes bedeutet:

  • Jede Datenmanipulation außer Erstellen, vollständige/teilweise Aktualisierung oder Löschen

  • Jeder Vorgang, der keine Datenmanipulation ist, wie zum Beispiel:

  • Führen Sie a aus Volltextsuche nach Zeilen, die mit einer Phrase übereinstimmen.

  • Generieren Sie ein GIS-Objekt zur Anzeige auf einer Karte.

Das Wort MUSS bedeutet Ihr Die Implementierung ist nur dann HTTP-kompatibel, wenn Sie die Anweisungen befolgen. Die Verwendung von PUT nur für Updates wird offensichtlich nichts kaputt machen, nur weil es nicht RFC-kompatibel ist. Wenn Sie Clients bereitstellen, die alle Details des Sendens/Empfangens von Daten verwalten, spielt es für den Benutzer des Clients keine große Rolle, welche Verben verwendet werden.

Ich bin der Typ, der einen Grund dafür haben möchte Nichteinhaltung des RFC. Ich habe nie verstanden, wie wichtig es ist, Erstellen und Aktualisieren in REST-APIs zu trennen, genauso wenig wie in Web-Apps. Denken Sie an Handy-Apps wie Kalendertermine, Notizen, Kontakte usw.:

  • „Erstellen“ bedeutet das Klicken auf das Plus-Symbol, das ein neues Formular mit leeren oder Standardwerten anzeigt.

  • „Aktualisieren“ bedeutet, ein Objekt auszuwählen und auf das Stiftsymbol zu klicken, wodurch ein Eingabeformular mit aktuellen Werten angezeigt wird.

  • Sobald das Eingabeformular angezeigt wird, wird es angezeigt funktioniert in Bezug auf Feldvalidierungen genauso.

Warum sollten sich REST-APIs und Web-Frontends also von Handy-Apps unterscheiden? Wenn es für Telefonbenutzer hilfreich ist, das gleiche Dateneingabeformular für „Erstellen“ und „Aktualisieren“ zu erhalten, wäre es dann nicht genauso hilfreich für API- und Webbenutzer?

Wenn Sie sich für die Verwendung von „PUT“ entscheiden „erstellen“ oder „aktualisieren“ und Sie SQL als Speicher verwenden, verfügen die meisten Anbieter über eine Art Upsert-Abfrage. Leider hilft das nicht bei der Entscheidung, wann „200 OK“ oder „201 erstellt“ zurückgegeben werden soll. Sie müssten sich die Informationen ansehen, die Ihr Treiber bereitstellt, wenn eine DML-Abfrage ausgeführt wird, um eine Möglichkeit zu finden, bei einem Upsert zwischen Einfügen und Aktualisieren zu unterscheiden, oder eine andere Abfragestrategie verwenden. 

Ein einfaches Beispiel wäre die Durchführung eines Aktualisierungssatzes ... wobei pk-Spalte = pk-Wert ist. Wenn eine Zeile betroffen war, ist die Zeile vorhanden und wurde aktualisiert. Andernfalls existiert die Zeile nicht und es ist eine Einfügung erforderlich. Auf Postgres können Sie die RETURNING-Klausel nutzen, die tatsächlich alles zurückgeben kann, nicht nur Zeilendaten, wie folgt:

SQL VALUES (...) ON CONFLICT() DO UPDATE SET ( ...) RETURNING (SELECT COUNT() FROMWHERE=) existiert" data-lang="text/x-sql" style="box-sizing: border-box;">1

INSERT INTO <table>
VALUES (...)
ON CONFLICT(<pk column>) DO
UPDATE SET (...)
RETURNING (SELECT COUNT(<pk column>) FROM <table> WHERE <pk column> = <pk value>) exists

Das Geniale daran ist:

  • Die Unterauswahl in der RETURNING-Klausel wird zuerst ausgeführt und bestimmt, ob die Zeile vorhanden ist, bevor die Abfrage INSERT ON CONFLICT UPDATE ausgeführt wird. Das Ergebnis der Abfrage ist eine Spalte mit dem Namen „exists“, die 1 ist, wenn die Zeile vor der Abfrage vorhanden war ausgeführt, 0, wenn nicht.

  • Die RETURNING-Klausel kann auch die Spalten der Zeile zurückgeben, einschließlich aller generierten Elemente, die nicht bereitgestellt wurden.

Sie müssen nur einmal herausfinden, wie Sie damit umgehen, wenn eine Einfügung oder Aktualisierung erforderlich ist, und eine einfache Abstraktion erstellen, die alle Ihre PUTs aufrufen können und die 200 OK oder 201 Erstellt verarbeitet.

Ein schöner Vorteil der Verwendung PUT wie beabsichtigt bedeutet, dass Sie, sobald Sie einen POST sehen, mit Sicherheit wissen, dass es sich nicht um einen Abruf oder eine Persistenz handelt, und umgekehrt wissen Sie, dass Sie nach POST suchen müssen, um den Code für jeden Vorgang zu finden, der kein Abruf oder eine Persistenz ist.

Ich denke, die Vorteile der Verwendung von PUT und POST, wie im RFC beschrieben, überwiegen die Gründe, warum Menschen sie auf eine Weise verwenden, die nicht RFC-konform ist.

Das obige ist der detaillierte Inhalt vonREST- und HTTP-Semantik. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn