Wann werden verschachtelte Ressourcen in einer RESTful-API verwendet?

16

Ich habe zwei Ressourcen: Benutzer und Links.

Benutzern können mehrere Links zugeordnet sein. Ich habe meine RESTful-API so gestaltet, dass Sie die einem Benutzer zugeordneten Links unter der folgenden URI erreichen können:

/users/:id/links

Ich muss jedoch immer eine URI für nur Links haben - manchmal möchte ich alle Links, unabhängig vom Benutzer.

Dafür habe ich:

/links

Hört sich das okay an? Haben Sie zwei URIs für Links?

Ich frage mich, ob ich stattdessen die Links für einen Benutzer mit einer URI wie folgt erreichen soll:

/links/user/:id oder /links/?user=:id

Auf diese Weise habe ich nur eine Ressource für Links.

Oliver Joseph Ash
quelle
3
hmm .. Dieser scheint eleganter:/links/user/:id
theMarceloR
7
@theMarceloR: Das ist das einzige Beispiel von den dreien, das ich nicht besonders klar finde. Ist die Ressource für einen Link oder einen Benutzer? Der URI ist bei Verwendung der verschachtelten Ressourcenmethode ( /users/:id/links) oder der Abfragezeichenfolgenmethode ( /links/?user=:id) weitaus weniger mehrdeutig, da es sich tatsächlich um eine Abfrage handelt. /links/user/:idsieht vielleicht gut aus und / oder ist in einigen Frameworks einfacher zu routen, ist aber tatsächlich ziemlich verwirrend.
Aaronaught

Antworten:

16

Nein, es ist nichts Falsches daran, mehrere Ressourcen für dasselbe "Ding" zu haben, in diesem Fall Listen von Links.

Wir hatten kürzlich mit dem gleichen Problem zu kämpfen. Unsere Entscheidung war, alle Ressourcen zu haben, bei denen es kein striktes Eigentum gibt, um nicht verschachtelt zu werden. Mit anderen Worten, die Links würden unter modelliert

/links -- all links
/links/:linkid -- a particular link

Filter in der Linksammlung werden dann als Abfrageparameter ausgedrückt. Um also die Links eines bestimmten Benutzers zu erhalten, würden Sie Folgendes verwenden:

/links?user=/users/:userid

Dies ermöglicht auch eine einfachere Zusammenstellung von Filtern:

/links?user=/users/10&since=2013-01-01

Und konzeptionell ist es einfach zu verstehen: Sie haben eine Sammlung von Elementen und fügen Filter hinzu.

Davon abgesehen ist an diesem Ansatz nichts "RESTvolleres" als jedes andere URI-Benennungsschema. Es ist nur eine Konvention, die wir für Menschen lesbar und für uns Entwickler leicht zu verstehen und zu akzeptieren fanden. REST kümmert sich nicht darum, was Sie in Ihre Ressourcen-IDs einfügen.

Seidenschwanz
quelle
1
"Alle Ressourcen, bei denen es keine strikte Eigentümerschaft gibt, um nicht verschachtelt zu werden", klingt nach einer guten Regel. Vielen Dank.
Oliver Joseph Ash
5
Ich würde sagen , dass es ist etwas nicht in Ordnung mehr Ressourcen für die gleiche physikalische Einheit mit zu haben, aber das ist eigentlich nicht , was das ist. Jeder einzelne Link hat eine kanonische URL (links /: id), wohingegen jede der oben genannten Ressourcen eine einzelne Ressource (/ links) mit angewendeten Filtern ist. Außerdem bin ich verrückt nach dem ?user=users/:useridin der Abfragezeichenfolge; was ist los mit gerade ?userid=:userid?
Aaronaught
2
@Aaronaught: Der Grund für das Festhalten an uri's anstelle von nackten IDs besteht darin, dass Clients alle Ressourcenkennungen gleich behandeln können. Das heißt, ein Client muss nur wissen, dass 'dieser Benutzer durch' identifiziert wird "/*******". wo die *undurchsichtig sind. Der gleiche Bezeichner kann jedoch immer verwendet werden, um auf diese Ressource zu verweisen (wie in, mit Links), um die aktuellste Version dieser Ressource abzurufen usw. Der Inhalt dieser URL wird nur vom Ursprungsserver verstanden. Dies bedeutet auch, dass sich /realm/:businessid/users/:idder Client nicht ändert , wenn sich beispielsweise die Bezeichner ändern müssen .
SingleNegationElimination
@TokenMacGuy: Entschuldigung, ich verstehe keinen Teil Ihres Kommentars. Was ist der praktische Unterschied zwischen /users/:userid/linksund /links?userid=:userid? In beiden Fällen ändern sich die Bezeichner nicht, sie rufen die aktuelle Version dieser Ressource ab und der Client behandelt sie auf dieselbe Weise. Es gibt keine kanonische URL dafür, da es sich nicht um eine Ressource, sondern um eine Abfrage handelt. Dies sind also nur zwei verschiedene Arten der Abfragesyntax. Mir ist auch nicht klar, wie sich der Client ändern müsste, wenn sich die URL-Struktur ändert. Dies wird als grundlegende Änderung bei REST angesehen, es sei denn, ein 301 ist vorhanden.
Aaronaught
1
@Aaronaught: Ich könnte Ihre Besorgnis missverstanden haben. Angenommen, es wird /linkseine Abfrageschnittstelle unterstützt, /links?user=/users/123die einen Black-Box-Ansatz für Ressourcen-IDs in Clients ermöglicht, bei dem /links?userid=123dies nicht der Fall ist. Letzteres setzt voraus, dass der Kunde versteht, was eine Benutzer-ID ist und wie er sie erhält, vermutlich aus der Ressource, aus der sie stammt, /users/123oder /links/456/user. Ersteres bedeutet, dass der Kunde die Uri unverändert verwenden kann. Angenommen, das /links/.../usergibt eine Hypermedia-Antwort (z. B. mit Location:Überschriften).
SingleNegationElimination
1

Mein Anliegen ist also: / users /: userid / links gibt "links" zurück, ABER wenn die user_id nicht identifiziert wird, sollte dies eine 404 zurückgeben.

jedoch

/ links? userid =: userid würde möglicherweise eine leere Liste (im Wesentlichen 200) zurückgeben, bei der es sich wahrscheinlich um einen Fehler handelt. Und durchaus möglich.

Obwohl beide funktionieren, bietet die Verschachtelung zusätzliche Funktionen, auf die Sie später zurückgreifen können.

Richard Browne
quelle