Wie erstelle ich REST-URLs ohne Verben?

283

Ich habe Probleme zu bestimmen, wie erholsame URLs entworfen werden sollen. Ich bin alle für den erholsamen Ansatz, URLs mit Substantiven und nicht mit Verben zu verwenden, verstehe nicht, wie das geht.

Wir erstellen einen Service zur Implementierung eines Finanzrechners. Der Rechner verwendet eine Reihe von Parametern, die wir über eine CSV-Datei hochladen. Die Anwendungsfälle würden Folgendes umfassen:

  1. Laden Sie neue Parameter hoch
  2. Holen Sie sich die neuesten Parameter
  3. Parameter für ein bestimmtes Geschäftsdatum abrufen
  4. Aktivieren Sie eine Reihe von Parametern
  5. Überprüfen Sie eine Reihe von Parametern

Ich denke, der erholsame Ansatz wäre, die folgenden Typ-URLs zu haben:

/parameters
/parameters/12-23-2009

Sie können die ersten drei Anwendungsfälle erreichen mit:

  1. POST, in dem Sie die Parameterdatei in die Post-Anfrage aufnehmen
  2. Erste URL abrufen
  3. Holen Sie sich die zweite URL

Aber wie macht man den 4. und 5. Anwendungsfall ohne Verb? Benötigen Sie keine URLs wie:

/parameters/ID/activate
/parameters/ID/validate

??

Marcus Leon
quelle
3
Ich bevorzuge PATCH anstelle von POST für die teilweise Aktualisierung.
user2016971

Antworten:

71

Vielleicht so etwas wie:

PUT /parameters/activation HTTP/1.1
Content-Type: application/json; encoding=UTF-8
Content-Length: 18

{ "active": true }
Yfeldblum
quelle
1
POSTist in Ordnung, wenn Sie eine "Prozedur" ausführen müssen, z. B. die Parameter jedes Mal überprüfen, wenn Sie eine Anfrage senden. Wenn Sie jedoch den (Anwendungs-) Status der Ressource ändern, aktualisieren Sie tatsächlich die vorhandene Ressource, erstellen keine neue Ressource und stellen keine Verarbeitungsanforderung.
Andrey Vlasovskikh
19
PUT dient zum Erstellen einer neuen Ressource oder zum Platzieren (ganz, nicht teilweise) einer neuen Ressource unter einer bestimmten URL. Ich sehe nicht, wie PUT in diesen Fall passt.
Bretonischer
30
Eigentlich POSTvs PUTist nicht genau wie insertvs update. PUTAktualisiert die dem angegebenen Pfad entsprechende Ressource oder erstellt eine neue Ressource, die dem angegebenen Pfad entspricht. POSTerstellt irgendwo eine neue Ressource. Zum Beispiel PUT /blog/posts/3/comments/5wird den entsprechenden Kommentar aktualisieren, während POST /blog/posts/3/commentseine neue erstellen commentRessource (und soll den Weg auf die neue Ressource in der Antwort zurück).
Yfeldblum
23
@Justice @Breton Der wichtigere Unterschied ist, dass er PUTidempotent ist, während dies POSTnicht der Fall ist. Normalerweise sollten Sie Ihre Ergebnisse so stark wie möglich einschränken. Das Festhalten an PUThält dem Kunden des Dienstes weitere Informationen.
Andrey Vlasovskikh
3
Die Ressource könnte auch / parameters / status gewesen sein und der Hauptteil der Anfrage könnte nur "aktiv" gewesen sein. Auf diese Weise platzieren Sie eine ganz neue Ressource auf einer bestimmten URL.
Carlos Aguayo
991

Allgemeine Grundsätze für ein gutes URI-Design:

  • Verwenden Sie keine Abfrageparameter, um den Status zu ändern
  • Tu es nichtVerwenden Pfade in gemischten Groß- und Kleinschreibung, wenn Sie helfen können. Kleinbuchstaben sind am besten
  • Verwenden Sie keine implementierungsspezifischen Erweiterungen in Ihren URIs (.php, .py, .pl usw.).
  • Fallen Sie nicht mit Ihren URIs in RPC
  • Sie beschränken Sie Ihre URI Raum so weit wie möglich
  • Halten Sie die Pfadsegmente kurz
  • Do bevorzugt entweder /resourceoder /resource/; Erstellen Sie 301 Weiterleitungen von der, die Sie nicht verwenden
  • Haben Verwendung Abfrageparameter für Unter Auswahl einer Ressource; dh Paginierung, Suchanfragen
  • Do bewegen Sachen aus dem URI, die in einem HTTP - Header oder ein Körper sein sollten

(Hinweis: Ich habe nicht "RESTful URI Design" gesagt. URIs sind in REST im Wesentlichen undurchsichtig.)

Allgemeine Grundsätze für die Auswahl der HTTP-Methode:

  • Nicht immer GET zu altem Zustand verwenden; Dies ist eine großartige Möglichkeit, den Googlebot Ihren Tag ruinieren zu lassen
  • Sie nicht verwenden , PUT , wenn Sie eine gesamte Ressource aktualisieren
  • Sie nicht verwenden , PUT , wenn Sie auch eine GET auf dem gleichen URI zu Recht tun können
  • Sie nicht verwenden POST Informationen abzurufen , die langlebig ist , oder dass könnte Cache sinnvoll sein ,
  • Führen Sie keine Operation aus, die mit PUT nicht idempotent ist
  • Haben Verwendung GET für so viel wie möglich
  • Haben Verwendung POST den Vorzug vor PUT im Zweifelsfall
  • Haben Verwendung POST , wenn Sie zu tun haben, etwas , das fühlt sich RPC-like
  • Haben Verwendung PUT für Klassen von Ressourcen, die größer sind oder hierarchische
  • Machen DELETE Verwendung bevorzugt , um es zu entfernen Ressourcen
  • Do Verwendung GET für Dinge wie Berechnungen, es sei denn , Ihr Eingang ist groß, wobei in diesem Fall der Verwendung POST

Allgemeine Prinzipien des Webdienstdesigns mit HTTP:

  • Fügen Sie keine Metadaten in den Text einer Antwort ein, die sich in einem Header befinden sollte
  • Fügen Sie Metadaten nicht in eine separate Ressource ein, es sei denn, die Einbeziehung würde einen erheblichen Overhead verursachen
  • Sie verwenden den entsprechenden Statuscode
    • 201 Creatednach dem Erstellen einer Ressource; Die Ressource muss zum Zeitpunkt des Sendens der Antwort vorhanden sein
    • 202 Accepted nachdem Sie eine Operation erfolgreich ausgeführt oder eine Ressource asynchron erstellt haben
    • 400 Bad Requestwenn jemand eine Operation an Daten ausführt, die eindeutig falsch sind; Für Ihre Anwendung kann dies ein Validierungsfehler sein. Im Allgemeinen reservieren Sie 500 für nicht erfasste Ausnahmen
    • 401 Unauthorizedwenn jemand auf Ihre API zugreift, ohne einen erforderlichen AuthorizationHeader anzugeben, oder wenn die Anmeldeinformationen in der Authorizationungültig sind; Verwenden Sie diesen Antwortcode nicht, wenn Sie keine Anmeldeinformationen über einen AuthorizationHeader erwarten .
    • 403 Forbidden wenn jemand auf böswillige Weise auf Ihre API zugreift oder wenn er nicht autorisiert ist
    • 405 Method Not Allowed wenn jemand POST verwendet, wenn er PUT usw. hätte verwenden sollen
    • 413 Request Entity Too Large wenn jemand versucht, Ihnen eine unannehmbar große Datei zu senden
    • 418 I'm a teapot beim Versuch, Kaffee mit einer Teekanne zu kochen
  • Haben Verwendung Caching - Header wann immer Sie können
    • ETag Header sind gut, wenn Sie eine Ressource leicht auf einen Hashwert reduzieren können
    • Last-Modified sollte Ihnen darauf hinweisen, dass es eine gute Idee ist, einen Zeitstempel für die Aktualisierung der Ressourcen einzuhalten
    • Cache-Controlund Expiressollte vernünftige Werte gegeben werden
  • Tun Sie alles, um Caching-Header in einer Anfrage zu berücksichtigen ( If-None-Modified, If-Modified-Since)
  • Do Verwendung Umleitungen , wenn sie Sinn machen, aber diese sollten für einen Web - Service selten

In Bezug auf Ihre spezifische Frage sollte POST für Nr. 4 und Nr. 5 verwendet werden. Diese Operationen fallen unter die oben genannte "RPC-ähnliche" Richtlinie. Denken Sie für # 5 daran, dass POST nicht unbedingt verwendet werden muss Content-Type: application/x-www-form-urlencoded. Dies kann genauso gut eine JSON- oder CSV-Nutzlast sein.

Bob Aman
quelle
11
413 ist für die Größe der Anfrage vorgesehen, die Sie senden, damit Sie höflich jemanden ablehnen können, der Ihnen Datenmengen sendet, häufig in Verbindung mit 411, sodass Sie die Leute zwingen, Ihnen mitzuteilen, wie viel gesendet wird. Für das Beispiel gegen 413 halte ich 400 für eine angemessenere Antwort.
Garry Shutler
5
+1, da dies eine großartige Ressource ist. Es ist jedoch eine allgemeine Ressource und beantwortet die Frage nicht direkt. Dies sollte idealerweise einen zusätzlichen Absatz mit einer spezifischen Antwort enthalten.
Samuel Neff
@GarryShutler Guter Fang, du hast absolut Recht. Danke für die Bearbeitung.
Bob Aman
1
Ja, Sie würden PUT nur in Fällen verwenden, in denen Sie das gesamte Objekt überschreiben. Ich würde jedoch behaupten, dass entweder PATCH oder POST im Falle einer teilweisen Aktualisierung einer Ressource angemessen sind. PATCH ist klarer in Bezug auf die Funktionsweise des Vorgangs, aber da nicht alle Clients in der Lage sind, eine PATCH- Anfrage zu stellen, ist es durchaus angebracht, stattdessen einen POST zuzulassen , und ich könnte sogar so weit gehen, dies zu befürworten POST sollte immer als Fallback zulässig sein, wenn PATCH verwendet wird.
Bob Aman
1
+1 für 409 Fehler. Ein 400-Fehler kann durch eine ausreichende clientseitige Validierung behoben werden. Ein 409 stellt klar, dass die Anforderung selbst akzeptabel und konsistent war, jedoch mit einem Aspekt des Serverstatus in Konflikt steht (normalerweise Parallelitätskontrollen, aber theoretisch jede Einschränkung ohne Eingabe).
Claytond
18

Wann immer es so aussieht, als ob Sie ein neues Verb benötigen, denken Sie daran, dieses Verb stattdessen in ein Substantiv umzuwandeln. Verwandeln Sie beispielsweise "Aktivieren" in "Aktivierung" und "Validieren" in "Validierung".

Aber nur von dem, was Sie geschrieben haben, würde ich sagen, dass Ihre Bewerbung viel größere Probleme hat.

Jedes Mal, wenn eine Ressource namens "Parameter" vorgeschlagen wird, sollte sie in den Gedanken jedes Projektteammitglieds rote Fahnen setzen. 'Parameter' kann buchstäblich auf jede Ressource angewendet werden. es ist nicht spezifisch genug.

Was genau repräsentiert ein 'Parameter'? Wahrscheinlich eine Reihe verschiedener Dinge, für die jeweils eine eigene Ressource vorgesehen sein sollte.

Ein anderer Weg, um dies zu erreichen: Wenn Sie Ihre Anwendung mit Endbenutzern besprechen (diejenigen, die vermutlich wenig über Programmierung wissen), welche Wörter verwenden sie selbst wiederholt?

Mit diesen Worten sollten Sie Ihre Anwendung gestalten.

Wenn Sie diese Konvertierung noch nicht mit potenziellen Benutzern durchgeführt haben, stoppen Sie jetzt alles und schreiben Sie erst dann eine weitere Codezeile! Nur dann hat Ihr Team eine Vorstellung davon, was gebaut werden muss.

Ich weiß nichts über Finanzsoftware, aber wenn ich raten müsste, würde ich sagen, dass einige der Ressourcen unter Namen wie "Bericht", "Zahlung", "Überweisung" und "Währung" geführt werden könnten.

Es gibt eine Reihe guter Bücher zu diesem Teil des Software-Design-Prozesses. Zwei, die ich empfehlen kann, sind domänengesteuerte Entwurfs- und Analysemuster .

Reiches Apodaca
quelle
1
Das ist ein wirklich guter Punkt. Es ist leicht zu übersehen, wenn Sie in der Lage sind, formale Logik und Argumentation zu verarbeiten. Es spielt keine Rolle, was X ist, solange es auf gültige Weise mit den anderen Teilen zusammenpasst. Menschliche Faktoren verschwinden einfach.
Bretonischer
1
Manchmal finde ich es nützlich, die Wörter in eine "Verarbeitungsressource" wie "Aktivator" oder "Validator" umzuwandeln. Gemäß RFC 2616 kann POST verwendet werden, um "einen Datenblock ... für einen Datenverarbeitungsprozess bereitzustellen"
Darrel Miller,
Verstanden. In diesem Fall bezeichnen Benutzer die Daten als "Parameter" (oder "Risikoparameter" oder ähnliches). Die Liste der Parameter enthält viele verschiedene Arten von Einstellungen, aber die Parameter werden immer als Ganzes hochgeladen (in einer CSV-Datei).
Marcus Leon
@Marcus - das klingt nach einem sehr ungewöhnlichen Fall. Wenn Sie die Funktionsweise Ihrer App genauer erläutern, können wir Ihnen möglicherweise bessere Vorschläge zur Identifizierung von Ressourcen unterbreiten.
Rich Apodaca
1
"Wenn Sie Ihre Anwendung mit Endbenutzern besprechen, welche Wörter verwenden sie selbst wiederholt?" ... und was ist, wenn sie alle Verben sind? XD
Amalgovinus
11

Das Design Ihrer URLs hat nichts damit zu tun, ob Ihre Anwendung RESTful ist oder nicht. Der Ausdruck "RESTful URLs" ist daher Unsinn.

Ich denke, Sie sollten noch etwas darüber lesen, was REST eigentlich ist. REST behandelt die URLs als undurchsichtig und weiß daher nicht, was darin enthalten ist, ob es Verben oder Substantive gibt oder was auch immer. Möglicherweise möchten Sie Ihre URLs weiterhin entwerfen, aber es geht um die Benutzeroberfläche, nicht um REST.

Kommen wir jedoch zu Ihrer Frage: Die letzten beiden Fälle sind nicht RESTful und passen nicht in ein erholsames Schema. Das könnte man RPC nennen. Wenn Sie REST ernst nehmen, müssen Sie die Funktionsweise Ihrer Anwendung von Grund auf überdenken. Entweder das oder geben Sie REST auf und machen Sie Ihre App einfach als RPC-App.

Hrmmm vielleicht nicht.

Die Idee hier ist, dass Sie alles als Ressource behandeln müssen. Sobald ein Parametersatz eine URL hat, auf die Sie verweisen können, fügen Sie einfach Folgendes hinzu:

GET [parametersurl]/validationresults

POST [paramatersurl]
body: {command:"activate"}

Aber auch dieses Aktivierungsobjekt ist RPC, nicht REST.

Bretonisch
quelle
Sie geben hier einen interessanten Punkt an. Können Sie etwas näher erläutern, wie der RESTful-Ansatz für so etwas aussehen würde?
Poezn
Ich habe ein bisschen Zeit damit verbracht, die Antworten hier zu lesen, und ich denke, Gerechtigkeit könnte etwas bewirken. Er modelliert einzelne Eigenschaften Ihres Parameterobjekts als einzelne Ressourcen und verwendet das PUT-Verb, um den Inhalt dieser Eigenschaft in dieser Ressource zu ersetzen. Hierbei wird der Status jedes Objekts als Sammlung von Ressourcen modelliert und der Status als Platzieren oder Entfernen oder Ändern der Ressource geändert. Zur Validierung: Sie benötigen lediglich eine Ressource, die auf magische Weise angibt, ob die Parameter gültig sind oder nicht, wie oben in meiner Antwort beschrieben. Das wäre in Ordnung, solange das keine Nebenwirkungen hat.
Bretonischer
Vorausgesetzt natürlich, dass "Aktivieren" lediglich eine einzelne Eigenschaft auf true setzt. Wenn es etwas anderes tun muss, ist es immer noch nicht RESTful und ich bin mir nicht sicher, wie Sie es RESTfully modellieren würden.
Bretonischer
Ich glaube nicht, dass man sagen kann, dass die letzten beiden Fälle nicht RESTful sind. Tatsächlich sind Aktivieren und Validieren nur indirekte Methoden, um zu sagen, dass die Ressource in einer Zustandsmaschine in einen neuen Status wechselt. REST ist durchaus in der Lage, dies zu modellieren.
Darrel Miller
@Darrel, ich denke, Sie weisen auf einen Teil von REST hin, der für viele Leute, die neu bei REST sind, eine Herausforderung sein kann. Wie können Sie eine Operation "Ressource x validieren" implementieren? Ich denke, die Herausforderung besteht darin, dass es sich um eine Operation handelt, die zu einer Änderung des Status führen kann, aber der neue Status ist das Ergebnis der Anforderung.
Sean
6

Die Aktivierungs- und Validierungsanforderungen sind Situationen, in denen Sie versuchen, den Status einer Ressource zu ändern. Es ist nicht anders, als eine Bestellung "abgeschlossen" oder eine andere Anfrage "eingereicht" zu machen. Es gibt zahlreiche Möglichkeiten, diese Art von Statusänderungen zu modellieren, aber eine, die meiner Meinung nach häufig funktioniert, besteht darin, Sammlungsressourcen für Ressourcen desselben Status zu erstellen und die Ressource dann zwischen den Sammlungen zu verschieben, um den Status zu beeinflussen.

zB Erstellen Sie einige Ressourcen wie,

/ActiveParameters
/ValidatedParameters

Wenn Sie eine Reihe von Parametern aktivieren möchten, fügen Sie diese der ActiveParameters-Auflistung hinzu. Sie können den Parametersatz entweder als Entitätskörper übergeben oder eine URL als Abfrageparameter wie folgt übergeben:

POST /ActiveParameters?parameter=/Parameters/{Id}

Dasselbe kann mit den / ValidatedParameters gemacht werden. Wenn die Parameter nicht gültig sind, kann der Server "Bad Request" an die Anforderung zurückgeben, um die Parameter zur Sammlung validierter Parameter hinzuzufügen.

Darrel Miller
quelle
1

Ich würde die folgenden Meta-Ressourcen und Methoden vorschlagen.

Aktivieren Sie Parameter und / oder validieren Sie sie:

> PUT /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Content-Type: application/json
> Connection: close
>
> {'active': true, 'require-valid': true}
>
< HTTP/1.1 200 OK
< Connection: close
<

Überprüfen Sie, ob die Parameter aktiv und gültig sind:

> GET /parameters/<id>/meta HTTP/1.1
> Host: example.com
> Connection: close
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Connection: close
<
< {
<     'active': true,
<     'require-valid': true,
<     'valid': {'status': false, 'reason': '...'}
< }
<
Andrey Vlasovskikh
quelle
Soweit ich weiß, geht es um die Benennung der erholsamen URLs, nicht um die Funktionalität, nicht wahr?
Poezn
2
Eine Frage, die auf "RESTful URLs" beschränkt ist, ist eine schlechte Frage und sollte nicht beantwortet werden. Die Frage sollte stattdessen erweitert werden, um "RESTful-Ressourcen mit zugehörigen Methoden und URLs" zu berücksichtigen - und als solche beantwortet werden.
Yfeldblum
Nach meinem Verständnis ging es um die URL-Namenskonventionen und die HTTP-Methoden, auf die die benannte Ressource antworten sollte.
Andrey Vlasovskikh
1

Ich bin ein bisschen traurig zu sehen, dass es nach mehr als 10 Jahren keine Antwort gibt, die wirklich besagt, wie so etwas wie das im OP angeforderte in einer REST-Architektur entworfen werden könnte, daher habe ich das Bedürfnis, dies jetzt zu tun.

Das Wichtigste zuerst, was ist REST?! Das Akronym REST oder ReST steht für "Representational State Transfer" und definiert den Austausch des Zustands einer Ressource in einem bestimmten Repräsentationsformat. Das Darstellungsformat richtet sich nach dem ausgehandelten Medientyp. Im Fall des application/htmlDarstellungsformats kann es sich um einen Stream von HTML-formatiertem Textinhalt handeln, der im Browser gerendert wird, wahrscheinlich nachdem einige Stylesheet-Formatierungen angewendet wurden, um bestimmte Elemente an bestimmten Stellen zu positionieren.

REST ist im Prinzip eine Verallgemeinerung des durchsuchbaren Webs, das wir alle kennen, obwohl es auf alle Arten von Anwendungen und nicht nur auf Browser abzielt. Daher gelten dieselben Konzepte, die für das Web gelten, auch für eine REST-Architektur. Eine Frage wie das Erreichen von "RESTful" -Ergebnissen besteht darin, die Frage zu beantworten, wie auf einer Webseite etwas erreicht werden kann, und dann dieselben Konzepte auf die Anwendungsebene anzuwenden.

Ein webbasierter Taschenrechner beginnt normalerweise mit einer "Seite", auf der Sie einige zu berechnende Werte eingeben können, bevor Sie die eingegebenen Daten an den Server senden. In HTML wird dies normalerweise über HTML- <form>Elemente erreicht, die einem Client die verfügbaren Parameter zum Festlegen, den Zielspeicherort zum Senden der Anforderung sowie das beim Senden der Eingabedaten anzuwendende Darstellungsformat beibringen. Dies kann dh so aussehen:

<html>
  <head>
    ...
  </head>
  <body>
    <form action="/../someResource" method="post" enctype="application/x-www-form-urlencoded">
      <label for="firstNumber">First number:</label>
      <input type="number" id="firstNumber" name="firstNumber"/>

      <label for="secondNumber">Second number:</label>
      <input type="number" id="secondNumber" name="secondNumber"/>

      <input type="submit" value="Add numbers"/>
    </form>
  </body>
</html>

Das obige Beispiel besagt, dass es zwei Eingabefelder gibt, die entweder vom Benutzer oder von anderen Automaten ausgefüllt werden können, und dass der Browser beim Aufrufen des Submit-Eingabeelements dafür sorgt, dass die Eingabedaten in a formatiert werden application/x-www-form-urlencoded gesendetes Darstellungsformat formatiert werden POSTin diesem Fall über die angegebene HTTP-Anforderungsmethode an den genannten Zielort . Wenn wir 1in das firstNumberEingabefeld und 2in das secondNumberEingabefeld eingeben , generiert der Browser eine Darstellung firstNumber=1&secondNumber=2und sendet diese als Hauptnutzlast der tatsächlichen Anforderung an die Zielressource.

Die an den Server gesendete HTTP-Rohanforderung kann daher folgendermaßen aussehen:

POST /../someResource
Host: www.acme.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Accept: application/html

firstNumber=1&secondNumber=2

Der Server kann die Berechnung durchführen und mit einer weiteren HTML-Seite antworten, die das Ergebnis der Berechnung enthält, da die Anforderung anzeigt, dass der Client dieses Format versteht.

Wie Breton bereits betont hat, gibt es keine "RESTful" -URL oder URI. Eine URI / URL ist eine eigene Sache und sollte einem Client / Benutzer keine Bedeutung vermitteln. In dem obigen Rechnerbeispiel ist ein Benutzer einfach nicht daran interessiert, wohin er die Daten senden soll. Er ist nur daran interessiert, dass beim Auslösen des Übermittlungs-Eingabefelds die Anforderung gesendet wird. Alle zur Ausführung der Aufgabe erforderlichen Informationen sollten bereits vom Server bereitgestellt werden.

Ein Browser weiß möglicherweise auch nicht, dass die Anforderung tatsächlich einen Taschenrechner mit einigen Eingabeparametern versorgt. Es kann sich auch um eine Art Bestellformular handeln, das nur die nächste Formulardarstellung zurückgibt, um den Bestellvorgang fortzusetzen, oder um eine völlig andere Art von Ressource. Es führt einfach das aus, was die HTML-Spezifikation in einem solchen Fall verlangt, und es ist egal, was der Server tatsächlich tut. Dieses Konzept ermöglicht es einem Browser, dasselbe Darstellungsformat zu verwenden, um alle möglichen Dinge zu erledigen, z. B. einige Dinge in Ihrem bevorzugten Online-Shop zu bestellen, mit Ihren besten Freunden zu chatten, sich in einem Online-Konto anzumelden und so weiter.

Die Erschwinglichkeit bestimmter Elemente, z. B. im Fall des Eingabefelds "Senden", das normalerweise als Schaltfläche gerendert wird, definiert, was Sie damit tun sollen. Im Falle einer Schaltfläche oder eines Links werden Sie grundsätzlich aufgefordert, darauf zu klicken. Andere Elemente können unterschiedliche Leistungen vermitteln. Ein solcher Vorteil kann auch über Link-Beziehungen ausgedrückt werden , z. B. mit preloadkommentierten Links, die einem Kunden im Grunde mitteilen, dass er den Inhalt der verknüpften Ressource bereits im Hintergrund laden kann, da der Benutzer diesen Inhalt höchstwahrscheinlich als Nächstes abrufen wird. Solche Link-Beziehungen sollten natürlich standardisiert sein oder dem Erweiterungsmechanismus für Beziehungstypen folgen, wie er durch Web-Linking definiert ist .

Dies sind die grundlegenden Konzepte, die im Web verwendet werden und die auch in einer REST-Architektur verwendet werden sollten. Laut "Onkel Bob" Robert C. Martin geht es bei einer Architektur um Absicht, und die Absicht hinter der REST-Architektur ist die Entkopplung von Clients von Servern, damit sich Server in Zukunft frei entwickeln können, ohne befürchten zu müssen, dass sie Clients beschädigen. Dies erfordert leider viel Disziplin, da es so einfach ist, Kopplungen einzuführen oder schnelle Lösungen hinzuzufügen, um die Arbeit zu erledigen und weiterzumachen. Wie Jim Webber in einer REST-Architektur hervorhob, sollten Sie als Dienstanbieter versuchen, ein Domänenanwendungsprotokoll zu entwerfen , das einem textbasierten Computerspiel der 70er Jahre ähnelt, das Clients bis zum Ende eines Prozesses durchlaufen.

Was viele sogenannte "REST" -APIs in der Realität leider tun, ist alles andere als das. Sie sehen den Austausch von hauptsächlich JSON-basierten Daten, die in einer API-spezifischen externen Dokumentation angegeben sind, die normalerweise im laufenden Betrieb nur schwer dynamisch zu integrieren ist. Das Format, wie eine Anforderung aussehen muss, ist ebenfalls in der externen Dokumentation fest codiert, was zu einer Vielzahl von Implementierungsinterpretationen von URIs führt codiert. Dies um vordefinierte Typen zurückzugebenanstatt ein allgemeines Darstellungsformat zu verwenden, das im Voraus ausgehandelt wird. Dies verhindert, dass sich Server ändern, da Clients jetzt ein bestimmtes Datenformat (Hinweis, kein Darstellungsformat!) Für vordefinierte URIs erwarten. Dieser benutzerdefinierte Datenformataustausch verhindert außerdem, dass Clients mit anderen APIs interagieren, da das "Datenformat" normalerweise für eine bestimmte API gilt. Wir kennen dieses Konzept aus der Vergangenheit aus RPC-Technologien wie Corba, RMI oder SOAP, die wir als irgendwie böse verurteilen, obwohl Peppol erneut darauf zurückgegriffen hat, indem er AS2 durch AS4 als Standardübertragungsprotokoll ersetzt hat.

In Bezug auf die tatsächlich gestellte Frage unterscheidet sich das Senden von Daten als CSV-Datei nicht von der Verwendung von application/x-www-form-urlencodedDarstellungen oder ähnlichem. Jim Webber machte deutlich, dass HTTP schließlich nur ein Transportprotokoll ist, dessen Anwendungsdomäne die Übertragung von Dokumenten über das Web ist . Client und Server sollten mindestens beide unterstützen, text/csvwie in RFC 7111 definiert . Diese CSV-Datei kann als Folge der Verarbeitung eines Medientyps generiert werden, der Formularelemente, ein Zielelement oder Attribut zum Senden der Anforderung sowie die HTTP-Methode zum Hochladen der Konfiguration definiert.

Es gibt einige Medientypen, die Formulare wie HTML , HAL Forms , Halform , Ion oder Hydra unterstützen . Derzeit ist mir jedoch kein Medientyp bekannt, der die Eingabedaten automatisch text/csvdirekt codieren kann. Daher muss möglicherweise ein Medientyp definiert und in der Medientypregistrierung von IANA registriert werden .

Das Hoch- und Herunterladen des gesamten Parametersatzes sollte wohl kein Problem sein. Wie bereits erwähnt, ist der Ziel-URI nicht relevant, da ein Client den URI nur zum Abrufen neuer zu verarbeitender Inhalte verwendet. Das Filtern nach Geschäftsdatum sollte auch nicht zu schwierig sein. Hier sollte der Server jedoch dem Client alle Möglichkeiten bieten, aus denen der Client einfach wählen kann. In den letzten Jahren haben sich GraphQL und RestQL weiterentwickelt, die eine SQL-ähnliche Sprache einführen, die auf einen bestimmten Endpunkt ausgerichtet werden kann, um eine gefilterte Antwort zu erhalten. Im wahrsten Sinne des Wortes verstößt dies jedoch gegen die Idee hinter REST, da a) GraphQL nur einen einzigen Endpunkt verwendet, der die optimale Nutzung des Caching irgendwie verhindert, und b) die Kenntnis der verfügbaren Felder im Voraus erfordert, was zur Einführung einer Kopplung von Clients führen kann zum Basisdatenmodell der Ressource.

Das Aktivieren oder Deaktivieren bestimmter Konfigurationsparameter ist lediglich eine Frage des Auslösens der Hypermedia-Steuerelemente, die diesen Vorteil bieten. In HTML-Formularen kann dies ein einfaches Kontrollkästchen oder eine mehrzeilige Auswahl in einer Liste oder dergleichen sein. Abhängig vom Formular und der von ihm definierten Methode kann es dann möglicherweise die gesamte Konfiguration über senden PUToder über die vorgenommenen Änderungen klug sein und nur eine teilweise Aktualisierung über durchführen PATCH. Letzteres erfordert grundsätzlich eine Berechnung der Änderungsdarstellung auf die aktualisierte und speist den Server mit den erforderlichen Schritten, um die aktuelle Darstellung in die gewünschte umzuwandeln. Gemäß der PATH-Spezifikation muss dies innerhalb einer Transaktion erfolgen, damit entweder alle oder keine der Schritte angewendet werden.

HTTP ermöglicht und ermutigt einen Server, eine empfangene Anfrage im Voraus zu validieren, bevor die Änderungen übernommen werden. Für PUT heißt es in der Spezifikation:

Ein Ursprungsserver SOLLTE überprüfen, ob die PUT-Darstellung mit allen Einschränkungen des Servers für die Zielressource übereinstimmt, die vom PUT nicht geändert werden können oder werden. Dies ist besonders wichtig, wenn der Ursprungsserver interne Konfigurationsinformationen zum URI verwendet, um die Werte für Darstellungsmetadaten für GET-Antworten festzulegen. Wenn eine PUT-Darstellung nicht mit der Zielressource übereinstimmt, sollte der Ursprungsserver sie entweder konsistent machen, indem er die Darstellung transformiert oder die Ressourcenkonfiguration ändert, oder mit einer entsprechenden Fehlermeldung antworten, die ausreichende Informationen enthält, um zu erklären, warum die Darstellung ungeeignet ist. Die Statuscodes 409 (Konflikt) oder 415 (Nicht unterstützter Medientyp) werden vorgeschlagen.

Wenn die Zielressource beispielsweise so konfiguriert ist, dass sie immer den Inhaltstyp "text / html" hat und die Darstellung als PUT den Inhaltstyp "image / jpeg" hat, sollte der Ursprungsserver einen der folgenden Schritte ausführen:

ein. Konfigurieren Sie die Zielressource neu, um den neuen Medientyp widerzuspiegeln.

b. Transformieren Sie die PUT-Darstellung in ein Format, das mit dem der Ressource übereinstimmt, bevor Sie sie als neuen Ressourcenzustand speichern. oder,

c. lehnen Sie die Anforderung mit einer 415-Antwort (nicht unterstützter Medientyp) ab, die angibt, dass die Zielressource auf "text / html" beschränkt ist, möglicherweise mit einem Link zu einer anderen Ressource, die ein geeignetes Ziel für die neue Darstellung wäre.

HTTP definiert nicht genau, wie sich eine PUT-Methode auf den Status eines Ursprungsservers auswirkt, und zwar über das hinaus, was durch die Absicht der Benutzeragentenanforderung und die Semantik der Antwort des Ursprungsservers ausgedrückt werden kann. ...

Um diesen Beitrag zusammenzufassen, sollten Sie entweder einen vorhandenen Medientyp verwenden, mit dem Sie einem Client die erforderlichen oder unterstützten Eingabeparameter, den Zielspeicherort für die Anforderung, den zu verwendenden Vorgang sowie den Medientyp beibringen können Die Anfrage muss formatiert sein oder Sie müssen eine eigene Anfrage definieren, die Sie bei IANA registrieren. Letzteres kann erforderlich sein, wenn Sie die Eingabe in konvertieren möchtentext/csvLaden Sie anschließend die CSV-Darstellung auf den Server hoch. Die Validierung sollte erfolgen, bevor die Änderungen auf die Ressource angewendet werden. Die tatsächliche URI sollte für andere Clients nur relevant sein, um zu bestimmen, wohin die Anfrage gesendet werden soll, und kann daher von Ihnen, dem Service-Implementierer, frei gewählt werden. Wenn Sie diese Schritte ausführen, haben Sie so gut wie die Freiheit, Ihre Serverseite jederzeit zu ändern, und Clients werden nicht beschädigt, wenn sie die verwendeten Medientypen unterstützen.

Roman Vottner
quelle
0

Bearbeiten: In der Tat hätte die URI verhindert GET, dass Anforderungen idempotent bleiben.


Für die Validierung würde jedoch die Verwendung von HTTP-Statuscodes zur Benachrichtigung über die Gültigkeit einer Anforderung (zum Erstellen eines neuen oder zum Ändern eines vorhandenen 'Parameters') zu einem Restful-Modell passen.

Melden Sie sich mit einem 400 Bad RequestStatuscode zurück, wenn die übermittelten Daten ungültig sind / sind und die Anforderung vor der erneuten Übermittlung geändert werden muss ( HTTP / 1.1-Statuscodes ).

Dies hängt jedoch davon ab, dass die Validierung zum Zeitpunkt der Einreichung erfolgt, anstatt sie wie in Ihrem Anwendungsfall zu verschieben. Die anderen Antworten haben geeignete Lösungen für dieses Szenario.

Derek Mortimer
quelle
Der URI soll eine Kennung sein. Die Verwendung einer bestimmten URL sollte keine Nebenwirkungen haben. Stellen Sie sich vor, was ein Proxy damit machen würde.
Bretonischer
2
oder Google für diese Angelegenheit. Ich habe einmal eine Geschichte über einen Webstore gelesen, in dem alle Produkte von Google wegen dieser Art von Idiotie gelöscht wurden.
Bretonischer
0

In einer REST-Umgebung ist jede URL eine eindeutige Ressource. Was sind Ihre Ressourcen? Ein Finanzrechner hat wirklich keine offensichtlichen Ressourcen. Sie müssen sich mit den von Ihnen aufgerufenen Parametern befassen und die Ressourcen abrufen. Beispielsweise kann ein Tilgungskalender für ein Darlehen eine Ressource sein. Die URL für den Kalender kann Startdatum, Laufzeit (in Monaten oder Jahren), Zeitraum (wenn die Zinsen zusammengesetzt werden), Zinssatz und Anfangsprinzip enthalten. Mit all diesen Werten haben Sie einen bestimmten Zahlungskalender:

http://example.com/amort_cal/2009-10-20/30yrsfixed/monthly/5.00/200000

Jetzt weiß ich nicht, was Sie berechnen, aber Ihr Konzept einer Parameterliste klingt nicht RESTful. Wie jemand anderes sagte, klingen Ihre oben genannten Anforderungen mehr nach XMLRPC. Wenn Sie nach REST suchen, benötigen Sie Substantive. Berechnungen sind keine Substantive, sondern Verben, die auf Substantive einwirken. Sie müssen es umdrehen, um die Substantive aus Ihren Berechnungen herauszuziehen.

jmucchiello
quelle
5
Ich finde es ein bisschen albern, hier Schrägstriche zu verwenden. Was wäre falsch an amort_cal? Date = 2009-10-20 & type = 30yrsfixed & period = month & rate = 5.0 & initialamount = 200000? REST ist das egal, solange es sich um eine Ressource handelt. Die URI-Spezifikation kümmert sich jedoch darum. Wie stellen Sie sich relative Links vor, um mit einem solchen Schema zu arbeiten?
Bretonischer
Sie sprechen dennoch einen guten Punkt an. Müssen diese "Parameter" überhaupt serverseitig gespeichert werden? Wenn es sich nur um eine einmalige Berechnung handelt, erstellen Sie doch einfach einen virtuellen Bereich, in dem sich die Parameter in der URL befinden. Solange Sie den internen Status nicht ändern, sollte dies in Ordnung sein.
Bretonischer
1
Und "Parameter" gelten nicht für eine "Ressource". Eine Ressource ist eine einzelne Entität mit einer eindeutigen Kennung. Meine URL identifiziert eine einzelne Ressource. Eine parametrisierte URL gibt eine Sammlung von Ressourcen an, aus denen Sie mithilfe der Parameter auswählen.
jmucchiello
2
REST basiert nicht auf "CRUDing Resources". Das Einfügen aller Abfrageparameter in Pfadsegmente führt nicht automatisch zu einer RESTful-Schnittstelle, da Sie jetzt glauben, Sie können jede Permutation als Ressource bezeichnen. Leider gibt es keinen magischen Prozess, mit dem Sie die Ressourcen in Ihrem System ermitteln können. Es erfordert sorgfältiges Design, keine mechanische Formel.
Darrel Miller
2
Auch hier kümmert sich die REST-Architektur nicht darum, was in der URL enthalten ist. Die URL soll undurchsichtig sein . Es spielt keine Rolle, sich auszuruhen, ob Sie Schrägstriche, Semikolons oder Unicode-Herzen als Trennzeichen verwenden. Lesen Sie dies und antworten Sie darauf - nicht auf das, was Sie sich von mir vorstellen.
Bretonischer