sta usando un PUT con effetti collaterali accettabili (REST)

8

Voglio creare una cronologia di annullamento ogni volta che l'utente aggiorna un modulo. Perché è un aggiornamento, voglio usare una richiesta PUT. Tuttavia, ho letto che PUT non deve avere effetti collaterali .

È accettabile usare PUT qui? Ci sono alternative migliori?

PUT /person/F02E395A235

{
   time: 1234567,
   fields: {
      name: 'John',
      age: '41'
   }
}

Nel server

doPut('person/:personId',
   // create a new person snapshot
)

Modifica:

La cronologia sarà visibile all'utente, la chiamata più volte comporterebbe più versioni.

La soluzione era verificare se la versione fosse unica prima di crearla.

    
posta roo2 05.12.2013 - 14:16
fonte

3 risposte

9

Le persone che redassero HTTP / 2 erano molto più prolisse riguardo alle loro idee su cosa avrebbe dovuto fare HTTP, pur mantenendo il vecchio significato. Vediamo cosa ha da dire la specifica della bozza HTTP / 2 su idempotence:

4.2.2. Idempotent Methods

A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.Of the request methods defined by this specification, PUT, DELETE, and safe request methods are idempotent.

Like the definition of safe, the idempotent property only applies to what has been requested by the user; a server is free to log each request separately, retain a revision control history, or implement other non-idempotent side-effects for each idempotent request.

L'effetto voluto sul server per ciascuna di queste richieste PUT è di aggiornare la risorsa identificata da quell'URI . Questo è esattamente ciò che accade nel tuo caso.

Il fatto che tu decida di utilizzare le risorse delle versioni non ha molta importanza qui. Se non vuoi creare una nuova versione quando nulla è cambiato, dovrai confrontare il carico utile nella richiesta PUT con la versione più recente (o altrimenti identificata) della risorsa e quando nessuna delle proprietà è cambiata puoi scegliere non creare una nuova versione .

La tua modifica:

The history will be visible to the user, calling multiple times would result in multipleversions

Per quanto riguarda la risorsa, non c'è un effetto collaterale . La risorsa di quell'URI non cambia (le stesse proprietà ottengono PUT). La cronologia è solo metadata, poiché molto probabilmente è richiesta da un URI differente o con diverse intestazioni di richiesta.

    
risposta data 05.12.2013 - 15:14
fonte
10

HTTP distingue tra due proprietà:

  • idempotenza
  • Sicurezza

L'idempotenza è definita dalla specifica come segue:

Methods can also have the property of "idempotence" in that (aside from error or expiration issues) the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.

E sicurezza:

In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe". This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested.

Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature. The important distinction here is that the user did not request the side-effects, so therefore cannot be held accountable for them.

Si noti che la sicurezza implica l'idempotenza: se un metodo non ha effetti collaterali, eseguirlo più volte produrrà lo stesso effetto collaterale di una volta, vale a dire nessuno.

Questo pone i metodi in tre categorie:

  • sicuro (e quindi anche idempotente): GET , HEAD , OPTION , TRACE
  • idempotente ma non necessariamente sicuro: PUT , DELETE
  • né idempotente né sicuro: POST

PUT needs to have no side affects.

Questo è sbagliato. PUT è idempotente ma non sicuro. Il punto intero di PUT ha un effetto collaterale, ovvero l'aggiornamento di una risorsa. Ciò che significa idempotenza è che l'aggiornamento della stessa risorsa con gli stessi contenuti più volte dovrebbe avere lo stesso effetto dell'aggiornamento solo una volta.

Nota l'ultimo paragrafo nella sezione sulla sicurezza [enfasi sul mio]:

Naturally, it is not possible to ensure that the server does not generate side-effects as a result of performing a GET request; in fact, some dynamic resources consider that a feature. The important distinction here is that the user did not request the side-effects, so therefore cannot be held accountable for them.

Sebbene questa frase parli di GET e sicurezza, possiamo presumere che gli autori intendessero anche applicare lo stesso ragionamento a PUT e idempotency. IOW: PUT dovrebbe avere solo un effetto collaterale visibile all'utente , ovvero l'aggiornamento della risorsa denominata. potrebbe avere altri effetti collaterali, ma l'utente non può essere ritenuto responsabile per loro.

Ad esempio, il fatto che PUT sia idempotente significa che posso riprovare tutte le volte che voglio: la specifica garantisce che eseguirla più volte sarà esattamente la stessa cosa che eseguirla una volta . È perfettamente valido creare un backlog di vecchie revisioni come un effetto collaterale di quelle richieste multiple PUT . Tuttavia, se, come risultato di più tentativi, il tuo database si riempie con un arretrato di vecchie revisioni, non è un mio problema, è tuo.

IOW: ti è permesso avere tanti effetti collaterali quanti vuoi, ma

  1. deve guardare all'utente come se le sue richieste fossero idempotenti
  2. sei responsabile di quegli effetti collaterali, non dell'utente
risposta data 05.12.2013 - 15:36
fonte
1

Hai ragione che PUT non deve avere effetti collaterali , tuttavia vorrei aggiungere qualcosa a questo.

PUT needs to have no side affects on the resource for which that PUT operation is being performed

Stai aggiornando una risorsa person che è identificata come F02E395A235 , quindi l'uso di PUT è corretto. Ora come regola aziendale, tieni traccia delle modifiche che sono invisibili all'entità chiamante (consumatore del servizio REST). Questo non aggiungerà un nuovo elemento nella risorsa person . L'istantanea storica non sarà accessibile utilizzando l'endpoint /person/ . Quindi, credo, PUT dovrebbe essere perfettamente accettabile in questo caso.

    
risposta data 05.12.2013 - 14:58
fonte

Leggi altre domande sui tag