Qual è il limite dei livelli di risorse dell'API REST

3

Durante la progettazione di un'API REST, quanto dovrebbero essere profondi i livelli delle risorse?

Ad esempio; Se ho le seguenti tabelle del database:

  • Aziende: ID, nome
  • Dipendenti: ID, Nome, CompanyID
  • Attività: ID, Nome, ID dipendente

Esponendoli tramite un'API REST, potrebbe essere simile a questo (id è facoltativo):

  • Aziende: GET / api / companies / {id}
  • Dipendenti: GET / api / impiegati / {id}
  • Attività: GET / api / tasks / {id}

Diciamo che voglio recuperare tutti i dipendenti che lavorano in azienda 1. Potrei fare qualcosa del genere: GET / api / companies / 1 / employees, giusto?

L'esecuzione di un GET su / api / dipendenti sarebbe inutile, perché non si desidera restituire tutti i dipendenti memorizzati nel database. La risorsa / api / dipendenti deve essere utilizzata solo in questo caso per il recupero dei singoli dati relativi a un determinato dipendente?

Che cosa succede se voglio ottenere le attività associate a un dipendente? Dovrebbe essere l'URL:

GET / api / companies / 1 / employees / 123 / tasks

o

GET / api / employees / 123 / tasks.

Se non vuoi che i client abbiano accesso a determinate risorse, senza conoscere i loro genitori, come progetti le tue risorse?

Se non sono abbastanza chiaro o se ho molte domande, faccelo sapere.

    
posta Supercell 18.11.2013 - 18:35
fonte

1 risposta

5

Si,

GET / api / companies / 1 / employees

sarebbe il modo per ottenere i dipendenti di una società.

Che cosa esattamente le tue offerte di risorse dei dipendenti dipenderebbero da alcuni dettagli della tua applicazione. Ad esempio, potresti avere accessi per amministratori direttamente collegati a una società specifica. In questo caso sarebbe una possibile scorciatoia la risorsa dei dipendenti e andare direttamente a un dipendente o elenco di dipendenti. Ma in casi normali / api / dipendenti lavorerebbero solo in combinazione con le aziende.

Una domanda molto interessante sarebbe il livello di nidificazione. Questa è una delle domande che alcune persone possono discutere per ore. Ad esempio, Ruby on Rails ora ha un'opzione per i percorsi "superficiali".

Sebbene non esista un limite tecnico al numero di livelli (forse la lunghezza massima di un URL), penso che due livelli dovrebbero essere sufficienti per la maggior parte dei casi e se si desidera evitare il nesting più profondo se possibile, poiché renderebbe il codice più strutturato e manutenibile.

Il tuo esempio è abbastanza tipico ed è facile mostrare perché non avresti davvero bisogno di un terzo livello per le attività nella maggior parte degli scenari. I tuoi compiti sono direttamente collegati a un dipendente. Quindi la risorsa dell'entità in qualche modo porta già le informazioni sulla compagnia. (La selezione di un dipendente seleziona automaticamente la società). Quindi, fornire nuovamente all'URL l'azienda in qualche modo ripete le informazioni.

GET /api/employees/123/tasks

ha tutte le informazioni necessarie per accedere ai tuoi dati. Allora perché renderlo più complesso?

Non sono sicuro di comprendere appieno la tua ultima domanda.

Limitare l'accesso in questo contesto è piuttosto facile. Supponiamo che tu abbia un cliente che ha accesso solo alle risorse dell'azienda con l'ID 123. Quindi tutto ciò che devi fare è avviare il codice del controller assegnando alcuni "limiti rigidi". Se l'utente che ha effettuato il login non è autorizzato ad accedere a nulla tranne una società, crea un oggetto per tale società e da lì in poi usa solo questo oggetto per qualsiasi altro accesso.

Supponiamo di avere un progetto Rails. Per questo abbiamo un modello per ogni risorsa menzionata. Inoltre, disponiamo di un sistema di autenticazione che ci fornisce l'utente attualmente connesso. In questo caso sarebbe facile come restituire qualcosa come l'elenco degli impiegati:

current_user.company.employees

Si noti che non tenta nemmeno di utilizzare alcun ID di società utilizzato nell'URL (che in caso di Rails sarebbe memorizzato in params [: company_id]).

Cerca di ottenere le mansioni di un dipendente specifico con

GET /api/companies/123/employees/456/tasks

current_user.company.employees.find(params[employee_id]).tasks

Nota di nuovo che questo sta andando sul "percorso completo" invece di usare semplicemente

Employee.find(params[employee_id]).tasks

Il primo modulo creerà una query SQL con un sacco di LEFT JOINS che inizia dall'utente, passa attraverso l'azienda, i dipendenti e le attività. E importante in questo caso: fallirà se manca una singola relazione.

Anche se non nel contesto di un login e permessi, puoi ancora usarlo per far sì che l'utente abbia una certa conoscenza dei dati. Anche se in questo caso dovresti forse usare percorsi nidificati più profondi. Lo stesso esempio senza login, ma l'utente che effettua la richiesta deve conoscere l'id della compagnia corretta. In questo caso:

GET /api/companies/123/employees/456/tasks

Company.find(params[:company_id]).employees.find(params[employee_id]).tasks

Ancora una volta vai per il verso giusto. Se il tuo framework non ha questo tipo di relazioni oggettuali semplicemente nake sicuro che le tue richieste SQL usano JOINS in modo simile.

    
risposta data 18.11.2013 - 20:33
fonte

Leggi altre domande sui tag