Per includere un ID risorsa nel payload o per derivare dall'URI

9

Progettando un'API, ci siamo confrontati con la questione se un carico utile PUT debba contenere l'ID della risorsa da aggiornare.

Questo è ciò che abbiamo attualmente:

PUT /users/123 Payload: {name: "Adrian"}

Il nostro codice di rotta estrae l'ID dall'URI e continua con l'aggiornamento.

I primi utenti della nostra API stanno mettendo in dubbio il motivo per cui non permettiamo l'ID nel payload:

PUT /users/123 Payload: {id: 123, name: "Adrian"}

Il motivo per cui non l'abbiamo consentito è perché l'ID è duplicato, nel payload e nell'URI.

Pensandoci sopra, stiamo accoppiando la risorsa all'URI.

Se l'URI non ha l'ID, il carico utile dovrà essere modificato:

PUT /no/id/here Payload: {name: "Adrian"} < What user???

Ci sono dei motivi per non farlo?

    
posta Adrian Lynch 27.11.2014 - 11:07
fonte

2 risposte

14

Sei supposto che accoppia l'identificatore Risorsa uniforme alla risorsa .

Quando REST viene implementato con HTTP, si utilizza GET per recuperare il valore corrente della risorsa e PUT per impostare un nuovo valore. Il GET non ha un payload, quindi la risorsa deve essere identificata dall'URI. E il PUT è logicamente fatto allo stesso URI e il payload dovrebbe apparire esattamente come quello che vuoi che il prossimo GET restituisca.

È possibile utilizzare il POST su un URI diverso, ma sarebbe meno sensato in quanto sarebbe inutilmente asimmetrico al GET. Il POST all'URI comune poteva avere senso solo per la creazione di nuove risorse ( POST /users/new , carico utile: {name: "Adrian"} , risposta {id: 345, name: "Adrian"} ), ma questo è non idempotente e quindi dovrebbe essere evitato se stai cercando REST ¹. Invece dovresti riservare un ID con una chiamata e poi usare PUT per impostare il nuovo ID; è tollerante ai guasti, perché se la prima richiesta fallisce, la prenotazione dell'ID può scadere e il PUT è idempotente. Oppure usa UUID generato dal cliente.

¹ La definizione di REST non dice nulla di idempotence, quindi non posso davvero affermare che non è REST se si hanno operazioni non identienti. Ciò non cambia il fatto che attenersi a richieste idempotenti rende le cose più affidabili senza complicarle e pertanto è raccomandato.

    
risposta data 27.11.2014 - 11:24
fonte
1

Thinking about this some more, we are coupling the resource to the URI.

If the URI doesn't have the ID, the payload will need to be amended:

PUT /no/id/here Payload: {name: "Adrian"} < What user???

Are there any reasons not to?

La risposta a questa domanda dipende dal fatto che si desideri consentire al client di modificare l'ID?

Se il client può modificare l'ID, tramite un PUT, l'URI della risorsa cambierà e dovresti fornire un 301 permanentemente spostato ogni volta che una risorsa accede al vecchio URI.

Quindi, ad esempio, inizi con una risorsa in

/users/123

e il client METTA il seguente sulla risorsa

{id: 222, name: "Adrian"}

la risorsa è stata aggiornata e il suo URI è ora

/users/222

Il campo Location nella risposta PUT dovrebbe contenere il nuovo URI e se vai a /users/123 dovresti ottenere una risposta 301 con il campo Location che punta alla nuova risorsa /users/222 .

Nella maggior parte dei casi, anche se in realtà non si desidera che il client sia in grado di modificare l'ID, in questo modo può diventare piuttosto complicato abbastanza rapidamente. In questo caso l'ID è qualcosa che solo il server può cambiare e dovresti lasciarlo fuori dal corpo PUT, poiché il client non può aggiornare questo stato.

Se PUT richiede un diverso URI sulla stessa risorsa, ad esempio

/users/adian_lync

quindi se tale risorsa non esiste il server dovrebbe crearlo e creare e ID quando lo sta facendo

    
risposta data 27.11.2014 - 19:36
fonte

Leggi altre domande sui tag