È OK modificare parzialmente una collezione con PUT o DELETE?

19

Ho una collezione di prodotti in un gruppo di prodotti, ad esempio:

product-groups/123/products
  1. Se ho bisogno di aggiungi alla raccolta, è giusto che io passi solo alcuni prodotti con PUT?

  2. Se devo eliminare alcuni prodotti dalla raccolta, è giusto che io passi i dati del filtro (una serie di ID) con DELETE?

Qual è il modo migliore per implementare la funzionalità nello spirito di ReST?

Modifica: gli elementi sono collegamenti a entità separate, in pratica ID di prodotti.

    
posta user151851 22.03.2013 - 18:33
fonte

4 risposte

9

In generale hai un endpoint che rappresenta l'intera collezione di x :

/products

Di ', vuoi aggiornare un singolo prodotto, fai un PUT a /products/{id} . Se si desidera aggiornare parzialmente un singolo prodotto (non aggiornando tutti i campi), è possibile utilizzare anche un PATCH a /products/{id} . Lo stesso vale per la cancellazione di una singola entità ( DELETE a /products/{id} ).

Se vuoi scegliere come target una risorsa singola , puoi qualificarti tramite path, che single ressource, che vuoi modificare.

L'unica azione che interrompe lo schema è la creazione di una risorsa. Quando crei una risorsa, scegli come target la raccolta nel suo complesso, ad esempio POST a /products .

Detto questo, dovrebbe essere chiaro, che l'obiettivo per le operazioni che riguardano la raccolta nel suo complesso, dovrebbe andare al punto di raccolta appropriato.

es. vuoi recuperare un sottoinsieme di prodotti che sono rossi, lo chiedi con

OTTIENI a /products?colour=red .

Quindi, se vuoi eliminare tutti questi elementi, DELETE /products?colour=red . Oppure, se desideri eliminare alcuni prodotti tramite id , potresti DELETE /products?id=1&id=2&id=3 .

Che dire della creazione di massa delle risorse? POST la tua collezione [{...},{...},{...}] semplicemente a /products . Lo stesso vale per PUT e PATCH .

È molto semplice.

Per rispondere alle tue domande:

If I need to add to the collection, is it OK that I pass only some products with PUT?

Non è solo OK, sei incoraggiato a farlo in quel modo.

If I need to delete some products from the collection, is it OK that I pass filter data (an array of ID's) with DELETE?

Va bene. Come scrisse Eneko Alonso, a volte ci sono bulkoperations incapsulate tramite "controllore" -endpoint, cioè un POST viene usato per attivare operazioni (complesse).

    
risposta data 17.12.2014 - 22:07
fonte
5

Di solito, i metodi REST sono concepiti per operare su una singola entità / oggetto (CRUD).

Ci sono diverse opzioni:

  • Tratta le tue raccolte come entità e aggiornale tramite POST
  • Crea operazioni alternative non REST

Il primo segue gli standard REST, ma può essere costoso, dal momento che gli oggetti / le entità della raccolta potrebbero essere molto grandi (l'aggiornamento di un gruppo con migliaia di prodotti solo per aggiungere / rimuovere un prodotto sarebbe una richiesta pesante). / p>

La seconda opzione è preferita da molte API, come metodo per estendere il REST oltre le operazioni CRUD.

Ad esempio:

GET product-groups/123/products (list all the products in the group)
POST product-groups/123/products/append (POST a list of new product ids to append to the group)
POST product-groups/123/products/remove (POST a list of product ids to remove from the group)

Molte API utilizzano sempre il POST per queste operazioni estese, ma nulla ti limita a utilizzare altri metodi http (oltre al limite di GET e DELETE per avere un corpo vuoto)

    
risposta data 22.03.2013 - 19:21
fonte
3

Solo per precise risposte / commenti precedenti.

Come noto, il POST è il metodo per aggiungere singoli elementi alla collezione.

DELETE, a sua volta, è il metodo per eliminare un singolo elemento dalla raccolta. Entrambi gli scenari sono perfettamente RESTful.

Tuttavia, dovresti usare l'URI appropriato per riferire un singolo elemento o l'intera collezione.

Ad esempio, per aggiungere un elemento alla raccolta, dovresti inserire i dati POST nell'URI seguente:

https://www.factory.net/products/

Per eliminare un singolo prodotto dalla raccolta, è possibile utilizzare il metodo DELETE inviando una richiesta a qualcosa di simile:

https://www.factory.net/products/108/

Il metodo PATCH può essere utilizzato per aggiornare alcuni elementi all'interno della raccolta. Ad esempio, quando è necessario aggiornare solo un campo in un elemento. PUTting una rappresentazione completa delle risorse per una raccolta molto grande può essere un'operazione molto costosa.

    
risposta data 17.12.2014 - 17:42
fonte
2

In linea di principio, tutte le operazioni RESTful sono valide su una raccolta, ma assicurati di capire in che modo la semantica dei verbi si applica a una raccolta:

  • PUT è una sostituzione completa .

    • Se Metti su un singleton (ad esempio /item/{id} ) e lascia name out, dovrebbe essere cancellato o impostato su null o qualcosa di simile.
    • Se Metti in una raccolta e non includi un elemento, dovrebbe essere rimosso da quella raccolta.

    Mentre è possibile utilizzare un PUT per aggiungere elementi, è necessario inviare "tutti" elementi. L'invio di "alcuni" elementi dovrebbe comportare rimozioni (presumo che questo non sia ciò che l'OP desidera).

  • DELETE è più intuitivo. È valido cancellare la collezione o qualsiasi suo sottoinsieme filtrato. Solo gli articoli inclusi nel filtro dovrebbero essere interessati.

  • PATCH è anche valido. In teoria, dovresti fornire un elenco di "operazioni". Ad esempio, dovresti tecnicamente inviare qualcosa del tipo:

    [{ 
        "action": "update",
        "id": <id>,
        "value": {...}
    },{
        "action": "add",
        "value": {...}
    }, ...]
    

    In pratica, è più comune vedere un'API che accetta un elenco parziale di oggetti in cui ogni elemento viene elaborato utilizzando una logica UPSERT (aggiornamento o inserimento).

  • Tecnicamente, il POST dovrebbe elaborare l'input "in base alla semantica specifica della risorsa".

    • In pratica, il POST viene normalmente utilizzato per le operazioni di "creazione".
    • Tuttavia, POST è anche il verbo utilizzato per le chiamate non standard. Mentre è vigoroso il dibattito se gli endpoint di azione sono rigorosamente RESTful (io lato con i "no"), il POST è il verbo appropriato se stai inviando una richiesta a un endpoint come {resource}/activate .

NOTA: quando si utilizzano operazioni non GET sulle raccolte, considerare attentamente la definizione di successo e fallimento. REST non ti dà un buon modo per comunicare il successo parziale. Un buon valore predefinito è di presumere che si eseguirà l'operazione in una transazione con un criterio di successo tutto o niente. Se questo non è ciò che desideri, probabilmente non dovresti interagire direttamente con la raccolta.

    
risposta data 22.03.2018 - 21:41
fonte

Leggi altre domande sui tag