POST e PUT richieste - è solo la convenzione?

6

Ho letto parecchi articoli sulla differenza tra POST e PUT e in quando i due dovrebbero essere usati. Ma ci sono ancora poche cose che mi confondono (si spera che le domande abbiano un senso):

1) Dovremmo usare PUT per creare risorse quando vogliamo che i client specifichino l'URI delle risorse appena create e dovremmo usare POST per creare risorse quando lasciamo che il servizio generi l'URI delle risorse appena create .

a) È solo per convenzione che POST create request non contiene un URI della risorsa appena creata o La richiesta di creazione POST in realtà non può contenere l'URI della risorsa appena creata ?

b) PUT ha una semantica idempotente e quindi può essere tranquillamente utilizzato per aggiornamenti assoluti (cioè inviamo l'intero stato della risorsa al server), ma non anche per gli aggiornamenti relativi (cioè inviamo solo modifiche allo stato della risorsa ), poiché ciò violerebbe la sua semantica.

Tuttavia, suppongo che sia ancora possibile per PUT inviare aggiornamenti relativi al server, è solo che in tal caso l' aggiornamento PUT non sarà idempotente?

2) Ho letto da qualche parte che dovremmo " utilizzare POST per aggiungere una risorsa a una raccolta identificata da un URI generato dal servizio ".

a) Che cosa significa esattamente? Che se gli URI per le risorse fossero generati da un server (quindi le risorse sono state create tramite POST), allora TUTTE le risorse successive dovrebbero anche essere create tramite POST? Quindi, in tale situazione nessuna risorsa dovrebbe essere creata tramite PUT?

b) Se la mia ipotesi in a) è corretta, potresti elaborare il motivo per cui non dovremmo creare alcune risorse tramite POST e alcune tramite PUT (supponendo che il server contenga già una raccolta di risorse create tramite POST)?

    
posta bckpwrld 03.06.2014 - 19:39
fonte

3 risposte

15

Leggi le specifiche HTTP che definiscono quei metodi. Sul serio. Farà chiarezza su molte domande per il futuro.

link

  • In HTTP, PUT è specificamente il metodo di creazione / aggiornamento. Crea se non esiste o aggiornalo se lo fa.

  • POST è una sorta di metodo di presa. Come ha detto Roy Fielding, è il metodo da usare quando non vuoi generalizzare la tua operazione.

Il loro utilizzo è stato suddiviso in questo modo nei servizi RESTish:

  • Di solito, creare è caduto nel campo POST, a causa dell'idea di "accodare ad una collezione". È diventato il modo di aggiungere una risorsa a un elenco di risorse.

Tuttavia, il POST è anche il metodo di "elaborazione dati", quindi è applicabile anche a QUALSIASI ALTRO CHE VUOI FARE. Se vuoi guidare una nave da battaglia attraverso una feritoia in REST, usa POST.

Nel complesso, il POST è utile per la creazione, perché puoi dire "elaborare questo (dati incompleti) e aggiungerlo a questa risorsa lista".

  • La semantica di PUT è molto più specifica. PUT è il metodo "make it so". Quindi se hai una rappresentazione completa e un URL completo, allora lo metti e "fallo così". Se non esiste già, il servizio lo creerà.

Quindi, sì, sia PUT che POST possono essere appropriati per la creazione. Anche per l'aggiornamento, potresti POSTARE un pezzo di dati per la risorsa da elaborare. Non è possibile disegnare una definizione a linee luminose tra CREATE / UPDATE e PUT / POST.

Ho visto molte persone provare a mappare in modo esplicito CRUD ai metodi HTTP, ma si rompe sempre, perché a) HTTP segue un modello di "aggiornamento o creazione" e non un modello di creazione e aggiornamento separato, e b) l'ampiezza del POST è così grande. Inoltre, ci sono sottigliezze nel modo in cui i dati vengono elaborati che CRUD manca - come la generazione di identificatori.

...

Ad esempio, supponiamo che l'Accademia di polizia di Galactic abbia un servizio REST. Hanno una risorsa Cadet & Puoi ottenere un cadetto con il loro casco # per i dettagli del servizio.

GET http://galacticpoliceacademy/cadets/12345

Tutti i Cadetti sono un'altra risorsa che recupera un elenco o una collezione di cadetti:

GET http://galacticpoliceacademy/cadets/

Si noti che il singolo GET aggiunge solo informazioni alla risorsa di raccolta.

Ora, se vengo accettato alla Galactic Police Academy, non ho ancora il mio casco #, quindi pubblicheremo le mie informazioni alla collezione .

POST http://galacticpoliceacademy/cadets/

{ info: "my info" }

Che elaborerà le mie informazioni, assegnarmi un numero di casco e aggiungermi alla raccolta. Ora la collezione di cadetti ha 1 altro oggetto (cioè io), e posso ottenere i miei dettagli usando il mio # casco appena assegnato. Posso anche tirare la lista dei cadetti, e io sarò lì nella lista.

  • Alcuni cadetti si trasferiscono dalla Milizia di Frontiera Provvisoria e hanno già i propri elmetti. Possono essere semplicemente inseriti nella raccolta /cadets/ direttamente, poiché hanno già un numero di casco. I numeri del casco sono unici, quindi non entrano in collisione con un altro cadetto, e saranno semplicemente messi direttamente nell'elenco, così com'è.

  • (!) Se l'asteroide su cui è accorsa l'accademia viene fatto saltare in aria dai criminali spaziali, e abbiamo bisogno di ricostruire un nuovo asteroide, allora potrei mettere una copia della lista esistente, o mettere un record per ognuno dei sopravvissuti, e alla fine avrei una lista di cadetti che sembra esattamente come i dati che ho. Quindi potrei iniziare il POSTing mentre riempio i ranghi.

  • C'è un'ondata di patriottismo dopo l'attacco all'Academy, che ha comportato un gran numero di nuove reclute. Possiamo POSTARE un elenco di nuovi reclutati (senza elmetti) e il servizio New Academy aggiungerà ciascuno alla lista e assegnerà a ciascuno di loro un casco #.

Quindi il tuo esempio di 10/11 elementi in una raccolta di risorse è corretto - questo è il comportamento corretto. Di solito non mischio PUT e POST per creare una particolare risorsa, ma la semantica HTTP lo consente.

    
risposta data 03.06.2014 - 20:03
fonte
2

Ho fatto una domanda quasi identica here

Spring REST segue il tuo modello (PUT = id risorsa fornita dal cliente). Ma ammettono che è stato un dibattito serio. Fare riferimento alle specifiche non è abbastanza buono. Non è chiaro su questo problema (o almeno, abbastanza chiaro).

Per quanto riguarda gli aggiornamenti parziali, la mia comprensione è che, per quelli, dovresti usare il comando PATCH

    
risposta data 03.06.2014 - 22:47
fonte
2

È necessario considerare la distinzione tra standard / specifiche e linee guida.

Standard / specifiche:

La conformità alle specifiche è prevista e assunta dalla maggior parte dei browser e di altri client. Gestiscono le richieste assumendo che le specifiche siano valide. Alcune di queste "regole" sono specificate qui: Hypertext Transfer Protocol . La specifica HTTP va più nel dettaglio - una lettura consigliata per chiunque stia sviluppando web.

Ad esempio, per le specifiche HTTP, i browser presumono che GET non avrebbe effetti collaterali e quindi memorizza nella cache la maggior parte delle richieste GET per salvare larghezza di banda e chiamate al server. PUT è pensato per essere idempotente, quindi i browser sono autorizzati a ripetere le chiamate PUT senza alcuna conferma da parte degli utenti finali (non così per i POST).

Non seguire questi standard è ovviamente possibile, ma potresti rompere il comportamento dei client conformi e probabilmente causare bug difficili da tracciare.

Linee guida / Convenzioni:

L'altra parte che citi sono le linee guida. Vengono utilizzati per uniformità e per assicurarsi che altre persone possano capire / seguire facilmente la tua API. La mappatura delle chiamate da CRUD a REST che menzioni, è una di queste linee guida. Non affronta tutti gli scenari, a volte può essere una cattiva progettazione, ma è ancora un'astrazione utile se usata con giudizio.

Quindi la mappatura tipica è la seguente:

GET è un metodo idempotente che non dovrebbe richiedere un payload di input, ma solo parametri di query. Quindi viene solitamente utilizzato per le query e le operazioni di lettura sul server.

PUT è anche idempotente, ma può assumere un corpo di payload. Quindi, la sua semantica è usata per fare una sostituzione completa / aggiornamento di una risorsa. Se si ripete la chiamata, non vi è alcun cambiamento perché è comunque una sostituzione completa. PUT può anche essere associato a una creazione in cui il client ha specificato l'id della nuova risorsa. Ad esempio, puoi inserire il seguente indirizzo con i dettagli dell'utente nel corpo:

PUT http://www.example.com/users/<new_user_id>
{
    ...
}

Questo dovrebbe ancora essere implementato come idempotente - una chiamata ripetuta creerebbe lo stesso utente con lo stesso id, in pratica nessun cambiamento effettivo.

PATCH è una nuova aggiunta alle specifiche HTTP. Può essere utilizzato per inviare modifiche parziali e unirle sul server. Questo non ha ancora un'adozione diffusa ma dovrebbe essere la strada da percorrere.

POST è più un metodo generico di "tutto il resto". Non ha restrizioni come essere idempotente. In molti casi, è mappato alla creazione di sottorisorse. Ad esempio, puoi POSTARE i dettagli di un utente al seguente URL per farti creare un nuovo utente:

POST http://www.example.com/users
{
    ...
}

La convenzione è che il server crea l'id utente e te lo restituisce. Successivamente, puoi accedere all'utente creato con:

GET http://www.example.com/users/<created_user_id>
    
risposta data 04.06.2014 - 03:34
fonte

Leggi altre domande sui tag