Domanda PUT vs. POST in REST


Secondo la specifica HTTP / 1.1:

Il POST il metodo viene utilizzato per richiedere che il server di origine accetti l'entità inclusa nella richiesta come nuovo subordinato della risorsa identificata da Request-URI nel Request-Line

In altre parole, POST è abituato a creare .

Il PUT il metodo richiede che l'entità inclusa sia archiviata sotto la fornitura Request-URI. Se la Request-URI si riferisce a una risorsa già esistente, l'entità inclusa DOVREBBE essere considerata come una versione modificata di quella che risiede sul server di origine. Se la Request-URI non punta a una risorsa esistente e quell'URI può essere definito come una nuova risorsa dall'agente utente richiedente, il server di origine può creare la risorsa con quell'URI. "

Questo è, PUT è abituato a creare o aggiornare .

Quindi, quale dovrebbe essere usato per creare una risorsa? O uno deve supportare entrambi?


4456
2018-03-10 14:25


origine


risposte:


Complessivamente:  

Sia PUT che POST possono essere utilizzati per la creazione.

Devi chiedere "a cosa stai eseguendo l'azione?" per distinguere ciò che dovresti usare. Supponiamo che tu stia progettando un'API per fare domande. Se si desidera utilizzare il POST, lo si farebbe su un elenco di domande. Se vuoi usare PUT, lo faresti a una particolare domanda.

Possono essere utilizzati entrambi, quindi quale si dovrebbe usare nel mio progetto RESTful:

Non è necessario supportare sia PUT che POST.

Che viene utilizzato è lasciato a voi. Ma ricorda di usare quello giusto a seconda dell'oggetto a cui fai riferimento nella richiesta.

Alcune considerazioni:

  • Nomini i tuoi oggetti URL che crei esplicitamente o lasci decidere al server? Se li chiami, usa PUT. Se lasci decidere al server, usa POST.
  • PUT è idempotente, quindi se Metti un oggetto due volte, non ha alcun effetto. Questa è una bella proprietà, quindi userei PUT quando possibile.
  • Puoi aggiornare o creare una risorsa con PUT con lo stesso URL dell'oggetto
  • Con POST è possibile avere 2 richieste contemporaneamente apportando modifiche a un URL e possono aggiornare parti diverse dell'oggetto.

Un esempio:

Ho scritto quanto segue come parte di un'altra risposta su SO in merito :

INVIARE:

Utilizzato per modificare e aggiornare una risorsa

POST /questions/<existing_question> HTTP/1.1
Host: www.example.com/

Si noti che quanto segue è un errore:

POST /questions/<new_question> HTTP/1.1
Host: www.example.com/

Se l'URL non è stato ancora creato, tu   non dovrebbe usare il POST per crearlo   mentre si specifica il nome. Questo dovrebbe   causare un errore "risorsa non trovata"   perché <new_question> non esiste   ancora. Dovresti mettere il <new_question>   prima risorsa sul server.

Potresti comunque fare qualcosa di simile   questo per creare una risorsa usando il POST:

POST /questions HTTP/1.1
Host: www.example.com/

Nota che in questo caso la risorsa   il nome non è specificato, i nuovi oggetti   Il percorso URL ti verrà restituito.

METTERE:  

Utilizzato per creare una risorsa, o   sovrascriverlo. Mentre si specifica il   risorse nuovo URL.

Per una nuova risorsa:

PUT /questions/<new_question> HTTP/1.1
Host: www.example.com/

Per sovrascrivere una risorsa esistente:

PUT /questions/<existing_question> HTTP/1.1
Host: www.example.com/

3480
2018-03-10 14:29



Puoi trovare affermazioni sul web che dicono

Nemmeno è giusto.


Migliore è scegliere tra PUT e POST basati su idempotence  dell'azione.

METTERE  implica mettere una risorsa - sostituendo completamente qualsiasi cosa sia disponibile all'URL dato con una cosa diversa. Per definizione, un PUT è idempotente. Fallo tutte le volte che vuoi, e il risultato è lo stesso. x=5 è idempotente. È possibile inserire una risorsa indipendentemente dal fatto che esistesse in precedenza, oppure no (ad esempio, per creare o aggiornare)!

INVIARE  aggiorna una risorsa, aggiunge una risorsa sussidiaria o provoca una modifica. Un post non è idempotente, nel modo in cui x++ non è idempotente.


Con questo argomento, PUT è per creare quando conosci l'URL della cosa che creerai. Il POST può essere utilizzato per creare quando si conosce l'URL della "fabbrica" ​​o gestore per la categoria di cose che si desidera creare.

così:

POST /expense-report

o:

PUT  /expense-report/10929

1878
2018-04-22 14:55



  • INVIARE  a un URL crea una risorsa secondaria  a a server definito  URL.
  • METTERE  a un URL crea / sostituisce la risorsa  nella sua interezza al cliente definito  URL.
  • PATCH  a un URL aggiornamenti parte  della risorsa  a quell'URL definito dal cliente.

La specifica pertinente per PUT e POST è RFC 2616 §9.5 sgg.

POST crea una risorsa secondaria , così POST a /items crea una risorsa che vive sotto il /items risorsa. Per esempio. /items/1. L'invio dello stesso pacchetto di posta due volte creerà due risorse.

METTERE  è per creare o sostituire una risorsa in a URL conosciuto dal cliente .

Perciò: METTERE  è solo un candidato per CREATE dove il client conosce già l'url prima che la risorsa venga creata. Per esempio. /blogs/nigel/entry/when_to_use_post_vs_put poiché il titolo è usato come chiave della risorsa

METTERE  sostituisce la risorsa nell'URL conosciuto se già esiste, quindi l'invio della stessa richiesta due volte non ha alcun effetto. In altre parole, le chiamate a PUT sono idempotenti .

La RFC si legge così:

La differenza fondamentale tra le richieste POST e PUT si riflette nel diverso significato dell'Unità della richiesta. L'URI in una richiesta POST identifica la risorsa che gestirà l'entità inclusa. Quella risorsa potrebbe essere un processo di accettazione dei dati, un gateway per qualche altro protocollo o un'entità separata che accetta annotazioni. Al contrario, l'URI in una richiesta PUT identifica l'entità inclusa nella richiesta: l'agente utente sa quale URI è inteso e il server NON DEVE tentare di applicare la richiesta ad un'altra risorsa. Se il server desidera che la richiesta venga applicata a un URI diverso,

Nota:  PUT è stato principalmente utilizzato per aggiornare le risorse (sostituendole nella loro interezza), ma di recente c'è movimento verso l'utilizzo di PATCH per l'aggiornamento delle risorse esistenti, in quanto PUT specifica che sostituisce l'intera risorsa. RFC 5789.


562
2018-04-07 05:52



Sommario:

Creare:

Può essere eseguito con PUT o POST nel modo seguente:

METTERE

crea IL  nuova risorsa con newResourceId  come identificatore, sotto l'URI / risorse, o collezione .

PUT /resources/<newResourceId> HTTP/1.1 

INVIARE

crea UN  nuova risorsa sotto l'URI / risorse, o collezione . Di solito l'identificatore viene restituito dal server.

POST /resources HTTP/1.1

Aggiornare:

Può solo  essere eseguito con PUT nel modo seguente:

METTERE

Aggiorna la risorsa con existingResourceId  come identificatore, sotto l'URI / risorse, o collezione .

PUT /resources/<existingResourceId> HTTP/1.1

Spiegazione:

Quando si ha a che fare con REST e URI come generale, si ha generico  sul sinistra  e specifica  sul destra . Il farmaci generici  di solito sono chiamati collezioni  e più specifica  gli oggetti possono essere chiamati risorsa . Si noti che a risorsa  può contenere a collezione .

Esempi:

<- generico - specifico ->

URI: website.com/users/john
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource

URI:website.com/users/john/posts/23
website.com  - whole site
users        - collection of users
john         - item of the collection, or a resource
posts        - collection of posts from john
23           - post from john with identifier 23, also a resource

Quando usi POST lo sei sempre  riferendosi a a collezione , quindi ogni volta che dici:

POST /users HTTP/1.1

stai postando un nuovo utente al utenti   collezione .

Se vai avanti e prova qualcosa del genere:

POST /users/john HTTP/1.1

funzionerà, ma semanticamente stai dicendo che vuoi aggiungere una risorsa al John   collezione  sotto il utenti   collezione .

Una volta che si utilizza PUT, si sta facendo riferimento a a risorsa  o un singolo oggetto, possibilmente dentro a collezione . Quindi quando dici:

PUT /users/john HTTP/1.1

stai dicendo all'aggiornamento del server, o crea se non esiste, il John   risorsa  sotto il utenti   collezione .

Spec:

Permettetemi di evidenziare alcune parti importanti delle specifiche:

INVIARE

Il INVIARE  il metodo viene utilizzato per richiedere il server di origine accettare  l'entità inclusa nella richiesta come a nuovo  subordinare  della risorsa identificata dall'URI della richiesta nella riga di richiesta

Quindi, crea un nuovo risorsa  a collezione .

METTERE

Il METTERE  metodo richiede che l'entità inclusa sia immagazzinato  sotto l'URI di richiesta fornito. Se l'URI della richiesta si riferisce a un già esistente  risorsa, l'entità inclusa DOVREBBE essere considerata come un versione modificata  di quello che risiede sul server di origine. Se l'URI della richiesta lo fa non puntare a un esistente  risorsa, e quell'URI è capace  di essere definito come a nuovo  risorsa  dallo user agent richiedente, il server di origine può creare  la risorsa con quell'URI. "

Quindi, creare o aggiornare in base all'esistenza del risorsa .

Riferimento:


165
2017-08-14 22:47



Mi piacerebbe aggiungere il mio consiglio "pragmatico". Usa PUT quando conosci l'"id" con il quale l'oggetto che stai salvando può essere recuperato. L'utilizzo di PUT non funzionerà molto bene se è necessario, ad esempio, un ID generato da un database da restituire per consentire future ricerche o aggiornamenti.

Quindi: per salvare un utente esistente o uno in cui il client genera l'ID e si è verificato che l'ID è univoco:

PUT /user/12345 HTTP/1.1  <-- create the user providing the id 12345
Host: mydomain.com

GET /user/12345 HTTP/1.1  <-- return that user
Host: mydomain.com

Altrimenti, usa POST per creare inizialmente l'oggetto e PUT per aggiornare l'oggetto:

POST /user HTTP/1.1   <--- create the user, server returns 12345
Host: mydomain.com

PUT /user/12345 HTTP/1.1  <--- update the user
Host: mydomain.com

156
2018-01-15 19:59



POST significa "crea nuovo" come in "Ecco l'input per creare un utente, crearlo per me".

PUT significa "inserisci, sostituisci se già esiste" come in "Ecco i dati per l'utente 5".

POST a example.com/users poiché non conosci ancora l'URL dell'utente, vuoi che il server lo crei.

Metti su example.com/users/id poiché vuoi sostituire / creare a specifica  utente.

POSTARE due volte con gli stessi dati significa creare due utenti identici con ID diversi. METTENDO due volte con gli stessi dati crea l'utente il primo e lo aggiorna allo stesso stato la seconda volta (senza modifiche). Poiché si finisce con lo stesso stato dopo un PUT, non importa quante volte lo si esegue, si dice che sia "ugualmente potente" ogni volta - idempotente. Questo è utile per riprovare automaticamente le richieste. Non è più "sei sicuro di voler inviare nuovamente" quando premi il pulsante Indietro sul browser.

Un consiglio generale è di usare il POST quando hai bisogno che il server controlli la generazione di URL delle tue risorse. Usa PUT altrimenti. Preferisci PUT su POST.


145
2017-10-23 14:27



Usa POST per creare e PUT per aggiornare. È così che lo fa Ruby on Rails, comunque.

PUT    /items/1      #=> update
POST   /items        #=> create

105
2018-03-10 14:28



REST è un molto  concetto di alto livello. In effetti, non menziona nemmeno l'HTTP!

Se hai dei dubbi su come implementare REST in HTTP, puoi sempre dare un'occhiata a Atom Publication Protocol (AtomPub)  specifica. AtomPub è uno standard per la scrittura di servizi web RESTful con HTTP sviluppato da molti luminari HTTP e REST, con alcuni input da Roy Fielding, l'inventore di REST e (co-) inventore dello stesso HTTP.

In effetti, potresti anche essere in grado di utilizzare direttamente AtomPub. Anche se è uscito dalla comunità dei blog, non è in alcun modo limitato al blogging: è un protocollo generico per interagire RESTfully con raccolte arbitrarie (nidificate) di risorse arbitrarie via HTTP. Se è possibile rappresentare la propria applicazione come raccolta nidificata di risorse, è sufficiente utilizzare AtomPub e non preoccuparsi se utilizzare PUT o POST, quali codici di stato HTTP restituire e tutti quei dettagli.

Questo è ciò che AtomPub ha da dire sulla creazione di risorse (sezione 9.2):

Per aggiungere membri a una raccolta, i client inviano richieste POST all'URI della raccolta.


58
2018-03-10 15:27



La decisione se utilizzare PUT o POST per creare una risorsa su un server con un'API HTTP + REST è basata su chi possiede la struttura dell'URL.  Avere il cliente a conoscenza o partecipare alla definizione, la struttura dell'URL è un accoppiamento non necessario simile agli accoppiamenti indesiderati che sono sorti dalla SOA. La fuga di tipi di accoppiamenti è la ragione per cui REST è così popolare. Perciò, il metodo corretto da usare è POST.  Esistono eccezioni a questa regola e si verificano quando il cliente desidera mantenere il controllo sulla struttura delle risorse delle risorse che distribuisce. Questo è raro e probabilmente significa che qualcos'altro è sbagliato.

A questo punto alcune persone sosterranno che se di RESTful-URL  vengono utilizzati, il client conosce l'URL della risorsa e pertanto un PUT è accettabile. Dopo tutto, questo è il motivo per cui sono canonici, normalizzati, Ruby on Rails, gli URL di Django sono importanti, guarda l'API di Twitter ... blah blah blah. Quelle persone hanno bisogno di capire non esiste un URL riposante  e quello Lo stesso Roy Fielding afferma :

Un'API REST non deve definire nomi o gerarchie di risorse fisse (a   ovvio accoppiamento di client e server). I server devono avere la libertà   per controllare il proprio spazio dei nomi. Invece, consentire ai server di istruire   i clienti su come costruire URI appropriati, come ad esempio in HTML   forme e modelli URI, definendo quelle istruzioni all'interno dei media   tipi e relazioni di collegamento. [Il fallimento qui implica che i clienti lo sono   assumendo una struttura di risorse a causa di informazioni fuori banda, come ad esempio   uno standard specifico per il dominio, che è l'equivalente a livello di dati   Accoppiamento funzionale di RPC].

http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

L'idea di a RESTful-URL  è in realtà una violazione di REST poiché il server è responsabile della struttura dell'URL e dovrebbe essere libero di decidere come utilizzarlo per evitare l'accoppiamento. Se questo ti confonde, leggi l'importanza della scoperta di sé sul design dell'API.

L'uso di POST per creare risorse viene fornito con una considerazione di progettazione perché il POST non è idempotente.  Ciò significa che ripetere un POST diverse volte non garantisce lo stesso comportamento ogni volta. Questo spaventa le persone a usare PUT per creare risorse quando non dovrebbero.  Sanno che è sbagliato (il POST è per CREATE) ma lo fanno comunque perché non sanno come risolvere questo problema. Questa preoccupazione è dimostrata nella seguente situazione:

  1. Il client invia una nuova risorsa al server.
  2. Il server elabora la richiesta e invia una risposta.
  3. Il client non riceve mai la risposta.
  4. Il server non è a conoscenza del fatto che il client non abbia ricevuto la risposta.
  5. Il client non ha un URL per la risorsa (quindi PUT non è un'opzione) e ripete il POST.
  6. Il POST non è idempotente e il server ...

Il punto 6 è dove le persone si confondono comunemente su cosa fare. Tuttavia, non vi è alcun motivo per creare un kludge per risolvere questo problema. Invece, HTTP può essere utilizzato come specificato in RFC 2616  e il server risponde:

10.4.10 409 Conflitto

La richiesta non può essere completata a causa di un conflitto con la corrente   stato della risorsa. Questo codice è consentito solo in situazioni in cui   è previsto che l'utente possa essere in grado di risolvere il conflitto e   invia nuovamente la richiesta. Il corpo della risposta DOVREBBE includere abbastanza

informazioni per l'utente per riconoscere l'origine del conflitto.   Idealmente, l'entità di risposta includerebbe informazioni sufficienti per   utente o agente utente per risolvere il problema; tuttavia, potrebbe non essere   possibile e non è richiesto.

È più probabile che si verifichino conflitti in risposta a una richiesta PUT. Per   esempio, se sono state utilizzate le versioni e l'entità è PUT   incluse modifiche a una risorsa che sono in conflitto con quelle fatte da un   richiesta precedente (di terze parti), il server potrebbe utilizzare la risposta 409   per indicare che non è possibile completare la richiesta. In questo caso, il   l'entità di risposta conterrebbe probabilmente un elenco delle differenze tra   le due versioni in un formato definito dalla risposta Content-Type.

Rispondere con un codice di stato di 409 Conflitto è il ricorso corretto perché :

  • L'esecuzione di un POST di dati con un ID che corrisponde a una risorsa già presente nel sistema è "un conflitto con lo stato corrente della risorsa".
  • Poiché la parte importante è che il client comprenda che il server ha la risorsa e che intraprende le azioni appropriate. Questa è una "situazione / i in cui è previsto che l'utente possa essere in grado di risolvere il conflitto e inviare nuovamente la richiesta".
  • Una risposta che contiene l'URL della risorsa con l'ID in conflitto e le precondizioni appropriate per la risorsa fornirebbe "informazioni sufficienti per l'utente o l'agente utente per risolvere il problema", che è il caso ideale per RFC 2616.

Aggiornamento basato sul rilascio di RFC 7231 su Sostituisci 2616

RFC 7231  è progettato per sostituire 2616 e in Sezione 4.3.3  descrive la seguente risposta possibile per un POST

Se il risultato dell'elaborazione di un POST sarebbe equivalente a a   rappresentazione di una risorsa esistente, un server di origine può reindirizzare   l'agente utente di quella risorsa inviando una risposta 303 (Vedi Altro)   con l'identificativo della risorsa esistente nel campo Posizione. Questo   ha i vantaggi di fornire all'agente utente un identificatore di risorsa   e trasferendo la rappresentazione tramite un metodo più suscettibile a   cache condivisa, anche se al costo di una richiesta aggiuntiva se l'utente   l'agente non ha già la rappresentazione nella cache.

Ora potrebbe essere tentato di restituire semplicemente un 303 nel caso in cui un POST venga ripetuto. Comunque, l'opposto è vero. Restituire un 303 avrebbe senso solo se più richieste di creazione (creando risorse diverse) restituiscono lo stesso contenuto. Un esempio potrebbe essere un "ringraziamento per aver inviato il messaggio di richiesta" che il cliente non deve scaricare nuovamente ogni volta. RFC 7231 mantiene ancora nella sezione 4.2.2 che il POST non deve essere idempotente e continua a sostenere che il POST dovrebbe essere usato per creare.

Per maggiori informazioni a riguardo, leggi questo articolo .


54
2017-10-29 23:00



Mi piace questo consiglio, da La definizione di PUT di RFC 2616 :

La differenza fondamentale tra le richieste POST e PUT si riflette nel diverso significato dell'Unità della richiesta. L'URI in una richiesta POST identifica la risorsa che gestirà l'entità inclusa. Quella risorsa potrebbe essere un processo di accettazione dei dati, un gateway per qualche altro protocollo o un'entità separata che accetta annotazioni. Al contrario, l'URI in una richiesta PUT identifica l'entità inclusa nella richiesta: l'agente utente sa quale URI è inteso e il server NON DEVE tentare di applicare la richiesta ad un'altra risorsa.

Questo fa cenno con l'altro consiglio qui, che PUT si applica meglio alle risorse che hanno già un nome e POST è buono per creare un nuovo oggetto sotto una risorsa esistente (e lasciare che sia il nome del server).

Interpreto questo e i requisiti di idempotenza su PUT, nel senso che:

  • POST è buono per creare nuovi oggetti sotto una collezione (e creare non ha bisogno di essere idempotente)
  • PUT è buono per l'aggiornamento di oggetti esistenti (e l'aggiornamento deve essere idempotente)
  • Il POST può anche essere usato per aggiornamenti non identienti di oggetti esistenti (in particolare, cambiando parte di un oggetto senza specificare il tutto - se ci pensate, creare un nuovo membro di una collezione è in realtà un caso speciale di questo tipo di aggiornamento, dal punto di vista della collezione)
  • PUT può essere utilizzato anche per creare se e solo se si consente al client di nominare la risorsa. Ma dal momento che i client REST non sono tenuti a formulare ipotesi sulla struttura dell'URL, questo è meno nello spirito intenzionale delle cose.

48
2018-01-11 17:18



Entrambi sono usati per la trasmissione dei dati tra client e server, ma ci sono sottili differenze tra loro, che sono:

Enter image description here

Analogia:

  • MESSO, quindi prendi e PUT
  • POST come inviare posta nell'ufficio postale.

enter image description here


41
2017-09-11 13:12