Ich versuche, mich mit dem besten Weg zu befassen, um Konzepte in einer REST-basierten API anzusprechen. Flache Ressourcen, die keine anderen Ressourcen enthalten, sind kein Problem. Wo ich in Schwierigkeiten gerate, sind die komplexen Ressourcen.
Zum Beispiel habe ich eine Ressource für ein Comic. ComicBook
hat alle Arten von Eigenschaften auf es mögen author
, issue number
, date
etc.
Ein Comic hat auch eine Liste von 1..n
Covers. Diese Abdeckungen sind komplexe Objekte. Sie enthalten viele Informationen über das Cover: den Künstler, ein Datum und sogar ein Basis-64-codiertes Bild des Covers.
Für eine GET
auf ComicBook
konnte ich einfach den Comic zurückzukehren, und alle Abdeckungen ihre base64'ed Bilder einschließlich. Das ist wahrscheinlich keine große Sache, um einen einzigen Comic zu bekommen. Angenommen, ich erstelle eine Client-App, die alle Comics im System in einer Tabelle auflisten möchte.
Die Tabelle enthält einige Eigenschaften aus der ComicBook
Ressource, aber wir werden sicherlich nicht alle Cover in der Tabelle anzeigen wollen. Die Rückgabe von 1000 Comics mit jeweils mehreren Deckblättern würde zu einer lächerlich großen Datenmenge führen, die in diesem Fall für den Endbenutzer nicht erforderlich ist.
Mein Instinkt ist es, Cover
eine Ressource zu erstellen und ComicBook
Cover zu enthalten. Also jetzt Cover
ist eine URI. GET
Bei Comic-Arbeiten funktioniert jetzt anstelle der riesigen Cover
Ressource eine URI für jedes Cover zurück, und Kunden können die Cover-Ressourcen nach Bedarf abrufen.
Jetzt habe ich ein Problem beim Erstellen neuer Comics. Sicherlich werde ich mindestens ein Cover erstellen wollen, wenn ich ein Comic
, tatsächlich ist das wahrscheinlich eine Geschäftsregel.
Jetzt stecke ich fest. Entweder zwinge ich die Kunden, Geschäftsregeln durchzusetzen, indem ich zuerst einen Cover
einsen, den URI für dieses Cover POST
erhalte und dann einen ComicBook
mit diesem URI in der Liste einfüge, oder mein POST
On ComicBook
nimmt eine anders aussehende Ressource auf, als sie ausspuckt aus. Die eingehenden Ressourcen für POST
und GET
sind tiefe Kopien, wobei die ausgehenden GET
s Verweise auf abhängige Ressourcen enthalten.
Die Cover
Ressource ist wahrscheinlich in jedem Fall erforderlich, da ich als Kunde sicher bin, dass ich in einigen Fällen die Richtung der Deckungen ansprechen möchte. Das Problem besteht also in einer allgemeinen Form, unabhängig von der Größe der abhängigen Ressource. Wie gehen Sie im Allgemeinen mit komplexen Ressourcen um, ohne den Client zu zwingen, nur zu "wissen", wie diese Ressourcen zusammengesetzt sind?
quelle
Antworten:
@ray, ausgezeichnete Diskussion
@jgerman, vergiss nicht, dass nur weil es REST ist, die Ressourcen von POST nicht in Stein gemeißelt werden müssen.
Was Sie in eine bestimmte Darstellung einer Ressource aufnehmen möchten, liegt bei Ihnen.
Ihr Fall der Cover, auf die separat verwiesen wird, ist lediglich die Erstellung einer übergeordneten Ressource (Comic), auf deren untergeordnete Ressourcen (Cover) verwiesen werden kann. Beispielsweise möchten Sie möglicherweise auch Verweise auf Autoren, Herausgeber, Charaktere oder Kategorien separat bereitstellen. Möglicherweise möchten Sie diese Ressourcen separat oder vor dem Comic erstellen, in dem sie als untergeordnete Ressourcen referenziert werden. Alternativ möchten Sie möglicherweise beim Erstellen der übergeordneten Ressource neue untergeordnete Ressourcen erstellen.
Ihr spezieller Fall der Cover ist insofern etwas komplexer, als für ein Cover wirklich ein Comic erforderlich ist und umgekehrt.
Wenn Sie jedoch eine E-Mail-Nachricht als Ressource und die Absenderadresse als untergeordnete Ressource betrachten, können Sie die Absenderadresse natürlich immer noch separat referenzieren. Holen Sie sich zum Beispiel alles von Adressen. Oder erstellen Sie eine neue Nachricht mit einer vorherigen Absenderadresse. Wenn E-Mail REST war, konnten Sie leicht erkennen, dass viele Ressourcen mit Querverweisen verfügbar sein könnten: / empfangene Nachrichten, / Entwurfsnachrichten, / von Adressen, / an Adressen, / Adressen, / Betreff, / Anhänge, / Ordner , / Tags, / Kategorien, / Labels, et al.
Dieses Tutorial bietet ein hervorragendes Beispiel für Ressourcen, auf die verwiesen wird. http://www.peej.co.uk/articles/restfully-delicious.html
Dies ist das häufigste Muster für automatisch generierte Daten. Beispielsweise veröffentlichen Sie keinen URI, keine ID oder kein Erstellungsdatum für die neue Ressource, da diese vom Server generiert werden. Sie können jedoch den URI, die ID oder das Erstellungsdatum abrufen, wenn Sie die neue Ressource zurückerhalten.
Ein Beispiel für Binärdaten. Beispielsweise möchten Sie Binärdaten als untergeordnete Ressourcen veröffentlichen. Wenn Sie die übergeordnete Ressource erhalten, können Sie diese untergeordneten Ressourcen als dieselben Binärdaten oder als URIs darstellen, die die Binärdaten darstellen.
Formulare und Parameter unterscheiden sich bereits von den HTML-Darstellungen der Ressourcen. Das Posten eines Binär- / Dateiparameters, der zu einer URL führt, ist kein Problem.
Wenn Sie das Formular für eine neue Ressource (/ comic-books / new) oder das Formular zum Bearbeiten einer Ressource (/ comic-books / 0 / edit) erhalten, fordern Sie eine formularspezifische Darstellung der Ressource an. Wenn Sie es mit dem Inhaltstyp "application / x-www-form-urlencoded" oder "multipart / form-data" in die Ressourcensammlung stellen, bitten Sie den Server, diese Typdarstellung zu speichern. Der Server kann mit der gespeicherten HTML-Darstellung oder was auch immer antworten.
Möglicherweise möchten Sie auch zulassen, dass eine HTML-, XML- oder JSON-Darstellung für Zwecke einer API oder ähnlichem in die Ressourcensammlung gestellt wird.
Es ist auch möglich, Ihre Ressourcen und Ihren Workflow so darzustellen, wie Sie es beschreiben, wobei nach dem Comic veröffentlichte Cover berücksichtigt werden, für Comics jedoch ein Cover erforderlich ist. Beispiel wie folgt.
GET / comic-books
=> 200 OK, Holen Sie sich alle Comics.
GET / comic-books / 0
=> 200 OK, Holen Sie sich das Comic-Buch (id: 0) mit den Covers (/ cover / 1, / cover / 2).
GET / comic-books / 0 / cover
=> 200 OK, Cover für Comic-Buch abrufen (id: 0).
GET / cover
=> 200 OK, Holen Sie sich alle Cover.
GET /
cover / 1 => 200 OK, Cover (id: 1) mit Comic (/ comic-books / 0) abrufen.
GET / comic-books / new
=> 200 OK, Formular zum Erstellen eines Comics abrufen (Formular: POST / Draft-Comic-Bücher).
POST / Draft-Comic-Bücher
Titel = foo
Autor = Boo
Verlag = Goo
veröffentlicht = 2011-01-01
=> 302 Gefunden, Ort: / Draft-Comic-Bücher / 3, Weiterleiten zum Entwurf eines Comics (ID: 3) mit Abdeckungen (binär).
GET / Draft-Comic-Bücher / 3
=> 200 OK, Holen Sie sich einen Comic-Entwurf (ID: 3) mit Umschlägen.
GET / Draft-Comic-Bücher / 3 / Cover
=> 200 OK, Cover für Draft-Comic-Buch (/ Draft-Comic-Buch / 3) abrufen.
GET / Draft-Comic-Bücher / 3 / Cover / New
=> 200 OK, Formular zum Erstellen eines Covers für Draft-Comic-Bücher (/ Draft-Comic-Buch / 3) abrufen (Formular: POST / Draft-Comic-Bücher / 3 / Abdeckungen).
POST / Draft-Comic-Bücher / 3 / Cover
cover_type =
Frontcover_data = (binär)
=> 302 Gefunden, Ort: / Draft-Comic-Bücher / 3 / Cover, Weiterleitung zum neuen Cover für Draft-Comic (/ Draft-Comic) -book / 3 / cover / 1).
GET / Draft-Comic-Bücher / 3 / Publish
=> 200 OK, Formular zum Veröffentlichen des Comic-Entwurfs (ID: 3) abrufen (Formular: POST / Published-Comic-Books).
POST / Published-Comic-Books
Titel = Foo-
Autor = Boo-
Publisher = Goo
Published = 2011-01-01
Cover_Type = Front
Cover_Data = (Binär)
=> 302 Gefunden, Ort: / Comic-Books / 3, Weiterleitung zum veröffentlichten Comic (id: 3) mit Abdeckungen.
quelle
Die Behandlung von Deckblättern als Ressourcen ist definitiv im Sinne von REST, insbesondere von HATEOAS. Ja, eine
GET
Anfrage anhttp://example.com/comic-books/1
würde Ihnen eine Darstellung von Buch 1 geben, mit Eigenschaften, einschließlich einer Reihe von URIs für Cover. So weit, ist es gut.Ihre Frage ist, wie Sie mit der Erstellung von Comics umgehen sollen. Wenn Ihre Geschäftsregel lautete, dass ein Buch 0 oder mehr Umschläge haben würde, haben Sie kein Problem:
Mit Coverless-Comic-Daten wird ein neues Comic-Buch erstellt und die vom Server generierte ID zurückgegeben (sagen wir, sie wird als 8 zurückgegeben). Jetzt können Sie Cover wie folgt hinzufügen:
mit der Abdeckung im Körper des Unternehmens.
Jetzt haben Sie eine gute Frage: Was passiert, wenn Ihre Geschäftsregel besagt, dass immer mindestens eine Deckung vorhanden sein muss? Hier sind einige Auswahlmöglichkeiten, von denen Sie die erste in Ihrer Frage identifiziert haben:
Erzwingen Sie zuerst die Erstellung eines Covers und machen Sie Cover nun im Wesentlichen zu einer nicht abhängigen Ressource, oder Sie platzieren das erste Cover im Entity-Body des POST, der das Comic-Buch erstellt. Dies bedeutet, wie Sie sagen, dass sich die Darstellung, die Sie POST erstellen möchten, von der Darstellung unterscheidet, die Sie erhalten.
Definieren Sie den Begriff einer primären oder anfänglichen oder bevorzugten oder anderweitig bezeichneten Deckung. Dies ist wahrscheinlich ein Modellierungs-Hack, und wenn Sie dies tun würden, wäre es so, als würden Sie Ihr Objektmodell (Ihr Konzept- oder Geschäftsmodell) optimieren, um es an eine Technologie anzupassen. Keine gute Idee.
Sie sollten diese beiden Optionen gegen das einfache Zulassen von Comics ohne Cover abwägen.
Welche der drei Entscheidungen sollten Sie treffen? Ich weiß nicht zu viel über Ihre Situation, aber beantworte die allgemeine Frage nach der 1 .. N-abhängigen Ressource. Ich würde sagen:
Wenn Sie für Ihre RESTful-Serviceschicht mit 0..N arbeiten können, ist das großartig. Möglicherweise kann eine Ebene zwischen Ihrer RESTful-SOA die weiteren geschäftlichen Einschränkungen bewältigen, wenn mindestens eine erforderlich ist. (Ich bin mir nicht sicher, wie das aussehen würde, aber es könnte sich lohnen, es zu erkunden. Endbenutzer sehen die SOA normalerweise sowieso nicht.)
Wenn Sie einfach eine 1..N-Einschränkung modellieren müssen, fragen Sie sich, ob Cover möglicherweise nur gemeinsam nutzbare Ressourcen sind, mit anderen Worten, sie können für andere Dinge als Comics vorhanden sein. Jetzt sind sie keine abhängigen Ressourcen mehr und Sie können sie zuerst erstellen und URIs in Ihrem POST angeben, die Comics erstellen.
Wenn Sie 1..N benötigen und Cover abhängig bleiben, entspannen Sie einfach Ihren Instinkt, um die Darstellungen in POST und GET gleich zu halten, oder machen Sie sie gleich.
Der letzte Punkt wird folgendermaßen erklärt:
Wenn Sie POSTEN, erlauben Sie vorhandene Uris, wenn Sie sie haben (aus anderen Büchern entlehnt), aber fügen Sie auch ein oder mehrere Anfangsbilder ein. Wenn Sie ein Buch erstellen und Ihre Entität kein erstes Titelbild hat, geben Sie eine Antwort 409 oder ähnlich zurück. Auf GET können Sie URIs zurückgeben.
Grundsätzlich erlauben Sie also, dass die POST- und GET-Darstellungen "gleich" sind, aber Sie entscheiden sich einfach dafür, das Titelbild weder auf GET noch auf POST zu "verwenden". Hoffe das macht Sinn.
quelle