Quando utilizzare le risorse nidificate in un'API RESTful


16

Ho due risorse: utenti e collegamenti.

Agli utenti possono essere associati diversi collegamenti. Ho progettato la mia API RESTful in modo che tu possa raggiungere i collegamenti associati a un utente al seguente URI:

/users/:id/links

Tuttavia, ho sempre bisogno di avere un URI solo per i collegamenti, a volte potrei volere tutti i collegamenti, indipendentemente dall'utente.

Per questo ho:

/links

Suona bene? Hai due URI per i link?

Mi chiedo se dovrei invece raggiungere i collegamenti per un utente con un URI come:

/links/user/:id o /links/?user=:id

In questo modo, ho solo una risorsa per i collegamenti.


3
hmm .. Questo sembra più elegante:/links/user/:id
theMarceloR

7
@theMarceloR: Questo è l'unico esempio dei tre che non trovo particolarmente chiaro. La risorsa è per un collegamento o un utente? L'URI è molto meno ambiguo utilizzando il metodo della risorsa nidificata ( /users/:id/links) o il metodo della stringa di query ( /links/?user=:id) poiché in realtà è una query./links/user/:idpotrebbe sembrare bello e / o essere più facile da instradare in alcuni framework ma in realtà è abbastanza confuso.
Aaronaught,

Risposte:


16

No, non c'è nulla di sbagliato nell'avere più risorse per la stessa "cosa", in questo caso elenchi di collegamenti.

Di recente abbiamo avuto problemi con lo stesso problema. La nostra decisione è stata quella di disporre di tutte le risorse in cui non esiste una proprietà rigorosa per non essere nidificati. In altre parole, i collegamenti sarebbero modellati sotto

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

Quindi, i filtri sulla raccolta di collegamenti vengono espressi come parametri di query. Quindi, per ottenere i collegamenti di un determinato utente, dovrai utilizzare:

/links?user=/users/:userid

Ciò consente anche una più semplice composizione dei filtri:

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

Ed è facile da capire concettualmente: hai una collezione di oggetti e aggiungi filtri.

Detto questo, non c'è niente di più "RESTOSO" in questo approccio di qualsiasi altro schema di denominazione URI. È solo una convenzione che abbiamo trovato leggibile e facile da comprendere per gli sviluppatori. A REST non importa cosa metti nei tuoi identificatori di risorse.


1
"Tutte le risorse in cui non esiste una proprietà rigorosa da non annidare" sembrano una buona regola da avere. Grazie mille.
Oliver Joseph Ash,

5
Direi che ci sia qualcosa di sbagliato con avere più risorse per la stessa entità fisica, ma non è in realtà che cosa si tratta. Ogni singolo collegamento ha un URL canonico (links /: id), mentre ciascuna delle risorse sopra è in realtà una singola risorsa (/ links) con i filtri applicati. Inoltre, sono stroncato dalla ?user=users/:useridstringa della query; cosa c'è di sbagliato in solo ?userid=:userid?
Aaronaught,

2
@Aaronaught: la ragione per attenersi agli uri invece che agli ID nudi è che i client possano trattare equamente tutti gli identificatori di risorse, ovvero un client deve solo sapere che 'questo utente è identificato da "/*******"; dove *sono opachi. ma lo stesso identificatore può sempre essere usato per fare riferimento a quella risorsa (come in, con collegamenti), per recuperare la versione più recente di quella risorsa e così via. il contenuto di quell'URI è compreso solo dal server di origine. Questo significa anche che se gli identificatori devono cambiare, diciamo /realm/:businessid/users/:id, il client non cambia affatto.
SingleNegationElimination

@TokenMacGuy: Mi dispiace, non capisco nessuna parte del tuo commento. Qual è la differenza pratica tra /users/:userid/linkse /links?userid=:userid? In entrambi i casi gli identificatori non cambiano, recuperano la versione corrente di quella risorsa e il client li tratta allo stesso modo. Non esiste un URL canonico per questo perché non è una risorsa, è una query, quindi questi sono solo due diversi tipi di sintassi della query. Inoltre non sono chiaro su come il cliente non avrebbe bisogno di cambiare se cambia la struttura dell'URL; questo è considerato un cambiamento di rottura in REST a meno che non sia presente un 301.
Aaronaught,

1
@Aaronaught: potrei aver frainteso la tua preoccupazione. Supponendo che /linkssupporti un'interfaccia di query, /links?user=/users/123consenta un approccio black-box agli identificatori di risorse nei client che /links?userid=123non lo fanno. quest'ultimo richiede al cliente di capire cos'è un ID utente e come ottenerlo, presumibilmente dalla risorsa da cui ha ottenuto /users/123o /links/456/user. Il primo significa che il client può usare l'uri non modificato; supponendo che /links/.../userdia una risposta ipermediale (diciamo, con le Location:intestazioni).
SingleNegationElimination

1

Quindi la mia preoccupazione è: / users /: userid / links restituisce "links", MA se user_id non viene identificato, questo dovrebbe restituire un 404.

tuttavia

/ links? userid =: userid potrebbe potenzialmente restituire un elenco vuoto (essenzialmente un 200) che in realtà è probabilmente un bug. E abbastanza possibile.

Sebbene entrambi funzionino, l'annidamento ti offre funzionalità aggiuntive su cui puoi attingere in seguito.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.