642 Stimmen

REST verstehen: Verben, Fehlercodes und Authentifizierung

Ich bin auf der Suche nach einer Möglichkeit, APIs um Standardfunktionen in meinen PHP-basierten Webanwendungen, Datenbanken und CMSs zu wickeln.

Ich habe mich umgesehen und mehrere "Skelett"-Frameworks gefunden. Zusätzlich zu den Antworten in meiner Frage gibt es Tonic ein REST-Framework, das ich mag, weil es sehr leichtgewichtig ist.

REST gefällt mir wegen seiner Einfachheit am besten, und ich möchte eine darauf basierende API-Architektur erstellen. Ich versuche, die grundlegenden Prinzipien zu verstehen und habe sie noch nicht ganz durchschaut. Daher eine Reihe von Fragen.

1. Verstehe ich es richtig?

Angenommen, ich habe eine Ressource "Benutzer". Ich könnte eine Reihe von URIs wie folgt einrichten:

/api/users     when called with GET, lists users
/api/users     when called with POST, creates user record
/api/users/1   when called with GET, shows user record
               when called with PUT, updates user record
               when called with DELETE, deletes user record

Ist dies bisher eine korrekte Darstellung einer RESTful-Architektur?

2. Ich brauche mehr Verben

Erstellen, Aktualisieren und Löschen mögen in der Theorie ausreichen, aber in der Praxis werde ich viel mehr Verben benötigen. Mir ist klar, dass dies Dinge sind, die pourrait in eine Aktualisierungsanforderung eingebettet werden, aber es handelt sich um spezifische Aktionen, die spezifische Rückgabewerte haben können, und ich möchte sie nicht alle in eine einzige Aktion packen.

Einige, die mir im Zusammenhang mit dem Benutzerbeispiel einfallen, sind:

activate_login
deactivate_login
change_password
add_credit

Wie würde ich Aktionen wie diese in einer RESTful-URL-Architektur ausdrücken?

Mein Instinkt wäre es, einen GET-Aufruf an eine URL wie

/api/users/1/activate_login 

und erwarten einen Statuscode zurück.

Das weicht jedoch von der Idee der Verwendung von HTTP-Verben ab. Was halten Sie davon?

3. Wie man Fehlermeldungen und Codes zurückgibt

Ein großer Teil der Schönheit von REST ergibt sich aus der Verwendung von Standard-HTTP-Methoden. Bei einem Fehler gebe ich eine Kopfzeile mit einem 3xx, 4xx oder 5xx Fehlerstatuscode aus. Für eine detaillierte Fehlerbeschreibung kann ich den Body verwenden (richtig?). So weit, so gut. Aber wie kann ich eine proprietärer Fehlercode die detaillierter beschreibt, was schief gelaufen ist (z.B. "Verbindung zur Datenbank fehlgeschlagen" oder "Datenbankanmeldung falsch")? Wenn ich sie zusammen mit der Meldung in den Textkörper einfüge, muss ich sie anschließend auslesen. Gibt es einen Standard-Header für diese Art von Meldungen?

4. Wie erfolgt die Authentifizierung?

  • Wie würde eine auf API-Schlüssel basierende Authentifizierung nach REST-Grundsätzen aussehen?
  • Gibt es gute Gründe, die gegen die Verwendung von Sitzungen bei der Authentifizierung eines REST-Clients sprechen, abgesehen davon, dass es ein eklatanter Verstoß gegen das REST-Prinzip ist? :) (Das ist nur ein halber Scherz, sitzungsbasierte Authentifizierung würde gut zu meiner bestehenden Infrastruktur passen).

17 Stimmen

@Daniel, danke für die Bearbeitung. "Ich mehr Verben" war ein absichtliches Wortspiel, aber ich lasse es so, es ist jetzt leichter zu lesen :)

1 Stimmen

Übrigens, zur Fehlerbeschreibung. Ich habe es geschafft, die Fehlerbeschreibung in die Kopfzeile der Antwort zu schreiben. Fügen Sie einfach eine Kopfzeile mit dem Namen "Fehlerbeschreibung" hinzu.

0 Stimmen

Dies sieht eher nach Fragen der Anwendungssicherheit aus. Anwendungssicherheit ist nicht das, worum es bei REST geht.

13voto

jonnii Punkte 27657

Für die von Ihnen genannten Beispiele würde ich folgendes verwenden:

aktivieren_anmelden

POST /users/1/activation

deaktivieren_anmelden

DELETE /users/1/activation

passwort_ändern

PUT /passwords (dies setzt voraus, dass der Benutzer authentifiziert ist)

add_credit

POST /credits (dies setzt voraus, dass der Benutzer authentifiziert ist)

Bei Fehlern geben Sie den Fehler in dem Format zurück, in dem Sie die Anfrage erhalten haben, also wenn Sie erhalten:

DELETE /users/1.xml

Sie würden die Antwort in XML zurücksenden, dasselbe würde für JSON usw. gelten.

Für die Authentifizierung sollten Sie http-Authentifizierung verwenden.

1 Stimmen

Ich würde nicht verwenden create als Teil der URI (denken Sie daran, dass URIs Substantive sein sollten und HTTP-Methoden Verben, die auf diese Substantive wirken). Stattdessen würde ich eine Ressource wie /users/1/active die ein einfacher Boolescher Wert sein kann, der durch PUTING einer 1 oder 0 auf diese Ressource gesetzt werden kann.

0 Stimmen

Sie haben Recht, ich habe das /create entfernt. Es sollte nur ein Post an die Singleton-Ressource sein.

3 Stimmen

Ich würde nicht verwenden activation auf den URI, es sei denn, Sie wollen explizit eine Ressource mit dem Namen des URI bearbeiten und verwalten. /users/1/activation . Was bewirkt ein GET in diesem Fall? Was bewirkt ein PUT? Mir kommt es so vor, als würden Sie den URI verbifizieren. Was die Aushandlung des Content-Typs angeht, so ist es oft am besten, diesen nicht in der URI, sondern in den Header einzufügen, z.B. Accept .

8voto

Arjan Punkte 17211
  1. Verwenden Sie post, wenn Sie nicht wissen, wie der neue Ressourcen-URI aussehen würde (Sie erstellen einen neuen Benutzer, die Anwendung würde dem neuen Benutzer seine ID zuweisen), PUT für die Aktualisierung oder Erstellung von Ressourcen, von denen Sie wissen, wie sie dargestellt werden sollen (Beispiel: PUT /myfiles/thisismynewfile.txt)
  2. Rückgabe der Fehlerbeschreibung im Nachrichtentext
  3. Sie können die HTTP-Authentifizierung verwenden (wenn sie ausreichend ist) Webdienste sollten stateles sein

6voto

Brian Agnew Punkte 260470

Ich würde vorschlagen (in einem ersten Schritt), dass PUT sollte nur für die Aktualisierung bestehender Entitäten verwendet werden. POST sollten für die Erstellung neuer verwendet werden, d.h.

/api/users     when called with PUT, creates user record

fühlt sich für mich nicht richtig an. Der Rest deines ersten Abschnitts (bezüglich der Verwendung von Verben) sieht jedoch logisch aus.

0 Stimmen

Wahrscheinlich dachte jemand, dass dies nicht wirklich eine Antwort auf seine Frage ist.

6 Stimmen

Meine Meinung zu PUT versus POST für die Erstellung neuer Entitäten ist, PUT zu verwenden, wenn der Aufrufer den Ressourcennamen kontrolliert, so können Sie PUT auf die genaue Ressource und POST, wenn der Aufrufer den neuen Ressourcennamen kontrolliert (wie im Beispiel hier).

6voto

gahooa Punkte 121696

Ausführlich, aber aus der HTTP 1.1-Methodenspezifikation kopiert unter http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

9.3 GET

Die GET-Methode bedeutet, dass alle Informationen (in Form einer Entität) abgerufen werden, die durch die Request-URI identifiziert werden. Bezieht sich die Request-URI auf einen datenproduzierenden Prozess, werden die produzierten Daten als Entität in der Antwort zurückgegeben und nicht der Quelltext des Prozesses, es sei denn, dieser Text ist die Ausgabe des Prozesses.

Die Semantik der GET-Methode ändert sich in ein "bedingtes GET", wenn die Anforderungsnachricht ein If-Modified-Since-, If-Unmodified-Since-, If-Match-, If-None-Match- oder If-Range-Headerfeld enthält. Eine bedingte GET-Methode verlangt, dass die Entität nur unter den durch das/die bedingte(n) Header-Feld(er) beschriebenen Umständen übertragen wird. Die bedingte GET-Methode soll die unnötige Netzauslastung verringern, indem sie es ermöglicht, zwischengespeicherte Entitäten zu aktualisieren, ohne dass mehrere Anfragen erforderlich sind oder Daten übertragen werden müssen, die sich bereits im Besitz des Clients befinden.

Die Semantik der GET-Methode ändert sich zu einem "partiellen GET", wenn die Anforderungsnachricht ein Range-Header-Feld enthält. Ein teilweiser GET verlangt, dass nur ein Teil der Entität übertragen wird, wie in Abschnitt 14.35 beschrieben. Die partielle GET-Methode soll die unnötige Netzauslastung verringern, indem sie es ermöglicht, teilweise abgerufene Entitäten zu vervollständigen, ohne bereits im Besitz des Clients befindliche Daten zu übertragen.

Die Antwort auf eine GET-Anfrage ist nur dann zwischenspeicherfähig, wenn sie die in Abschnitt 13 beschriebenen Anforderungen für HTTP-Caching erfüllt.

Siehe Abschnitt 15.1.3 zu Sicherheitsüberlegungen bei der Verwendung für Formulare.

9.5 POST

Die POST-Methode wird verwendet, um anzufordern, dass der Ursprungsserver die in der Anfrage enthaltene Entität als neuen Unterordner der durch die Request-URI in der Request-Line identifizierten Ressource akzeptiert. POST wurde entwickelt, um eine einheitliche Methode zu ermöglichen, die die folgenden Funktionen abdeckt:

  - Annotation of existing resources;
  - Posting a message to a bulletin board, newsgroup, mailing list,
    or similar group of articles;
  - Providing a block of data, such as the result of submitting a
    form, to a data-handling process;
  - Extending a database through an append operation.

Die tatsächliche Funktion, die von der POST-Methode ausgeführt wird, wird vom Server bestimmt und ist in der Regel von der Request-URI abhängig. Die gepostete Entität ist dieser URI untergeordnet, so wie eine Datei einem Verzeichnis untergeordnet ist, das sie enthält, ein News-Artikel einer Newsgruppe untergeordnet ist, in die er gepostet wird, oder ein Datensatz einer Datenbank untergeordnet ist.

Die von der POST-Methode durchgeführte Aktion führt möglicherweise nicht zu einer Ressource, die durch einen URI identifiziert werden kann. In diesem Fall ist entweder 200 (OK) oder 204 (kein Inhalt) der geeignete Antwortstatus, je nachdem, ob die Antwort eine Entität enthält, die das Ergebnis beschreibt oder nicht.

Wenn eine Ressource auf dem Ursprungsserver erstellt wurde, SOLLTE die Antwort 201 (Created) lauten und eine Entität enthalten, die den Status der Anfrage beschreibt und auf die neue Ressource verweist, sowie einen Location-Header (siehe Abschnitt 14.30).

Antworten auf diese Methode können nicht zwischengespeichert werden, es sei denn, die Antwort enthält entsprechende Cache-Control- oder Expires-Header-Felder. Die Antwort 303 (siehe Sonstiges) kann jedoch verwendet werden, um den Benutzeragenten anzuweisen, eine cachefähige Ressource abzurufen.

POST-Anfragen MÜSSEN die in Abschnitt 8.2 genannten Anforderungen an die Nachrichtenübermittlung erfüllen.

Siehe Abschnitt 15.1.3 für Sicherheitsüberlegungen.

9.6 PUT

Die PUT-Methode verlangt, dass die eingeschlossene Entität unter der angegebenen Request-URI gespeichert wird. Verweist die Request-URI auf eine bereits existierende Ressource, SOLLTE die eingeschlossene Entität als eine modifizierte Version der auf dem Ursprungsserver befindlichen Entität betrachtet werden. Wenn die Request-URI nicht auf eine bestehende Ressource verweist und diese URI vom anfragenden User-Agent als neue Ressource definiert werden kann, kann der Ursprungsserver die Ressource mit dieser URI erstellen. Wenn eine neue Ressource erstellt wird, MUSS der Ursprungsserver den User-Agent über die 201 (Created) Antwort informieren. Wird eine bestehende Ressource geändert, SOLLTE entweder der Antwortcode 200 (OK) oder 204 (No Content) gesendet werden, um den erfolgreichen Abschluss der Anfrage anzuzeigen. Konnte die Ressource mit der Request-URI nicht erstellt oder geändert werden, SOLLTE eine entsprechende Fehlerantwort gegeben werden, die die Art des Problems widerspiegelt. Der Empfänger der Entität DARF KEINE Content-*-Header (z. B. Content-Range) ignorieren, die er nicht versteht oder nicht implementiert, und MUSS in solchen Fällen eine Antwort 501 (Not Implemented) zurückgeben.

Wenn die Anfrage einen Cache durchläuft und die Request-URI eine oder mehrere aktuell gecachte Entitäten identifiziert, SOLLTEN diese Einträge als veraltet behandelt werden. Antworten auf diese Methode sind nicht cachefähig.

Der grundlegende Unterschied zwischen POST- und PUT-Anfragen spiegelt sich in der unterschiedlichen Bedeutung der Request-URI wider. Die URI in einer POST-Anforderung identifiziert die Ressource, die die eingeschlossene Entität verarbeiten wird. Bei dieser Ressource kann es sich um einen datenannehmenden Prozess, ein Gateway zu einem anderen Protokoll oder um eine separate Entität handeln, die Anmerkungen annimmt. Im Gegensatz dazu identifiziert die URI in einer PUT-Anfrage die der Anfrage beigefügte Entität - der User Agent weiß, welche URI gemeint ist, und der Server MUSS NICHT versuchen, die Anfrage auf eine andere Ressource anzuwenden. Wenn der Server wünscht, dass die Anfrage auf einen anderen URI angewendet wird,

MUSS er eine 301-Antwort (Moved Permanently) senden; der User-Agent kann dann selbst entscheiden, ob er die Anfrage weiterleitet oder nicht.

Eine einzelne Ressource KANN durch viele verschiedene URIs identifiziert werden. Zum Beispiel könnte ein Artikel eine URI zur Identifizierung der "aktuellen Version" haben, die von der URI zur Identifizierung jeder einzelnen Version getrennt ist. In diesem Fall kann eine PUT-Anfrage an einen allgemeinen URI dazu führen, dass der Ursprungsserver mehrere andere URIs definiert.

HTTP/1.1 definiert nicht, wie eine PUT-Methode den Zustand eines Ursprungs-Servers beeinflusst.

PUT-Anfragen MÜSSEN die in Abschnitt 8.2 beschriebenen Anforderungen an die Nachrichtenübertragung erfüllen.

Sofern für einen bestimmten Entity-Header nicht anders angegeben, SOLLTEN die Entity-Header in der PUT-Anfrage auf die durch das PUT erstellte oder geänderte Ressource angewendet werden.

9.7 LÖSCHEN

Die DELETE-Methode fordert den Ursprungsserver auf, die durch die Request-URI identifizierte Ressource zu löschen. Diese Methode KANN durch menschliches Eingreifen (oder andere Mittel) auf dem Herkunftsserver außer Kraft gesetzt werden. Der Client kann nicht sicher sein, dass die Operation ausgeführt wurde, selbst wenn der vom Ursprungsserver zurückgegebene Statuscode anzeigt, dass die Aktion erfolgreich abgeschlossen wurde. Der Server SOLLTE jedoch NICHT den Erfolg anzeigen, es sei denn, er beabsichtigt zum Zeitpunkt der Antwort, die Ressource zu löschen oder sie an einen unzugänglichen Ort zu verschieben.

Eine erfolgreiche Antwort SOLLTE 200 (OK) lauten, wenn die Antwort eine Entität enthält, die den Status beschreibt, 202 (Angenommen), wenn die Aktion noch nicht ausgeführt wurde, oder 204 (Kein Inhalt), wenn die Aktion ausgeführt wurde, aber die Antwort keine Entität enthält.

Wenn die Anfrage einen Cache durchläuft und die Request-URI eine oder mehrere aktuell gecachte Entitäten identifiziert, SOLLTEN diese Einträge als veraltet behandelt werden. Antworten auf diese Methode sind nicht cachefähig.

2voto

Marcodor Punkte 2829

Über REST-Rückgabecodes: Es ist falsch um HTTP-Protokollcodes und REST-Ergebnisse zu mischen.

Ich habe jedoch viele Implementierungen gesehen, bei denen sie gemischt wurden, und viele Entwickler sind vielleicht anderer Meinung als ich.

Die HTTP-Rückgabecodes beziehen sich auf die HTTP Request selbst. Ein REST-Aufruf erfolgt über eine Hypertext Transfer Protocol-Anfrage und arbeitet auf einer niedrigeren Ebene als die aufgerufene REST-Methode selbst. REST ist ein Konzept/Ansatz, und seine Ausgabe ist ein betriebswirtschaftlich/logisch Ergebnis, während der HTTP-Ergebniscode ein transportieren ein.

Zum Beispiel ist die Rückgabe von "404 Not found" beim Aufruf von /users/ verwirrend, weil es bedeuten kann:

  • URI ist falsch (HTTP)
  • Es wurden keine Benutzer gefunden (REST)

"403 Forbidden/Access Denied" kann bedeuten:

  • Sondergenehmigung erforderlich. Browser können dies durch Abfrage von Benutzer/Passwort erledigen. (HTTP)
  • Falsche Zugriffsberechtigungen auf dem Server konfiguriert. (HTTP)
  • Sie müssen authentifiziert sein (REST)

Und die Liste lässt sich fortsetzen mit "500 Serverfehler" (ein Apache/Nginx-HTTP-Fehler oder ein Business-Constraint-Fehler in REST) oder anderen HTTP-Fehlern usw...

Anhand des Codes lässt sich nur schwer nachvollziehen, was der Grund für den Fehler war: ein HTTP-Fehler (Transport) oder ein REST-Fehler (logisch).

Wenn die HTTP-Anfrage physisch erfolgreich durchgeführt wurde, sollte sie toujours Rückgabe des Codes 200, unabhängig davon, ob der/die Datensatz/e gefunden wurden oder nicht. Da die URI-Ressource gefunden und wurde vom http-Server verarbeitet. Ja, es kann eine leere Menge zurückgeben. Es ist möglich, eine leere Webseite mit 200 als http-Ergebnis zu erhalten, richtig?

Stattdessen können Sie einen 200 HTTP-Code und einfach ein JSON mit einem leeren Array/Objekt zurückgeben oder ein bool'sches Ergebnis-/Erfolgsflag verwenden, um über den Status der durchgeführten Operation zu informieren.

Außerdem kann es vorkommen, dass einige Internet-Provider Ihre Anfragen abfangen und Ihnen einen 404 http-Code zurückgeben. Dies bedeutet nicht, dass Ihre Daten nicht gefunden werden, sondern dass auf der Transportebene etwas nicht stimmt.

Desde Wiki :

Im Juli 2004 führte der britische Telekommunikationsanbieter BT Group das Cleanfeed ein, das bei jeder Anfrage nach potenziell illegalen Inhalten einen 404-Fehler die von der Internet Watch Foundation als potenziell illegal eingestuft wurden Stiftung. Andere Internetdienstanbieter geben unter denselben Umständen einen HTTP 403-Fehler zurück, der Umständen zurück. Die Praxis, gefälschte 404-Fehler zu verwenden, um Zensur zu verschleiern, wurde auch aus Thailand und Tunesien berichtet. In Tunesien, wo die Zensur vor der Revolution 2011 sehr streng war, wurden die Menschen auf die Natur der gefälschten 404-Fehler aufmerksam und schufen eine imaginäre Figur namens "Ammar 404", die "den unsichtbaren Zensor" darstellt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X