webentwicklung-frage-antwort-db.com.de

Grundlegendes zu REST: Verben, Fehlercodes und Authentifizierung

Ich suche nach einer Möglichkeit, APIs um Standardfunktionen in meinen PHP-basierten Webanwendungen, Datenbanken und CMS zu wickeln.

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

Ich mag REST das Beste für seine Einfachheit, und möchte eine API-Architektur erstellen, die darauf basiert. Ich versuche, mich mit den Grundprinzipien vertraut zu machen und habe sie noch nicht vollständig verstanden. 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 eine korrekte Darstellung einer RESTful-Architektur?

2. Ich brauche mehr Verben

Erstellen, Aktualisieren und Löschen mögen theoretisch ausreichen, aber in der Praxis werde ich viel mehr Verben benötigen. Mir ist klar, dass dies Dinge sind, die in eine Aktualisierungsanforderung eingebettet sein könnten , aber es sind bestimmte Aktionen, die bestimmte Rückkehrcodes haben können, und ich möchte sie nicht alle in eine Aktion werfen .

Einige, die im Benutzerbeispiel in den Sinn kommen, sind:

activate_login
deactivate_login
change_password
add_credit

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

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

/api/users/1/activate_login 

und erwarte einen Statuscode zurück.

Das weicht jedoch von der Idee ab, HTTP-Verben zu verwenden. Was denkst du?

3. So geben Sie Fehlermeldungen und Codes zurück

Ein großer Teil der Schönheit von REST beruht auf der Verwendung von Standard-HTTP-Methoden. Bei einem Fehler sende ich einen Header mit einem 3xx-, 4xx- oder 5xx-Fehlerstatuscode aus. Für eine detaillierte Fehlerbeschreibung kann ich den Body verwenden (oder?). So weit, ist es gut. Aber wie könnte ein proprietärer Fehlercode übertragen werden, der detaillierter beschreibt, was schief gelaufen ist (z. B. "Verbindung zur Datenbank fehlgeschlagen" oder "Datenbank Login falsch")? Wenn ich es zusammen mit der Nachricht in den Körper lege, muss ich es anschließend auswerten. Gibt es einen Standardheader für solche Dinge?

4. Authentifizierung durchführen

  • Wie würde eine auf API-Schlüsseln basierende Authentifizierung aussehen, die den REST Prinzipien entspricht?
  • Gibt es starke Argumente gegen die Verwendung von Sitzungen bei der Authentifizierung eines REST= - Clients, ansonsten handelt es sich um eine offensichtliche Verletzung des REST= - Prinzips? :) (hier nur ein Scherz) , Sitzungsbasierte Authentifizierung würde mit meiner vorhandenen Infrastruktur gut funktionieren.)
586
Pekka 웃

Diese Frage ist mir einige Tage zu spät aufgefallen, aber ich habe das Gefühl, dass ich einige Einsichten hinzufügen kann. Ich hoffe, dass dies für Ihr RESTful-Unternehmen hilfreich sein kann.


Punkt 1: Verstehe ich es richtig?

Du hast richtig verstanden. Das ist eine korrekte Darstellung einer RESTful-Architektur. Sie können die folgende Matrix aus Wikipedia sehr hilfreich bei der Definition Ihrer Substantive und Verben finden:


Beim Umgang mit einer Auflistung URI wie: http://example.com/resources/

  • [~ # ~] get [~ # ~] : Listet die Mitglieder der Sammlung mit ihren Mitglieds-URIs für die weitere Navigation auf. Listen Sie zum Beispiel alle Autos auf, die zum Verkauf stehen.

  • [~ # ~] put [~ # ~] : Bedeutung definiert als "die gesamte Sammlung durch eine andere Sammlung ersetzen".

  • [~ # ~] Beitrag [~ # ~] : Erstellen Sie einen neuen Eintrag in der Sammlung, wobei die ID automatisch von der Sammlung zugewiesen wird. Die erstellte ID wird normalerweise als Teil der von dieser Operation zurückgegebenen Daten einbezogen.

  • [~ # ~] löschen [~ # ~] : Bedeutung definiert als "gesamte Sammlung löschen".


Beim Umgang mit einem Mitglied URI wie: http://example.com/resources/7HOU57Y

  • [~ # ~] get [~ # ~] : Ruft eine Darstellung des adressierten Mitglieds der Sammlung ab, ausgedrückt in einem geeigneten MIME-Typ.

  • [~ # ~] put [~ # ~] : Aktualisieren Sie das adressierte Mitglied der Sammlung oder erstellen Sie es mit der angegebenen ID.

  • [~ # ~] post [~ # ~] : Behandelt das angesprochene Mitglied als eigenständige Sammlung und erstellt einen neuen Untergebenen davon.

  • [~ # ~] löschen [~ # ~] : Löschen Sie das adressierte Mitglied der Sammlung.


Punkt 2: Ich brauche mehr Verben

Wenn Sie glauben, dass Sie mehr Verben benötigen, kann dies im Allgemeinen bedeuten, dass Ihre Ressourcen neu identifiziert werden müssen. Denken Sie daran, dass Sie in REST immer auf eine Ressource oder eine Sammlung von Ressourcen einwirken. Was Sie als Ressource auswählen, ist für Ihre API-Definition sehr wichtig.

Login aktivieren/deaktivieren : Wenn Sie eine neue Sitzung erstellen, möchten Sie möglicherweise "die Sitzung" als Ressource betrachten. Verwenden Sie zum Erstellen einer neuen Sitzung POST, um http://example.com/sessions/ Mit den Anmeldeinformationen im Hauptteil zu verwenden. Verwenden Sie zum Ablaufen PUT oder DELETE (möglicherweise abhängig davon, ob Sie beabsichtigen, einen Sitzungsverlauf zu führen), um http://example.com/sessions/SESSION_ID.

Passwort ändern: Diesmal ist die Ressource "der Benutzer". Sie benötigen einen PUT, um http://example.com/users/USER_ID Mit den alten und neuen Passwörtern im Hauptteil zu setzen. Sie handeln auf der Ressource "Benutzer", und ein Änderungskennwort ist einfach eine Aktualisierungsanforderung. Es ist der UPDATE-Anweisung in einer relationalen Datenbank ziemlich ähnlich.

Mein Instinkt wäre, einen GET-Aufruf an eine URL wie /api/users/1/activate_login Durchzuführen.

Dies widerspricht einem sehr zentralen REST Prinzip: Die korrekte Verwendung von HTTP-Verben. Jede GET-Anfrage sollte niemals irgendwelche Nebenwirkungen hinterlassen.

Beispielsweise sollte eine GET-Anforderung niemals eine Sitzung in der Datenbank erstellen, kein Cookie mit einer neuen Sitzungs-ID zurückgeben oder Rückstände auf dem Server hinterlassen. Das Verb GET ähnelt der SELECT-Anweisung in einem Datenbankmodul. Denken Sie daran, dass die Antwort auf jede Anforderung mit dem Verb GET cachefähig sein sollte, wenn sie mit denselben Parametern angefordert wird, genau wie wenn Sie eine statische Webseite anfordern.


Punkt 3: Fehlermeldungen und Codes zurückgeben

Betrachten Sie die HTTP-Statuscodes 4xx oder 5xx als Fehlerkategorien. Sie können den Fehler im Körper ausarbeiten.

Verbindung zur Datenbank fehlgeschlagen: / Falsche Datenbankanmeldung : Im Allgemeinen Sie sollte für diese Fehlertypen einen 500-Fehler verwenden. Dies ist ein serverseitiger Fehler. Der Kunde hat nichts falsch gemacht. 500 Fehler werden normalerweise als "wiederholbar" angesehen. d.h. der Client kann die gleiche exakte Anfrage wiederholen und davon ausgehen, dass sie erfolgreich ist, sobald die Probleme des Servers behoben sind. Geben Sie die Details im Textkörper an, damit der Client uns Menschen einen Kontext bereitstellen kann.

Die andere Kategorie von Fehlern ist die 4xx-Familie, die im Allgemeinen darauf hinweist, dass der Client etwas falsch gemacht hat. Insbesondere weist diese Fehlerkategorie den Client normalerweise darauf hin, dass die Anforderung nicht wiederholt werden muss, da sie weiterhin dauerhaft fehlschlagen wird. d.h. der Client muss etwas ändern, bevor er diese Anforderung wiederholt. Beispielsweise würden Fehler "Ressource nicht gefunden" (HTTP 404) oder "Fehlerhafte Anforderung" (HTTP 400) in diese Kategorie fallen.


Punkt 4: Authentifizierung durchführen

Wie in Punkt 1 ausgeführt, sollten Sie über das Erstellen einer Sitzung nachdenken, anstatt einen Benutzer zu authentifizieren. Sie erhalten eine neue "Sitzungs-ID" mit dem entsprechenden HTTP-Statuscode (200: Zugriff gewährt oder 403: Zugriff verweigert).

Sie werden dann Ihren RESTful-Server fragen: "Können Sie mir die Ressource für diese Sitzungs-ID holen?".

Es gibt keinen authentifizierten Modus - REST ist statusfrei: Sie erstellen eine Sitzung, Sie fordern den Server auf, Ihnen Ressourcen mit dieser Sitzungs-ID als Parameter bereitzustellen, und Sie beenden oder beenden die Sitzung, wenn Sie sich abmelden.

606
Daniel Vassallo

Einfach ausgedrückt, machen Sie das komplett rückwärts.

Sie sollten dies nicht über die URLs tun, die Sie verwenden sollten. Die URLs werden effektiv "kostenlos" bereitgestellt, sobald Sie festgelegt haben, welche Ressourcen für Ihr System erforderlich sind, UND wie Sie diese Ressourcen darstellen und welche Wechselwirkungen zwischen den Ressourcen und dem Anwendungsstatus bestehen.

Zu zitieren Roy Fielding

Eine REST API sollte fast den gesamten beschreibenden Aufwand für die Definition der Medientypen verwenden, die zur Darstellung von Ressourcen und zur Steuerung des Anwendungsstatus verwendet werden, oder für die Definition erweiterter Beziehungsnamen und/oder hypertextfähiger Markierungen -up für vorhandene Standardmedientypen: Jeder Aufwand, der aufgewendet wird, um zu beschreiben, welche Methoden für welche URIs von Interesse zu verwenden sind, sollte vollständig im Rahmen der Verarbeitungsregeln für einen Medientyp (und in den meisten Fällen bereits durch vorhandene Medientypen definiert) definiert werden. . [Ein Misserfolg hier impliziert, dass Außerbandinformationen die Interaktion anstelle von Hypertext vorantreiben.]

Die Leute beginnen immer mit den URIs und denken, dass dies die Lösung ist, und dann verfehlen sie in der Regel ein Schlüsselkonzept in der REST= Architektur, insbesondere, wie oben erwähnt, "Fehler hier implizieren, dass Bandinformationen treiben die Interaktion anstelle von Hypertext voran. "

Um ehrlich zu sein, sehen viele eine Reihe von URIs und einige GETs und PUTs und POSTs und denken, dass REST ist einfach. REST ist nicht einfach. RPC über HTTP ist Das einfache Hin- und Herbewegen von Datenblobs über HTTP-Payloads ist einfach. REST geht jedoch darüber hinaus. REST ist protokollunabhängig. HTTP ist nur sehr beliebt und eignet sich für REST Systeme.

REST lebt von den Medientypen, ihren Definitionen und davon, wie die Anwendung die diesen Ressourcen zur Verfügung stehenden Aktionen über Hypertext (Links, effektiv) steuert.

Es gibt unterschiedliche Ansichten zu Medientypen in REST) - Systemen. Einige bevorzugen anwendungsspezifische Nutzdaten, während andere vorhandene Medientypen in Rollen hochheben, die für die Anwendung geeignet sind. Zum Beispiel Sie haben spezifische XML-Schemata, die für Ihre Anwendung geeignet sind, und verwenden XHTML als Repräsentation, möglicherweise über Mikroformate und andere Mechanismen.

Ich denke, beide Ansätze haben ihren Platz, da XHTML sehr gut in Szenarien funktioniert, die sowohl das von Menschen betriebene als auch das von Maschinen betriebene Web überlappen, während die ersteren, spezifischeren Datentypen meiner Meinung nach die Interaktion von Maschine zu Maschine besser erleichtern. Ich bin der Meinung, dass die Aufwertung von Warenformaten die Aushandlung von Inhalten möglicherweise erschweren kann. "application/xml + yourresource" ist als Medientyp viel spezifischer als "application/xhtml + xml", da letzteres auf viele Nutzdaten angewendet werden kann, an denen ein Maschinenclient möglicherweise tatsächlich interessiert ist oder nicht ohne Selbstbeobachtung bestimmen.

XHTML funktioniert jedoch (offensichtlich) sehr gut im menschlichen Web, wo Webbrowser und Rendering sehr wichtig sind.

Ihre Bewerbung wird Sie bei solchen Entscheidungen unterstützen.

Ein Teil des Entwurfsprozesses für ein REST System besteht darin, die erstklassigen Ressourcen in Ihrem System zusammen mit den abgeleiteten Supportressourcen zu ermitteln, die zur Unterstützung der Operationen für die primären Ressourcen erforderlich sind. Sobald die Ressourcen ermittelt wurden , dann die Darstellung dieser Ressourcen, sowie die Zustandsdiagramme, die den Ressourcenfluss per Hypertext innerhalb der Darstellungen für die nächste Herausforderung darstellen.

Es sei daran erinnert, dass jede Darstellung einer Ressource in einem Hypertextsystem sowohl die tatsächliche Ressourcendarstellung als auch die für die Ressource verfügbaren Statusübergänge kombiniert. Betrachten Sie jede Ressource als Knoten in einem Diagramm, wobei die Verknüpfungen die Linien sind, die diesen Knoten zu anderen Zuständen führen. Diese Links informieren die Kunden nicht nur darüber, was getan werden kann, sondern auch darüber, was getan werden muss (da ein guter Link den URI und den erforderlichen Medientyp kombiniert).

Zum Beispiel haben Sie vielleicht:

<link href="http://example.com/users" rel="users" type="application/xml+usercollection"/>
<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>

In Ihrer Dokumentation werden das rel-Feld "users" und der Medientyp "application/xml + youruser" beschrieben.

Diese Links scheinen überflüssig zu sein, sie sprechen alle mit der gleichen URI. Aber das sind sie nicht.

Dies liegt daran, dass für die Beziehung "Benutzer" dieser Link über die Sammlung von Benutzern spricht und Sie die einheitliche Oberfläche verwenden können, um mit der Sammlung zu arbeiten (GET, um alle abzurufen, DELETE, um alle zu löschen, usw.).

Wenn Sie POST an diese URL senden, müssen Sie ein "application/xml + usercollection" -Dokument übergeben, das wahrscheinlich nur eine einzelne Benutzerinstanz im Dokument enthält, damit Sie den Benutzer hinzufügen können. oder nicht, um mehrere auf einmal hinzuzufügen. Vielleicht wird in Ihrer Dokumentation vorgeschlagen, dass Sie anstelle der Auflistung einfach einen einzelnen Benutzertyp übergeben können.

Sie können sehen, was die Anwendung benötigt, um eine Suche durchzuführen, wie durch den Link "Suche" und dessen Medientyp definiert. In der Dokumentation zum Suchmedientyp erfahren Sie, wie sich dies verhält und was als Ergebnis zu erwarten ist.

Das Mitnehmen hier ist jedoch, dass die URIs selbst im Grunde genommen unwichtig sind. Die Anwendung kontrolliert die URIs, nicht die Clients. Abgesehen von einigen „Einstiegspunkten“ sollten sich Ihre Kunden bei ihrer Arbeit auf die von der Anwendung bereitgestellten URIs verlassen.

Der Kunde muss wissen, wie er die Medientypen manipuliert und interpretiert, muss sich aber nicht darum kümmern, wohin sie gehen.

Diese beiden Links sind in den Augen des Kunden semantisch identisch:

<link href="http://example.com/users?search" rel="search" type="application/xml+usersearchcriteria"/>
<link href="http://example.com/AW163FH87SGV" rel="search" type="application/xml+usersearchcriteria"/>

Konzentrieren Sie sich also auf Ihre Ressourcen. Konzentrieren Sie sich auf die Zustandsübergänge in der Anwendung und darauf, wie dies am besten erreicht wird.

77
Will Hartung

zu 1: Das sieht soweit gut aus. Denken Sie daran, den URI des neu erstellten Benutzers in einem "Location:" - Header als Teil der Antwort auf den POST zusammen mit einem "201 Created" -Statuscode zurückzugeben.

zu 2: Die Aktivierung über GET ist eine schlechte Idee, und die Aufnahme des Verbs in die URI ist ein Designgeruch. Möglicherweise möchten Sie ein Formular auf einem GET zurückgeben. In einer Webanwendung ist dies ein HTML-Formular mit einer Senden-Schaltfläche. Im API-Anwendungsfall möchten Sie möglicherweise eine Darstellung, die einen URI enthält, an PUT zurückgeben, um das Konto zu aktivieren. Natürlich können Sie diese URI auch in die Antwort auf POST to/users einbeziehen. Durch die Verwendung von PUT wird sichergestellt, dass Ihre Anfrage idempotent ist, dh sie kann sicher erneut gesendet werden, wenn der Client nicht sicher ist Überlegen Sie sich im Allgemeinen, in welche Ressourcen Sie Ihre Verben verwandeln können (Art "Substantivierung von Verben"). Fragen Sie sich, mit welcher Methode Ihre spezifische Aktion am ehesten übereinstimmt. ZB change_password -> PUT; disable -> probably DELETE ; add_credit -> möglicherweise POST oder PUT. Verweisen Sie den Client auf die entsprechenden URIs, indem Sie sie in Ihre Repräsentationen aufnehmen.

zu 3. Erfinde keine neuen Statuscodes, es sei denn, du glaubst, sie sind so allgemein, dass sie es verdienen, global standardisiert zu werden. Versuchen Sie, den am besten geeigneten verfügbaren Statuscode zu verwenden (Informationen dazu finden Sie in RFC 2616). Fügen Sie dem Antworttext zusätzliche Informationen hinzu. Wenn Sie wirklich, wirklich sicher sind, dass Sie einen neuen Statuscode erfinden möchten, denken Sie noch einmal darüber nach. Wenn Sie immer noch der Meinung sind, wählen Sie mindestens die richtige Kategorie aus (1xx -> OK, 2xx -> informativ, 3xx -> Umleitung; 4xx -> Clientfehler, 5xx -> Serverfehler). Habe ich schon erwähnt, dass es eine schlechte Idee ist, neue Statuscodes zu erfinden?

zu 4. Verwenden Sie nach Möglichkeit das in HTTP integrierte Authentifizierungsframework. Überprüfen Sie, wie Google die Authentifizierung in GData durchführt. Fügen Sie im Allgemeinen keine API-Schlüssel in Ihre URIs ein. Versuchen Sie, Sitzungen zu vermeiden, um die Skalierbarkeit zu verbessern und das Zwischenspeichern zu unterstützen. Wenn die Antwort auf eine Anforderung aufgrund eines zuvor aufgetretenen Ereignisses unterschiedlich ist, haben Sie sich normalerweise an eine bestimmte Serverprozessinstanz gebunden. Es ist viel besser, den Sitzungsstatus in einen Clientstatus umzuwandeln (z. B. in einen Teil nachfolgender Anforderungen) oder ihn explizit zu machen, indem Sie ihn in einen (Server-) Ressourcenstatus umwandeln, d. H. Ihm seinen eigenen URI zuweisen.

30
Stefan Tilkov

1. Sie haben die richtige Vorstellung davon, wie Sie Ihre Ressourcen gestalten, IMHO. Ich würde nichts ändern.

2. Anstatt zu versuchen, HTTP mit mehr Verben zu erweitern, überlegen Sie, auf was Ihre vorgeschlagenen Verben in Bezug auf die grundlegenden HTTP-Methoden und -Ressourcen reduziert werden können. Beispielsweise könnten Sie anstelle eines Verbs activate_login Ressourcen wie /api/users/1/login/active Einrichten, was ein einfacher Boolescher Wert ist. Um eine Anmeldung zu aktivieren, geben Sie dort einfach PUT ein Dokument ein, das "true" oder 1 oder was auch immer sagt. Zum Deaktivieren PUT eines Dokuments, das leer ist oder 0 oder false sagt.

Um Kennwörter zu ändern oder festzulegen, geben Sie PUT in /api/users/1/password Ein.

Wann immer Sie etwas hinzufügen müssen (z. B. eine Gutschrift), denken Sie an POST. Sie können beispielsweise eine Ressource wie /api/users/1/credits Mit einem Body mit der Anzahl der hinzuzufügenden Credits mit einem POST versehen. Ein PUT auf derselben Ressource könnte verwendet werden, um den Wert zu überschreiben, anstatt ihn hinzuzufügen. Ein POST mit einer negativen Zahl im Körper würde subtrahieren und so weiter.

. Ich würde dringend davon abraten, die grundlegenden HTTP-Statuscodes zu erweitern. Wenn Sie keine finden können, die genau zu Ihrer Situation passt, wählen Sie die nächstgelegene aus und tragen Sie die Fehlerdetails in den Antworttext ein. Denken Sie auch daran, dass HTTP-Header erweiterbar sind. Ihre Anwendung kann alle benutzerdefinierten Header definieren, die Ihnen gefallen. Eine Anwendung, an der ich gearbeitet habe, könnte beispielsweise unter mehreren Umständen einen 404 Not Found Zurückgeben. Anstatt den Client den Antworttext aus dem Grund analysieren zu lassen, haben wir einen neuen Header hinzugefügt, X-Status-Extended, Der unsere proprietären Statuscode-Erweiterungen enthielt. Vielleicht sehen Sie eine Antwort wie:

HTTP/1.1 404 Not Found    
X-Status-Extended: 404.3 More Specific Error Here

Auf diese Weise weiß ein HTTP-Client wie ein Webbrowser immer noch, was mit dem regulären 404-Code zu tun ist, und ein anspruchsvollerer HTTP-Client kann den X-Status-Extended - Header nach genaueren Informationen durchsuchen.

4. Für die Authentifizierung empfehle ich die Verwendung der HTTP-Authentifizierung, wenn Sie können. Aber meiner Meinung nach ist es nichts auszusetzen, eine Cookie-basierte Authentifizierung zu verwenden, wenn dies für Sie einfacher ist.

22
friedo

REST-Grundlagen

REST hat eine einheitliche Schnittstellenbeschränkung, die besagt, dass sich der REST Client auf Standards stützen muss und nicht auf anwendungsspezifische Details des tatsächlichen REST Service, also des REST Clients wird nicht durch kleinere Änderungen brechen, und es wird wahrscheinlich wiederverwendbar sein.

Es besteht also ein Vertrag zwischen dem REST Client und dem REST Service. Wenn Sie HTTP als zugrunde liegendes Protokoll verwenden, sind die folgenden Standards Bestandteil des Vertrags:

  • HTTP 1.1
    • methodendefinitionen
    • statuscode-Definitionen
    • cache-Steuerelement-Header
    • überschriften vom Typ accept und content akzeptieren
    • auth-Header
  • IRI (utf8 URI )
  • körper (wähle einen aus)
  • hyperlinks
    • was sollte sie enthalten (wähle eins aus)
      • senden in Link-Header
      • senden einer Hypermedien-Antwort, z.B. html, atom + xml, hal + json, ld + json & hydra, etc ...
    • semantik
      • verwenden Sie IANA-Verknüpfungsbeziehungen und wahrscheinlich benutzerdefinierte Verknüpfungsbeziehungen
      • verwenden Sie ein anwendungsspezifisches RDF Vokabular

REST hat eine zustandslose Einschränkung, die festlegt, dass die Kommunikation zwischen dem Dienst REST und dem Client zustandslos sein muss. Dies bedeutet, dass der Dienst REST die Clientzustände nicht verwalten kann, sodass Sie keinen serverseitigen Sitzungsspeicher haben können. Sie müssen jede einzelne Anfrage authentifizieren. So ist beispielsweise die HTTP-Basisauthentifizierung (Teil des HTTP-Standards) in Ordnung, da bei jeder Anforderung der Benutzername und das Kennwort gesendet werden.

Um Ihnen Fragen zu beantworten

  1. Ja das kann sein.

    Um nur zu erwähnen, die Clients interessieren sich nicht für die IRI-Struktur, sondern für die Semantik, da sie Links mit Link-Relationen oder Link-Data-Attributen (RDF) folgen.

    Das einzig Wichtige an den IRIs ist, dass ein einzelnes IRI nur eine einzelne Ressource identifizieren muss. Es ist einer einzelnen Ressource wie einem Benutzer gestattet, viele verschiedene IRIs zu haben.

    Es ist ziemlich einfach, warum wir Nice-IRIs wie /users/123/password Verwenden. Es ist viel einfacher, die Routing-Logik auf dem Server zu schreiben, wenn Sie die IRI einfach durch Lesen verstehen.

  2. Sie haben mehr Verben, wie PUT, PATCH, OPTIONS und noch mehr, aber Sie brauchen nicht mehr davon ... Anstatt neue Verben hinzuzufügen, müssen Sie lernen, wie Sie neue Ressourcen hinzufügen.

    activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}

    (Die Anmeldung ist aus Sicht von REST aufgrund der statusfreien Einschränkung nicht sinnvoll.)

  3. Ihren Benutzern ist es egal, warum das Problem besteht. Sie möchten nur wissen, ob ein Erfolg oder ein Fehler vorliegt, und wahrscheinlich eine Fehlermeldung, die sie verstehen können, zum Beispiel: "Entschuldigung, aber wir konnten Ihren Beitrag nicht speichern.", Etc ...

    Die HTTP-Status-Header sind Ihre Standard-Header. Alles andere sollte im Körper sein, denke ich. Ein einzelner Header reicht nicht aus, um beispielsweise detaillierte mehrsprachige Fehlermeldungen zu beschreiben.

  4. Die zustandslose Einschränkung (zusammen mit den Einschränkungen für Cache und geschichtete Systeme) stellt sicher, dass der Service gut skaliert wird. Sie werden sicherlich nicht Millionen von Sitzungen auf dem Server verwalten wollen, wenn Sie dasselbe auf den Clients tun können ...

    Der Drittanbieter-Client erhält ein Zugriffstoken, wenn der Benutzer über den Haupt-Client Zugriff darauf gewährt. Danach sendet der Drittanbieter-Client bei jeder Anforderung das Zugriffstoken. Es gibt kompliziertere Lösungen, z. B. können Sie jede einzelne Anfrage unterzeichnen usw. Weitere Informationen finden Sie im Handbuch OAuth.

Ähnliche Literatur

12
inf3rno

Für die von Ihnen angegebenen Beispiele verwende ich Folgendes:

activate_login

POST /users/1/activation

disable_login

DELETE /users/1/activation

passwort ändern

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

guthaben hinzufügen

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

Bei Fehlern würden Sie den Fehler im Hauptteil in dem Format zurückgeben, in dem Sie die Anforderung erhalten haben. Wenn Sie also Folgendes erhalten:

DELETE /users/1.xml

Sie würden die Antwort in XML zurücksenden, das Gleiche gilt für JSON usw.

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

11
jonnii
  1. Verwenden Sie post, wenn Sie nicht wissen, wie der neue Ressourcen-URI aussehen würde (Sie erstellen einen neuen Benutzer, die Anwendung weist dem neuen Benutzer die ID zu), PUT, um Ressourcen zu aktualisieren oder zu erstellen, von denen Sie wissen, wie sie dargestellt werden (Beispiel) : PUT /myfiles/thisismynewfile.txt)
  2. gibt die Fehlerbeschreibung im Nachrichtentext zurück
  3. Sie können HTTP-Authentifizierung verwenden (wenn es ausreicht). Webdienste sollten stateles sein
6
Arjan

Ich würde (als ersten Durchgang) vorschlagen, dass PUT nur zum Aktualisieren vorhandener Entitäten verwendet werden sollte. POST sollte zum Erstellen 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 Ihres ersten Abschnitts (bezüglich der Verbverwendung) sieht jedoch logisch aus.

5
Brian Agnew

Ausführlich, aber kopiert aus der HTTP 1.1-Methodenspezifikation 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 vom Request-URI identifiziert werden. Wenn sich der Anforderungs-URI auf einen datenerzeugenden Prozess bezieht, werden die erzeugten Daten als Entität in der Antwort und nicht als Quelltext des Prozesses zurückgegeben, es sei denn, dieser Text ist zufällig die Ausgabe des Prozesses.

Die Semantik der GET-Methode ändert sich zu einem "bedingten 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 fordert an, dass die Entität nur unter den von den bedingten Headerfeldern beschriebenen Umständen übertragen wird. Die bedingte GET-Methode soll die unnötige Netzwerknutzung reduzieren, indem zwischengespeicherte Entitäten aktualisiert werden können, ohne dass mehrere Anforderungen erforderlich sind oder bereits vom Client gespeicherte Daten übertragen werden müssen.

Die Semantik der GET-Methode ändert sich in "partielles GET", wenn die Anforderungsnachricht ein Range-Header-Feld enthält. Ein teilweises GET fordert, dass nur ein Teil der Entität übertragen wird, wie in Abschnitt 14.35 beschrieben. Die partielle GET-Methode soll die unnötige Netzwerknutzung reduzieren, indem teilweise abgerufene Entitäten vervollständigt werden können, ohne dass bereits vom Client gespeicherte Daten übertragen werden.

Die Antwort auf eine GET-Anforderung kann nur dann zwischengespeichert werden, wenn sie die in Abschnitt 13 beschriebenen Anforderungen für das HTTP-Caching erfüllt.

In Abschnitt 15.1.3 finden Sie Sicherheitsüberlegungen für Formulare.

9.5 POST

Die Methode POST wird verwendet, um den Origin-Server aufzufordern, die in der Anfrage enthaltene Entität als neuen Untergebenen der durch den Request-URI in der Anfragezeile angegebenen Ressource zu akzeptieren. POST soll eine einheitliche Methode ermöglichen, um die folgenden Funktionen abzudecken:

  - 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 hängt normalerweise von der Request-URI ab. Die bereitgestellte Entität ist dieser URI auf die gleiche Weise untergeordnet wie eine Datei Ein Verzeichnis, das es enthält, ein Nachrichtenartikel ist einer Newsgroup untergeordnet, in der es veröffentlicht wird, oder ein Datensatz ist einer Datenbank untergeordnet.

Die von der POST -Methode ausgeführte Aktion führt möglicherweise nicht zu einer Ressource, die von einem URI identifiziert werden kann. In diesem Fall ist entweder 200 (OK) oder 204 (No Content) der entsprechende Antwortstatus Dies hängt davon ab, ob die Antwort eine Entität enthält, die das Ergebnis beschreibt.

Wenn eine Ressource auf dem Origin-Server erstellt wurde, SOLLTE die Antwort 201 (Erstellt) lauten und eine Entität enthalten, die den Status der Anforderung beschreibt und auf die neue Ressource verweist, sowie einen Standort-Header (siehe Abschnitt 14.30).

Antworten auf diese Methode können nicht zwischengespeichert werden, es sei denn, die Antwort enthält die entsprechenden Felder für die Cachesteuerung oder den Ablauf der Header. Mit der Antwort 303 (Andere anzeigen) kann der Benutzeragent jedoch angewiesen werden, eine zwischenspeicherbare Ressource abzurufen.

POST-Anforderungen MÜSSEN die in Abschnitt 8.2 festgelegten Anforderungen für die Nachrichtenübertragung erfüllen.

Weitere Informationen zur Sicherheit finden Sie in Abschnitt 15.1.3.

9.6 PUT

Die PUT-Methode fordert an, dass die eingeschlossene Entität unter dem angegebenen Request-URI gespeichert wird. Wenn sich der Anforderungs-URI auf eine bereits vorhandene Ressource bezieht, MUSS die beigefügte Entität als eine modifizierte Version der auf dem Origin-Server befindlichen Entität betrachtet werden. Wenn der Anforderungs-URI nicht auf eine vorhandene Ressource verweist und dieser URI vom anfordernden Benutzeragenten als neue Ressource definiert werden kann, kann der Origin-Server die Ressource mit diesem URI erstellen. Wenn eine neue Ressource erstellt wird, MUSS der Origin-Server den Benutzeragenten über die Antwort 201 (Erstellt) informieren. Wenn eine vorhandene Ressource geändert wird, MÜSSEN die Antwortcodes 200 (OK) oder 204 (No Content) gesendet werden, um den erfolgreichen Abschluss der Anforderung anzuzeigen. Wenn die Ressource nicht mit dem Request-URI erstellt oder geändert werden konnte, MUSS 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-Header) ignorieren, die er nicht versteht oder nicht implementiert, und MUSS in solchen Fällen eine 501-Antwort (nicht implementiert) zurückgeben.

Wenn die Anforderung einen Cache durchläuft und der Anforderungs-URI eine oder mehrere aktuell zwischengespeicherte Entitäten identifiziert, MÜSSEN diese Einträge als veraltet behandelt werden. Antworten auf diese Methode können nicht zwischengespeichert werden.

Der grundlegende Unterschied zwischen den Anforderungen POST und PUT) spiegelt sich in der unterschiedlichen Bedeutung der Anforderungs-URI wider. Die URI in einer Anforderung POST identifiziert die Ressource, die verwendet wird Diese Ressource kann ein datenakzeptierender Prozess, ein Gateway zu einem anderen Protokoll oder eine separate Entität sein, die Anmerkungen akzeptiert.Im Gegensatz dazu identifiziert der URI in einer PUT-Anforderung die der Anforderung beigefügte Entität - den Benutzer Der Agent weiß, welche URI vorgesehen ist, und der Server DARF NICHT versuchen, die Anforderung auf eine andere Ressource anzuwenden. Wenn der Server wünscht, dass die Anforderung auf eine andere URI angewendet wird,

es MUSS eine 301-Antwort (dauerhaft verschoben) senden; Das Benutzerprogramm KANN dann selbst entscheiden, ob die Anforderung umgeleitet werden soll oder nicht.

Eine einzelne Ressource kann durch viele verschiedene URIs identifiziert werden. Beispielsweise kann ein Artikel eine URI zur Identifizierung der "aktuellen Version" haben, die von der URI zur Identifizierung der einzelnen Versionen getrennt ist. In diesem Fall kann eine PUT-Anforderung für einen allgemeinen URI dazu führen, dass mehrere andere URIs vom Origin-Server definiert werden.

HTTP/1.1 definiert nicht, wie sich eine PUT-Methode auf den Status eines Origin-Servers auswirkt.

PUT-Anforderungen MÜSSEN die in Abschnitt 8.2 festgelegten Anforderungen für die Nachrichtenübertragung erfüllen.

Sofern für einen bestimmten Entitätsheader nichts anderes angegeben ist, MÜSSEN die Entitätsheader in der PUT-Anforderung auf die vom PUT erstellte oder geänderte Ressource angewendet werden.

9.7 LÖSCHEN

Die DELETE-Methode fordert den Origin-Server auf, die durch den Request-URI angegebene Ressource zu löschen. Diese Methode kann durch menschliches Eingreifen (oder auf andere Weise) auf dem Origin-Server außer Kraft gesetzt werden. Dem Client kann nicht garantiert werden, dass die Operation ausgeführt wurde, selbst wenn der vom Origin-Server zurückgegebene Statuscode angibt, 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 an einen unzugänglichen Ort zu verschieben.

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

Wenn die Anforderung einen Cache durchläuft und der Anforderungs-URI eine oder mehrere aktuell zwischengespeicherte Entitäten identifiziert, MÜSSEN diese Einträge als veraltet behandelt werden. Antworten auf diese Methode können nicht zwischengespeichert werden.

5
gahooa

Informationen zu REST - Rückkehrcodes: Es ist falsch , HTTP-Protokollcodes und REST - Ergebnisse zu mischen.

Ich habe jedoch viele Implementierungen gesehen, die sich mischten, und viele Entwickler stimmen mir möglicherweise nicht zu.

HTTP-Rückkehrcodes beziehen sich auf den HTTP Request Selbst. Ein REST -Aufruf wird mithilfe einer Hypertext Transfer Protocol-Anforderung ausgeführt und funktioniert auf einer niedrigeren Ebene als die aufgerufene REST -Methode. REST ist ein Konzept/Ansatz und seine Ausgabe ist ein geschäftliches/logisches Ergebnis, während der HTTP-Ergebniscode ein Transport ist einer.

Wenn Sie beispielsweise/users/aufrufen, ist die Rückgabe von 404 Not found verwirrend, da dies Folgendes bedeuten kann:

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

"403 Verboten/Zugriff verweigert" kann bedeuten:

  • Sondergenehmigung erforderlich. Browser können damit umgehen, indem sie nach dem Benutzer/Passwort fragen. (HTTP)
  • Falsche Zugriffsberechtigungen auf dem Server konfiguriert. (HTTP)
  • Sie müssen authentifiziert sein (REST)

Und die Liste kann mit "500 Server error" (ein Apache/Nginx-HTTP-Fehler oder ein Business-Constraint-Fehler in REST) ​​oder anderen HTTP-Fehlern usw. fortgesetzt werden.

Aus dem Code ist schwer zu verstehen, was der Grund für den Fehler war, ein HTTP-Fehler (Transportfehler) oder ein REST - Fehler (logischer Fehler).

Wenn die HTTP-Anforderung physisch erfolgreich ausgeführt wurde, sollte immer 200-Code zurückgeben, unabhängig davon, ob die Datensätze gefunden wurden oder nicht. Weil die URI-Ressource gefunden wurde und vom http-Server verwaltet wurde. Ja, möglicherweise wird ein leerer Satz zurückgegeben. Ist es möglich, eine leere Webseite mit 200 als http-Ergebnis zu erhalten, oder?

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

Außerdem können einige Internetanbieter Ihre Anfragen abfangen und Ihnen einen 404-HTTP-Code zurückgeben. Dies bedeutet nicht, dass Ihre Daten nicht gefunden werden, aber auf Transportebene stimmt etwas nicht.

Von Wiki :

Im Juli 2004 stellte der britische Telekommunikationsanbieter BT Group das System zur Blockierung von Cleanfeed-Inhalten bereit, das eine 404-Fehlermeldung für alle von der Internet Watch Foundation als potenziell illegal erkannten Anforderungen an Inhalte zurückgibt. Andere ISPs geben unter denselben Umständen einen "verbotenen" HTTP 403-Fehler zurück. Auch in Thailand und Tunesien wurde über die Praxis berichtet, gefälschte 404-Fehler zu verwenden, um die Zensur zu verschleiern. In Tunesien, wo die Zensur vor der Revolution von 2011 schwerwiegend 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.

2
Marcodor