Decidere sulla corretta progettazione dell'URL RESTful

1

Sto lavorando su un sistema di ticketing. L'utente nel sistema è organizzato in un modo gerarchico a un livello. Ci sono molti team e ogni team ha un manager e ogni utente nel team ha un solo manager. Un ticket può essere creato da qualsiasi utente in squadra. Ho il seguente caso d'uso:

  1. Un utente può vedere solo i ticket creati da lui
  2. Un manager può vedere tutti i ticket creati dal team

Per caso (1) penso al seguente endpoint dell'API:

/api/tickets vs /api/users/:id/tickets

Per caso (2) sto pensando al seguente schema:

/api/tickets?manager=true vs /api/users/:id/tickets

per il caso successivo sul lato server posso controllare se l'utente è il gestore, se sì allora può vedere tutti i biglietti della sua squadra solo per conto suo.

In entrambi i casi la prima scelta è possibile perché Spring mantiene la propria sessione di utente autenticato quindi l'invio dell'id utente in ogni richiesta è ridondante, ma ho letto che gli endpoint sono progettati in modo stateless.

Quindi, la domanda è quale schema ha più senso e dovrei fare affidamento sul framework come Spring per fornirmi i dettagli o dovrei progettare i miei endpoint API in modo stateless anche se sembra ridondante?

    
posta CodeYogi 20.10.2017 - 23:12
fonte

2 risposte

5

Deciding on the correct RESTful URL design

Ricorda:

  1. REST non si cura di quali ortografie usi per i tuoi identificatori.
  2. "Risorse" sono risorse di integrazione , non entità di dominio.

So, the question is which scheme makes more sense and should I rely on the framework like Spring to provide me the details or I should design my API endpoints in a stateless fashion although it seems redundant?

Se stavi creando un sito web, come lo faresti? Da lì, pensa a come lo faresti con un sito web leggibile dalla macchina . Presto! hai te stesso un'API REST

Probabilmente avresti una sorta di home page, con un link che dice qualcosa come "I miei biglietti". Per gli operatori, sarebbe una vista con forse un titolo e un elemento di lista con i propri biglietti in esso. Per i gestori, potrebbe essere la stessa vista, ma con un collegamento aggiuntivo a un'altra pagina che include la panoramica dei ticket dei team, oppure potrebbe essere la vista originale con elementi aggiuntivi che mostrano il lavoro del team.

Un'idea chiave di REST è che il client e il server hanno una visione comune del tipo di supporto, vale a dire le regole di elaborazione, che possono includere il supporto per elementi facoltativi. Il server guida il cliente scegliendo quali elementi fornire nella rappresentazione.

Questo suggerisce che una determinata entità nel tuo modello di dominio potrebbe avere più di una rappresentazione "corrente". Potresti ottenerlo con due diverse risorse , ciascuna delle quali esegue una particolare mappatura dallo stato corrente a una rappresentazione.

Quindi le richieste di Bob potrebbero essere reindirizzate alla risorsa per i singoli contributori

GET /myTickets
Authorization: "Bob"

302 Found
Location: /03ea42b9-58ad-47cf-bff0-47619253a362

Ma le richieste di Alice potrebbero essere reindirizzate alla risorsa per i gestori

GET /myTickets
Authorization: "Alice"

302 Found
Location /ac78f4ee-752f-4c3c-adfa-54ead639823f

Proprio come il modo in cui facciamo le cose nel web, ai clienti non interessa quale dovrebbe essere l'ortografia dell'URI; seguono semplicemente i collegamenti che vengono loro forniti.

Quindi nel tuo primo esempio

GET /api/tickets
Authorization: ...

302 Found
Location: /api/users/:id/tickets

Va perfettamente bene. Per i manager, potresti analogamente fare

GET /api/tickets
Authorization: ...

302 Found
Location: /api/managers/:id/tickets

/api/tickets?manager=true

REST non si cura dell'ortografia, ma riferimenti relativi do; I punti-segmenti vanno bene per i percorsi, ma non esiste un'ortografia analoga che ti permetta di muoverti sul percorso preservando la query. In altre parole, se disponi di molte risorse correlate, è più utile che condividano un percorso comune rispetto a una query comune.

GET /api/tickets?manager=true
Authorization: ...

302 Found
Location: /api/managers/:id/tickets

Va perfettamente bene.

    
risposta data 21.10.2017 - 04:29
fonte
1

VoiceOfUnreason ha coperto la maggior parte delle parti che hai chiesto con una domanda rimanente:

What about the Spring issue? if the RESTful URLs needs to be stateless then I need to tell in the URL who is the user, right? because suppose in future I decide to not to use Spring or not store session then I have to change the whole URL scheme, makes sense?

Sì, questo sarebbe il caso, se dovessi rimuovere la parte della sessione dovresti ridisegnare gli endpoint. Nella risposta sopra puoi vedere in che modo VoiceOfUnreason ha risolto questo problema.

L'accesso all'applicazione con un'autorizzazione potrebbe fornire all'utente il link alla posizione dei suoi ticket. Nel suo esempio il controllore potrebbe controllare a) l'autorizzazione eb) controllare le regole dell'utente. A sua volta restituisce /api/{manager|user}/:user_id/tickets . Quindi una richiesta di un utente specifico con il codice di autorizzazione punta sempre ai ticket dell'utente.

Altre opzioni valide potrebbero essere ...

  • Costruire un singolo endpoint tickets con il seguente parametro tickets?user_id=x - Dopo aver effettuato il login, l'API restituirà un link a /tickets per i gestori o /tickets?user_id=x se è un utente normale a vedere i suoi ticket.
  • Costruisci /tickets e /users endpoint con:
    • /tickets che fornisce un elenco di tutti i ticket se sei un gestore (e un reindirizzamento a /users/:id/tickets in caso contrario.)
    • /tickets/:id che fornisce un biglietto solo
    • /users/:id/tickets che fornisce i ticket che hai creato

Le tue opzioni qui sono fondamentalmente aperte, devi solo scegliere il tuo veleno e attaccarlo. Inoltre c'era una domanda su Stackoverflow sull'uso della sessione nei servizi RESTful, dovresti controllare la discussione qui

Inoltre, puoi anche dare un'occhiata al HATEOAS paradigma dell'architettura. Descrive fondamentalmente che client e server possono essere disaccoppiati fornendo ulteriori informazioni su quali azioni sono possibili. Questo può essere visto approssimativamente come costruire qualcosa di simile a una macchina statale e potrebbe chiarire anche una certa confusione. Questo è anche approssimativamente ciò che VoiceOfUnreason ha già fatto con Found risposte.

    
risposta data 21.10.2017 - 10:16
fonte