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/html
Darstellungsformats 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 POST
in diesem Fall über die angegebene HTTP-Anforderungsmethode an den genannten Zielort . Wenn wir 1
in das firstNumber
Eingabefeld und 2
in das secondNumber
Eingabefeld eingeben , generiert der Browser eine Darstellung firstNumber=1&secondNumber=2
und 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 preload
kommentierten 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-urlencoded
Darstellungen 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/csv
wie 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/csv
direkt 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 PUT
oder ü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/csv
Laden 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.