Konsequenzen, wenn eine REST-API nicht „richtig“ ausgeführt wird?

8

Ich werde diese Frage auf diese Weise stellen - was sind die Bedenken der Softwareentwicklung, wenn meine REST-API nicht "richtig" implementiert wird?

Was meinst du mit dem "richtigen" Weg? Lassen Sie mich meine Wahrnehmung des richtigen Weges erklären, dann erkläre ich Ihnen, wie ich es mache (nehmen Sie auch an, ich spreche von einer JSON-REST-API).

Der richtige Weg

  1. Staatenlosigkeit. Dies ist der Teil, den ich bekomme. Der Client behält den Status immer zu 100% für immer bei. Es ist nicht die Aufgabe des Servers, sondern die des Kunden.

  2. Die erwarteten Aktionen und Antworten für jedes Verb:

    • GET - Ruft eine vollständig angegebene Ressource ab, die nur durch die Berechtigung in der Anforderung oder einen Abfrageparameter begrenzt ist. Dies stellt sicher, dass keine Ressource im Prozess geändert wird.
    • POST - Bei einer vollständigen Ressourcenbeschreibung (wie einem JSON-Objekt) wird eine Ressource erstellt und diese Ressource zurückgegeben, wobei auch alle serverseitigen Eigenschaften wie Datumsangaben oder IDs erstellt werden.
    • LÖSCHEN - Löscht eine angegebene Ressource und gibt als Antwort nur 200 OK an
    • PUT - Bei einer vollständigen Objektdeklaration als Eingabe wird die Ressource an einem bestimmten Speicherort aktualisiert, wobei alle Felder der Ressource auf jedes der in der Eingabe angegebenen Felder aktualisiert werden. Damit wird klargestellt, dass das gesamte Objekt als Eingabe übergeben wird. Die gesamte aktualisierte Ressource wird mit allen Feldern zurückgegeben (entsprechend der Autorisierung oder anderen Eingabeflags).
    • PATCH - Wenn nur die Felder für eine Ressource geändert werden sollen, werden nur die Felder in einer angegebenen Ressource aktualisiert, die als Eingabe angegeben werden. (Hier bin ich unklar): Die gesamte Ressource wird zurückgegeben? (Oder sind es nur die aktualisierten Felder? Keine Ahnung. Ist mir egal.)
  3. Ressourcenpfade. In Anbetracht der Beziehung der Ressourcen zueinander kann ein Ressourcenpfad wie folgt aussehen:
    • / parentresource /: id
    • / parentresource /: id / childresource
    • / parentresource /: id / childresource /: childId
    • / parentresource /: id / childresource /: childId / subresource /: subresourceId (In diesem Beispiel gehört eine Unterressource zu einer untergeordneten Ressource, die zu einer übergeordneten Ressource gehört).

So wie ich es machen will

Das Obige ist mein Verständnis davon, wie eine REST-API funktionieren soll. Lassen Sie mich nun einige meiner Variationen zu den oben genannten auflisten:

  1. PUT / PATCH - Wozu wird die gesamte Ressource zur Änderung übergeben? Ich verwende PUTs nur zum Ändern von Ressourcen und übergebe nur die Felder, die aktualisiert werden sollen. Daher muss ich PATCH nicht verwenden
  2. Ressourcenpfade - Ich verwende GUIDs in meiner Anwendung. Infolgedessen werden sie weltweit einzigartig sein. Warum benötige ich den vollständigen Ressourcenpfad, einschließlich der übergeordneten Ressourcen, wenn ich nur eindeutig auf eine Unterressource selbst verweisen kann? Wie:
     
    / subresource /: subresourceId
     
    Wenn ich es "richtig" machen würde, würde der Versuch, auf die Subressource zu verweisen, einen vollständigen Pfad erfordern wie:
     
    / parentresource /: id / childresource /: childId / subresource /: subresourceId
     
    Ist alles notwendig ? Weil ich jetzt eine zusätzliche Fehlerbehandlung haben muss, wenn mein Pfad eine: subresourceId enthält, die nicht tatsächlich einer bestimmten: childId gehört, und ebenso eine: childId, die keiner übergeordneten: id gehört. Meine Serverseite kümmert sich um die Ressourcenautorisierung. Kann ich nicht einfach auf die Ressource selbst verweisen und nicht auf den vollständigen Pfad?

  3. Die Rückantwort. Nehmen wir zum Beispiel an, meine Datenstruktur ist ein hierarchischer Baum ohne praktische Grenzen für die Baumtiefe. Ressourcen liegen hierarchisch auf verschiedenen Ebenen im Baum.

    • Das GET ist offensichtlich. Wenn ich diesen gesamten Baum erhalte, erwarte ich den gesamten Baum als Antwort mit Ressourcen, die in Ressourcen enthalten sind.
    • Wenn ich POST, um eine neue Ressource zu erstellen, PUT zu aktualisieren oder DELETE, um sie zu entfernen, möchte ich die Deltas im Baum sehen, anstatt nur die Ressource zu sehen, die ich erstellt / aktualisiert / gelöscht habe. Ich möchte nicht nach jedem POST, PUT oder DELETE erneut das GET des übergeordneten Baums aufrufen müssen, insbesondere wenn es kleine Änderungen am Baum gibt und ich nur die Deltas sehen möchte.

Hoffentlich sind meine Fragen klar.

Wenn Sie eine REST-Implementierung sehen würden, wie ich sie beschrieben habe, würden Sie sie betrachten und mir Ihre Bedenken hinsichtlich der Softwareentwicklung mitteilen? Wenn ja, was wären sie?

Michael Plautz
quelle
4
Seltsamerweise betrifft keines Ihrer Anliegen die architektonischen Einschränkungen von REST. Ihre Fragen sind streng an die WEB- und HTTP-Semantik gebunden. Sieht so aus, als ob Sie mit diesen letzten nicht vertraut sind. Was lässt mich denken: Warum überhaupt ein Webinterface erstellen? Auf der anderen Seite gibt es keinen "richtigen Weg" oder "falschen Weg". Nur Implementierungen, die Ihren Anforderungen am besten entsprechen. Was Sie als "richtig" bezeichnen, ist nur "webfreundlicher" und "entwicklerfreundlicher". Je "webfreundlicher" ist, desto mehr Vorteile bietet die WWW-Architektur. Das wäre der Punkt, um Web "Dinge" zu tun.
Laiv
Das Risiko einer Abweichung von REST besteht darin, dass jemand, der eine RESTful-Schnittstelle erwartet, durch das Verhalten Ihrer Webanwendung verwirrt wird. Was Sie vorschlagen, scheint jedoch nicht einmal so stark abzuweichen, was zu völliger Verwirrung führt. Daher würde ich argumentieren, dass das, was Sie vorschlagen, vollkommen in Ordnung ist. Fügen Sie einfach die Dokumentation hinzu!
Neil
@Laiv, Sie stellen eine gute Frage - warum überhaupt ein Webinterface erstellen? Weil ich mit keiner anderen Architektur vertraut bin, die ein clientseitiges Rendering-Framework wie React oder Vue unterstützt, als mit einer Webschnittstelle, die die benötigten Daten sendet. Aus Gründen der Flexibilität und Leistung möchte ich kein serverseitiges Rendering. Ich weiß auch, dass GraphQL eine Option ist, aber ich bin damit schrecklich unbekannt.
Michael Plautz
GraphQL ist kein Architekturstil, sondern nur eine weitere Abfragesprache mit viel Code für die Kesselplatte unter der Haube. Sie können das WWW nutzen, ohne REST zu machen. Es gibt noch WebSockets oder ProtocolBuffers. Wenn es sich bei Ihrer Anwendung nicht um eine rein repräsentative Statistikübertragung handelt, dient REST Ihnen nicht.
Laiv

Antworten:

3

Die allgemeine Antwort lautet, dass Ihre Ideen möglicherweise auf technischer Ebene funktionieren, dies bedeutet jedoch nicht, dass sie den standardisierten Konventionen von REST entsprechen.


  1. PUT / PATCH - Wozu wird die gesamte Ressource zur Änderung übergeben? Ich verwende PUTs nur zum Ändern von Ressourcen und übergebe nur die Felder, die aktualisiert werden sollen. Daher muss ich PATCH nicht verwenden

Ihre Idee funktioniert auf technischer Ebene, aber es ist einfach nicht so, wie REST beschrieben wurde. Beachten Sie, dass jede Diskussion über Arbeitscode (dh keine Kompilierungs- oder Laufzeitfehler) immer eine Frage der Konvention sein wird , nicht unbedingt der klaren technischen Überlegenheit.


  1. Ressourcenpfade - Ich verwende GUIDs in meiner Anwendung. Infolgedessen werden sie weltweit einzigartig sein. Warum benötige ich den vollständigen Ressourcenpfad, einschließlich der übergeordneten Ressourcen, wenn ich nur eindeutig auf eine Unterressource selbst verweisen kann?

Es gibt viele Nuancen, wie wir "untergeordnete / übergeordnete" Entitäten definieren. Am häufigsten bezieht es sich auf eine Eins-zu-Viele-Beziehung (Eltern-zu-Kinder).

Ich vermute jedoch, dass für REST ein Teil dessen, was ein Kind zu einem Kind macht, darin besteht, dass erwartet wird, dass es nur über die Eltern darauf zugreifen kann und dass es keine eigene global eindeutige (und extern bekannte) Kennung trägt.
Ich vermute, dass dies der gleichen Philosophie folgt (aber nicht unbedingt aus dem gleichen Grund) wie die der Aggregate (und ihrer Wurzeln) in der domänengetriebenen Entwicklung .

Ein DDD-Aggregat ist ein Cluster von Domänenobjekten, die als einzelne Einheit behandelt werden können. Bei einem Aggregat ist eines seiner Komponentenobjekte die Aggregatwurzel. Verweise von außerhalb des Aggregats sollten nur an das Aggregatstammverzeichnis gesendet werden .

In Ihrem Fall fungiert das, was Sie als "übergeordnetes Element" bezeichnen, als aggregierte Wurzel. Die zentrale Anlaufstelle (wenn Sie so wollen) für externe Anrufer.

Vielleicht möchten Sie daraus schließen, dass Ihr Kind tatsächlich ein anderes Aggregat ist. Das mag der Fall sein, aber ich möchte mit dieser Entscheidung eine Warnung herausgeben. Sie sollten Ihre Architektur nicht auf den bestimmten Feldtyp stützen. Sie können nicht wissen, ob Sie weiterhin global eindeutige IDs für alle Ihre Entitäten verwenden. Sollte sich dies aus irgendeinem Grund jemals ändern, werden Sie die Lebensfähigkeit Ihrer REST-Architektur beeinträchtigen. Dies kann dazu führen, dass das Kind nicht mehr eindeutig identifizierbar ist und daher über seine Eltern referenziert werden muss.


  1. Wenn ich POST, um eine neue Ressource zu erstellen, PUT zu aktualisieren oder DELETE, um sie zu entfernen, möchte ich die Deltas im Baum sehen, anstatt nur die Ressource zu sehen, die ich erstellt / aktualisiert / gelöscht habe.

Sie verletzen die Reihenfolge der Operationen des Entwurfs. Eine REST-API soll speziell verbraucherunabhängig sein. Die API sollte nicht gemäß den Spezifikationen eines ihrer Verbraucher erstellt werden.

Wenn Sie sagen "Ich möchte die Deltas im Baum sehen", sagen Sie wirklich: "Die konsumierende Anwendung muss nur die Deltas im Baum sehen". Für die REST-API ist das aber nicht ganz wichtig. Es bietet lediglich einen standardisierten Ansatz.

Es liegt in der Natur standardisierter Ansätze, häufig hochgradig anpassbare Tools zu fehlen und stattdessen die am häufigsten verwendeten Tools zu bevorzugen .


Kannst du vom Weg abweichen? Nun, es wird auf technischer Ebene funktionieren. Aber es wird kein reiner REST mehr sein. Dies ist sehr kontextabhängig und Sie müssen die Optionen abwägen.

  • Wenn Sie eine API erstellen, die voraussichtlich viele unterschiedliche Kunden ansprechen wird, empfehle ich, sich so gut wie möglich an REST zu halten.
  • Wenn Sie eine API erstellen, die nur einen Consumer hat, der ebenfalls von Ihnen entwickelt wurde; dann besteht keine wirkliche Notwendigkeit, sich an reines REST zu halten.
  • Wenn Sie vom Pfad abweichen, müssen Sie dokumentieren, wie Sie sich verirrt haben, damit andere Entwickler noch einen Sinn daraus ziehen können. Wenn Sie sich an reines REST halten, müssen Sie die Dokumentation nicht schreiben, und die anderen Entwickler müssen keine Zeit und Mühe aufwenden, um Ihren benutzerdefinierten Ansatz herauszufinden.
Flater
quelle
9

Was sind die Bedenken der Softwareentwicklung, wenn meine REST-API nicht "richtig" implementiert wird?

Meiner Meinung nach ist das Wichtigste die Möglichkeit, Arbeiten an generische Komponenten zu delegieren, die nur die Standards kennen, nicht Ihren spezifischen Geschäftsfall.

Wenn Sie sich an die einheitliche Benutzeroberfläche halten, ist es für andere Parteien einfacher, Komponenten zu erstellen, die sich gut in Ihre integrieren lassen.

Hier schreibt Fielding 2008

REST ist für langlebige netzwerkbasierte Anwendungen gedacht, die mehrere Organisationen umfassen.

Wir haben es unter anderem geschafft, "langlebig" zu sein, indem wir einen klaren Standard haben, der die Semantik der Nachrichten beschreibt, die wir weitergeben. Wenn sich alle einig sind, was PUTbedeutet, können Verbraucher und Hersteller dieser Anfragen unabhängig voneinander entwickelt werden, und Zwischenkomponenten zwischen beiden können sinnvolle Maßnahmen ergreifen, ohne die Details der Nachricht in Ihrem spezifischen Kontext kennen zu müssen.

PUT / PATCH - Wozu wird die gesamte Ressource zur Änderung übergeben? Ich verwende PUTs nur zum Ändern von Ressourcen und übergebe nur die Felder, die aktualisiert werden sollen. Daher muss ich PATCH nicht verwenden

Was bringt es PUTdann, wenn man es benutzt ?

PURPLE /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898 HTTP/1.1
...

Dies ist eine absolut gültige Anforderungszeile für eine HTTP-Nachricht, und die Änderung der Semantik wird niemanden verwirren.

Gleichwertig

POST /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898 HTTP/1.1
...

Welches hat so ziemlich uneingeschränkte Semantik; Der Server kann die Verarbeitung dieser Anforderung nach Belieben implementieren.

Angenommen, ich spreche von einer JSON-REST-API

Ihre Zurückhaltung bei der Verwendung von PATCH ist in diesem Fall besonders merkwürdig, da bereits Standards für JSON Patch und JSON Merge Patch vorgeschlagen wurden. Die Standardisierung eines Patch-Dokumentformats ist möglicherweise bereits für Sie erledigt.

Eine andere gültige Alternative wäre, das Patch-Dokument als separate Ressource zu behandeln. Semantisch könnte man sich so etwas vorstellen

PUT /014d8c83-604d-4cf0-a6ba-e1f7ef8c4898/patches/5c42c414-03c0-4ac5-af14-2b1165ac98b3 HTTP/1.1

Dadurch erhalten Sie eine ehrliche, einheitliche Nachrichtensemantik, die die standardisierte Cache-Ungültigmachung opfert .

In einer Codeüberprüfungseinstellung würde ich eine vorgeschlagene Änderung ablehnen, mit der versucht wurde, die Semantik von PUT neu zu definieren.

HTTP versucht nicht, die Sicherheit der Ergebnisse eines GET zu gewährleisten. Was es tut, erfordert, dass die Semantik der Operation sicher ist, und daher ist es ein Fehler der Implementierung, nicht der Schnittstelle oder des Benutzers dieser Schnittstelle, wenn etwas passiert, das zu einem Verlust von Eigentum führt (Geld, BTW, wird im Sinne dieser Definition als Eigentum angesehen). - Fielding, 2002 .

Die gleiche Überlegung gilt auch für PUT; Wenn Ihre Implementierung von PUT von der standardisierten Semantik abweicht, ist Ihre Implementierung für den daraus resultierenden Schaden verantwortlich.

Ressourcenpfade - Ich verwende GUIDs in meiner Anwendung. Infolgedessen werden sie weltweit einzigartig sein. Warum benötige ich den vollständigen Ressourcenpfad, einschließlich der übergeordneten Ressourcen, wenn ich nur eindeutig auf eine Unterressource selbst verweisen kann?

Das ist vollkommen in Ordnung. REST ist es egal, welche Schreibweisen Sie für Ihre Ressourcenkennungen verwenden.

Betrachten Sie die Google-Landingpage. Müssen Sie die Schreibweise des URI für das heutige Doodle beachten? oder wo das Suchformular eingereicht wird? Nein natürlich nicht. Die HTML-Nutzdaten enthalten URIs, und die Clients verwenden nur die bereitgestellten Bezeichner auf standardmäßige Weise, ohne diese Bezeichner analysieren zu müssen.

In einen URI codierte Informationen liegen im Ermessen des Ursprungsservers für seine eigenen Zwecke.

Ich würde davon abraten, einen solchen URI als Einstiegspunkt für Ihre API zu verwenden. https://www.example.org/df8f5f87-15ff-4212-8fb8-4fbca2c7efcfist ein bisschen umständlich für den menschlichen Verzehr. Ein von Menschen lesbarer URI, der zur UUID-Ressource umleitet, ist in Ordnung. Ein von Menschen lesbarer URI, der den Inhalt der UUID-Ressource zurückgibt, ist besser.

Wenn ich POST, um eine neue Ressource zu erstellen, PUT zu aktualisieren oder DELETE, um sie zu entfernen, möchte ich die Deltas im Baum sehen, anstatt nur die Ressource zu sehen, die ich erstellt / aktualisiert / gelöscht habe

Das ist in Ordnung - schauen Sie sich noch einmal den Standard an .

Die in einer 200-Antwort gesendete Nutzlast hängt von der Anforderungsmethode ab. Für die in dieser Spezifikation definierten Methoden kann die beabsichtigte Bedeutung der Nutzlast wie folgt zusammengefasst werden

POST eine Darstellung des Status oder der Ergebnisse der Aktion

PUT, DELETE eine Darstellung des Status der Aktion

In einigen Fällen ist es sinnvoll, die neue Darstellung der Ressource als Teil der Antwort zu senden (um dem Client die Latenz einer GET-Anforderung / Antwort zu ersparen).

VoiceOfUnreason
quelle
2
What's the point in using PUT then?-- Tatsächlich. Ein POST würde einwandfrei funktionieren.
Robert Harvey
@ RobertHarvey Oder warum nicht verwenden PATCH? Die Definition passt besser.
Solomon Ucko
@SolomonUcko: Alles zu einem POST zu machen, hat den Vorteil der Einfachheit.
Robert Harvey
3

REST ist ein Architekturstil zum zustandslosen Manipulieren von Ressourcen (wobei zustandslos bedeutet, dass jede Manipulation für sich steht und nicht von anderen Manipulationen abhängt, die möglicherweise stattgefunden haben).

Die Verwendung der Verben PUT / PATCH / POST / GET / DELETE beruht auf der allgemeinen Verwendung des HTTP-Protokolls, das zum Übertragen und Bearbeiten der Ressourcen verwendet wird. Die Bedeutung dieser Verben wird durch einen Internetstandard ( RFC7231 ) definiert.

Vor diesem Hintergrund ist Ihre Verwendung von PUT nicht Standard und kann andere Entwickler verwirren, die Ihre API verwenden möchten.

In Bezug auf die Ressourcenpfade kümmert sich kaum jemand um die genaue Schreibweise (auch wenn eine untergeordnete Ressource als untergeordnet aufgeführt ist). Was die Leute interessiert, ist, dass jede Ressource eindeutig identifiziert wird. Das System /parent/:pid/child/:cidwird häufig verwendet, wenn die untergeordneten IDs nur innerhalb eines übergeordneten Elements eindeutig sind, um weiterhin einen global eindeutigen Pfad zur Ressource zu haben.

Bart van Ingen Schenau
quelle
2
Neben Barts Antwort. Denken Sie daran, dass der HTTP-Client der einzige ist, der den URI lesen und verstehen muss , und dass die Hierarchie der Ressourcen keine Rolle spielt. Ob die URI Hierarchie, Beziehung oder irgendeine andere Art von Beziehung ausdrückt, ist nur für das arme Lebewesen von Bedeutung, das sie lesen muss
Laiv
1
  1. PUT / PATCH - Wozu wird die gesamte Ressource zur Änderung übergeben? Ich verwende PUTs nur zum Ändern von Ressourcen und übergebe nur die Felder, die aktualisiert werden sollen. Daher muss ich PATCH nicht verwenden

Mir scheint, Sie sollten PATCH hier wirklich als Semantik verwenden.

  • PUT erklärt den genauen gewünschten Zustand. Dies ist nützlich, wenn sich eine Ressource häufig ändert und die gewünschte Änderung in einem bestimmten Kontext erfolgen muss.

  • PATCH erklärt ein gewünschtes Delta zu allem, was da ist. Dies ist nützlich, wenn sich die Änderung nicht um den Kontext kümmert oder der relevante Kontext viel kleiner als die gesamte Ressource ist.

Ein Bild ist ein gutes Beispiel, wenn es sinnvoll wäre, das Ganze einfach hochzuladen. Es ist wichtig, dass die gesamte Ressource kommuniziert wird, um einen relevanten Kontext sicherzustellen.

Umgekehrt ist es möglicherweise sinnvoller, die Anzahl der Wiedergaben in einer Musikwiedergabeliste zu aktualisieren, um ein Delta zu sein. Nicht weil es sich um eine kleine Änderung handelt, sondern weil das erneute Senden der gesamten Liste Änderungen am Inhalt der Liste leicht rückgängig machen kann.

  1. Ressourcenpfade - Ich verwende GUIDs in meiner Anwendung. Infolgedessen werden sie weltweit einzigartig sein. Warum benötige ich den vollständigen Ressourcenpfad, einschließlich der übergeordneten Ressourcen, wenn ich nur eindeutig auf eine Unterressource selbst verweisen kann?

... schnipsen ...

Ist das alles nötig? Weil ich jetzt eine zusätzliche Fehlerbehandlung haben muss, wenn mein Pfad eine: subresourceId enthält, die nicht tatsächlich einer bestimmten: childId gehört, und ebenso eine: childId, die keiner übergeordneten: id gehört. Meine Serverseite kümmert sich um die Ressourcenautorisierung. Kann ich nicht einfach auf die Ressource selbst verweisen und nicht auf den vollständigen Pfad?

Nein, Sie müssen wirklich keine Pfade benutzen - niemals. Angenommen, Sie behalten alle Ihre Dateien auf dem Desktop? Nein? Warum nicht?

Wahrscheinlich etwas damit zu tun, dass es einfacher zu sehen ist, dasselbe Problem hier. Eine GUID sagt Ihnen nicht, was Sie tun, während Sie dies einrichten, debuggen oder ausführen.

Wie fühlt es sich an, dieses System zu unterstützen? oder damit interagieren? Wenn Sie nicht darüber nachgedacht haben, nehmen Sie sich etwas Zeit und überlegen Sie, welche Arbeit Sie auf der ganzen Linie erledigen.

Das Vorhandensein expliziter Pfadinformationen dient zur Validierung der Anforderung. Es hilft auch, Informationen so weit zu differenzieren, dass Support- und nachgeschaltete Systementwickler sich diesen URLs nähern und sie verwenden können.

  1. Die Rückantwort. Nehmen wir zum Beispiel an, meine Datenstruktur ist ein hierarchischer Baum ohne praktische Grenzen für die Baumtiefe. Ressourcen liegen hierarchisch auf verschiedenen Ebenen im Baum.

    ein. Das GET ist offensichtlich. Wenn ich diesen gesamten Baum erhalte, erwarte ich den gesamten Baum als Antwort mit Ressourcen, die in Ressourcen enthalten sind.

Möglicherweise möchten Sie eine Tiefenbegrenzung festlegen, damit ein kluges Kind nicht einfach für jede erdenkliche Operation die Wurzel Ihrer Website erhält.

b. Wenn ich POST, um eine neue Ressource zu erstellen, PUT zu aktualisieren oder DELETE, um sie zu entfernen, möchte ich die Deltas im Baum sehen, anstatt nur die Ressource zu sehen, die ich erstellt / aktualisiert / gelöscht habe. Ich möchte nicht nach jedem POST, PUT oder DELETE erneut das GET des übergeordneten Baums aufrufen müssen, insbesondere wenn es kleine Änderungen am Baum gibt und ich nur die Deltas sehen möchte.

Wenn sich das Aktualisieren einer Ressource auf nicht triviale und vorhersehbare Weise auf das übergeordnete Element auswirkt, haben Sie andere Probleme ... Sie müssen sich wirklich das Statusmodell ansehen und herausfinden, warum die Informationen herumspringen.

Wenn Sie nur eine detaillierte Liste der Deltas zurückgeben möchten, warum nicht? Warum nicht mehrere Ausgabeansichten unterstützen, die durch verschiedene Parameter umgeschaltet werden? Jenkins gibt seine API-Antworten in einer Auswahl von XML oder JSON zurück und ermöglicht es Ihnen, mehrere Filter zum Extrahieren des gewünschten Unterbaums anzugeben.

Verwenden Sie es selbst

Um ehrlich zu sein, treten Sie zurück von dem, was Sie machen, und versuchen Sie, es zu unterstützen, oder erstellen Sie eine andere Anwendung, um es zu verwenden (nicht eine Ihrer bereits vorhandenen Anwendungen). Machen Sie etwas Ähnliches für APIs von Drittanbietern, damit Sie einen kleinen Hintergrundkontext haben.

Immer wenn Sie etwas tun müssen, das die Supportanforderung nicht direkt löst oder für die Clientanwendung direkt erforderlich ist, ist die API nicht ideal, und Sie wissen, warum sie nicht ideal ist, was sogar noch besser ist, weil Sie es können Beheben Sie es oder machen Sie nicht den gleichen Fehler.

Wenn beispielsweise Anfragen an eine bestimmte URL ständig fehlschlagen, wie viel Aufwand müssen Sie investieren, um festzustellen, was fehlschlägt und warum? Welche Schritte haben Sie unternommen, hätten Sie einen dieser Schritte vermeiden können, indem Sie einen besseren URI, eine bessere Protokollierung, eine bessere Überwachung usw. hatten?

Wenn Sie einen neuen Client schreiben, wie oft müssen Sie auf die Dokumentation oder den Quellcode der API verweisen? Was könnten Sie tun, um diesen Bedarf zu reduzieren? Was können Sie tun, um Ihre eigenen Erwartungen nicht mehr zu verletzen? Was können Sie tun, um das Problem mit Clientanwendungen zu vereinfachen, ohne den Server zu einem Albtraum zu machen?

Richtiger Weg

Ehrlich gesagt ist der richtige Weg umständlich. REST ist eine Reihe von Methoden, die unter verschiedenen Umständen für eine Reihe von Problemen funktionieren. Wenn Ihr Problem nicht passt, machen Sie es bitte nicht passend, aber behaupten Sie auch nicht, diese Praktiken anzuwenden.

Kain0_0
quelle
-1

Die meisten Funktionen von REST apis sind aus einem bestimmten Grund vorhanden, aber möglicherweise nicht aus einem für Sie relevanten Grund. Die Angabe der gesamten Ressource, wie beispielsweise in PUT, ist relevant, wenn Sie Idempotenz benötigen, andernfalls nicht. (Obwohl ich denke, dass es für Benutzer / Kollegen / was auch immer besser wäre, die Tatsache zu bewerben, dass Ihr Endpunkt nicht idempotent ist, indem Sie stattdessen POST oder PATCH verwenden.)

Für den Weg habe ich noch nie gehört, dass es um Ruhe geht. /root/345dd4dc-e175-455f-b545-85b1b1ce3e82ist so viel Teil eines Baumes wie /foo/bar/baz. Vielleicht etwas weniger benutzerfreundlich, aber nicht weniger ruhig, soweit ich sehen kann.

Wenn Sie detailliertere Überlegungen dazu wünschen, warum REST so konzipiert wurde, wie es ist, sollten Sie die Originalarbeit lesen: https://www.ics.uci.edu/~fielding/pubs/dissertation/fielding_dissertation.pdf

Wenn Sie lesen, werden Sie vielleicht feststellen, dass es ganz anders ist, als REST heute in Konversationen dargestellt oder in APIs verwendet wird. Offensichtlich haben viele andere Menschen einen guten oder schlechten Grund gefunden, davon abzuweichen.

Mir gefällt besonders dieses Zitat, das Sie vielleicht relevant finden:

HTTP ist nicht als Transportprotokoll konzipiert. Es handelt sich um ein Übertragungsprotokoll, bei dem die Nachrichten die Semantik der Webarchitektur widerspiegeln, indem sie Aktionen für Ressourcen ausführen, indem Darstellungen dieser Ressourcen übertragen und bearbeitet werden. Mit dieser sehr einfachen Schnittstelle ist es möglich, einen breiten Funktionsumfang zu erreichen. Die Einhaltung der Schnittstelle ist jedoch erforderlich, damit die HTTP-Semantik für Vermittler sichtbar bleibt. Aus diesem Grund durchläuft HTTP Firewalls. Abgesehen von WebDAV [60] haben die meisten der kürzlich vorgeschlagenen Erweiterungen von HTTP lediglich HTTP verwendet, um andere Anwendungsprotokolle durch eine Firewall zu verschieben, was eine grundlegend fehlgeleitete Idee ist. Es macht nicht nur den Zweck einer Firewall zunichte, Auf lange Sicht funktioniert dies jedoch nicht, da Firewall-Anbieter lediglich eine zusätzliche Protokollfilterung durchführen müssen. Es ist daher nicht sinnvoll, diese Erweiterungen zusätzlich zu HTTP durchzuführen, da HTTP in dieser Situation nur das Hinzufügen von Overhead aus einer Legacy-Syntax ermöglicht. Eine echte HTTP-Anwendung ordnet die Aktionen des Protokollbenutzers etwas zu, das mithilfe der HTTP-Semantik ausgedrückt werden kann, und erstellt so eine netzwerkbasierte API für Dienste, die von Agenten und Vermittlern ohne Kenntnis der Anwendung verstanden werden können.

Monozelle
quelle
2
"Obwohl ich denke, dass es für Benutzer / Kollegen / was auch immer besser wäre, die Tatsache zu bewerben, dass Ihr Endpunkt nicht idempotent ist, indem Sie stattdessen POST oder PATCH verwenden." - Dies ist keine Frage der Freundlichkeit. Die HTTP-Methoden haben eine genau definierte Semantik, und die gesamte World Wide Web-Infrastruktur hängt von dieser Semantik ab. Beispielsweise können Proxys PUTAnforderungen mehrmals wiederholen , ohne dass Sie es wissen, und sie dürfen dies tun, da die HTTP-Spezifikation angibt, dass dies PUTidempotent ist . Wenn Ihre PUTs nicht idempotent sind, wird dies Ihren Dienst unterbrechen .
Jörg W Mittag
2
Eine Zeit lang waren "Webbeschleuniger" der letzte Schrei, und tatsächlich feiern sie ein Comeback für mobile Geräte. Diese Beschleuniger haben Ressourcen vorab abgerufen und zwischengespeichert, und das durften sie, weil die HTTP-Spezifikation dies garantiert GETund HEADrein und frei von Nebenwirkungen ist. Einige Leute haben Daten verloren, weil sie schlecht gestaltete Webanwendungen verwendeten, bei denen das Löschen von Inhalten mit einer GETAnfrage erfolgte und der Webbeschleuniger glücklich GETAnfragen an alle URIs sendete , die er finden konnte.
Jörg W Mittag
Sie haben natürlich recht. Ich kann mich einfach nicht mehr für ein richtig funktionierendes Web begeistern. Es fühlt sich für mich wie ein verlorener Kampf an, aber vielleicht befinden Sie sich in einer schöneren Umgebung, in der solche Dinge tatsächlich funktionieren. Wo ich bin http ist nur ein Transport mit dem Zusatz, dass es von einem Browser anstelle von Netcat debuggbar ist, und das ist alles.
Monocell