Best practice per aggiornamenti parziali in un servizio RESTful


208

Sto scrivendo un servizio RESTful per un sistema di gestione dei clienti e sto cercando di trovare le migliori pratiche per l'aggiornamento parziale dei record. Ad esempio, desidero che il chiamante sia in grado di leggere l'intero record con una richiesta GET. Ma per aggiornarlo sono consentite solo alcune operazioni sul record, come cambiare lo stato da ABILITATO a DISATTIVATO. (Ho scenari più complessi di così)

Non voglio che il chiamante invii l'intero record con solo il campo aggiornato per motivi di sicurezza (sembra anche eccessivo).

Esiste un modo consigliato per costruire gli URI? Quando si leggono i libri REST, le chiamate in stile RPC sembrano essere disapprovate.

Se la chiamata seguente restituisce il record cliente completo per il cliente con ID 123

GET /customer/123
<customer>
    {lots of attributes}
    <status>ENABLED</status>
    {even more attributes}
</customer>

come devo aggiornare lo stato?

POST /customer/123/status
<status>DISABLED</status>

POST /customer/123/changeStatus
DISABLED

...

Aggiornamento : per aumentare la domanda. In che modo si incorporano le "chiamate della logica aziendale" in un'API REST? Esiste un modo concordato per farlo? Non tutti i metodi sono CRUD per natura. Alcuni sono più complessi, come ' sendEmailToCustomer (123) ', ' mergeCustomers (123, 456) ', ' countCustomers () '

POST /customer/123?cmd=sendEmail

POST /cmd/sendEmail?customerId=123

GET /customer/count 

3
Per rispondere alla tua domanda sulle "chiamate di logica aziendale" ecco un post sullo POSTstesso Roy Fielding: roy.gbiv.com/untangled/2009/it-is-okay-to-use-post dove si trova l'idea di base: se non c'è è un metodo (come GETo PUT) ideale per il tuo uso operativo POST.
rojoca,

Questo è praticamente quello che ho finito per fare. Effettuare chiamate REST per recuperare e aggiornare risorse conosciute utilizzando GET, PUT, DELETE. POST per l'aggiunta di nuove risorse e POST con alcuni URL descrittivi per le chiamate di logica aziendale.
magiconair

Qualunque cosa tu decida, se tale operazione non fa parte della risposta GET, non hai un servizio RESTful. Non lo vedo qui
MStodd,

Risposte:


69

Fondamentalmente hai due opzioni:

  1. Usa PATCH(ma nota che devi definire il tuo tipo di media che specifica cosa accadrà esattamente)

  2. Utilizzare POSTper una risorsa secondaria e restituire 303 Vedi Altro con l'intestazione Posizione che punta alla risorsa principale. L'intenzione del 303 è di dire al cliente: "Ho eseguito il tuo POST e l'effetto è stato che qualche altra risorsa è stata aggiornata. Vedi l'intestazione della posizione per quale risorsa era". POST / 303 è inteso per aggiunte iterative a risorse per costruire lo stato di alcune risorse principali ed è perfetto per aggiornamenti parziali.


OK, il POST / 303 ha senso per me. PATCH e MERGE non sono riuscito a trovare nell'elenco di verbi HTTP validi, quindi richiederebbe ulteriori test. Come costruirò un URI se desidero che il sistema invii un'email al cliente 123? Qualcosa di simile a un puro metodo RPC che non cambia affatto lo stato dell'oggetto. Qual è il modo RESTful di farlo?
magiconair

Non capisco la domanda sull'URI dell'email. Vuoi implementare un gateway su cui POST puoi farlo inviare una e-mail o stai cercando mailto: customer.123@service.org?
Jan Algermissen,

15
Né REST né HTTP hanno nulla a che fare con CRUD a parte alcune persone che equiparano i metodi HTTP a CRUD. REST riguarda la manipolazione dello stato delle risorse trasferendo rappresentazioni. Qualunque cosa tu voglia ottenere, lo fai trasferendo una rappresentazione in una risorsa con la semantica appropriata. Fai attenzione ai termini "richiami di metodo puri" o "logica aziendale" poiché implicano troppo facilmente "HTTP è per il trasporto". Se è necessario inviare un'e-mail, POST a una risorsa gateway, se è necessario unire gli account, crearne uno nuovo e rappresentazioni POST delle altre due, ecc.
Jan Algermissen,

9
Vedi anche come lo fa Google: googlecode.blogspot.com/2010/03/…
Marius,

4
williamdurand.fr/2014/02/14/please-do-not-patch-like-an-idiot PATCH [{"op": "test", "path": "/ a / b / c", "value" : "foo"}, {"op": "remove", "path": "/ a / b / c"}, {"op": "add", "path": "/ a / b / c" , "value": ["pippo", "bar"]}, {"op": "sostituisci", "percorso": "/ a / b / c", "valore": 42}, {"op": "move", "from": "/ a / b / c", "path": "/ a / b / d"}, {"op": "copy", "from": "/ a / b / d "," path ":" / a / b / e "}]
intotecho
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.