está utilizando un PUT con efectos secundarios aceptables (REST)

9

Quiero crear un historial de deshacer siempre que el usuario actualice un formulario. Debido a que es una actualización, quiero usar una solicitud PUT. Sin embargo, leí que PUT no debe tener efectos secundarios .

¿Es aceptable usar PUT aquí? ¿Hay mejores alternativas?

PUT /person/F02E395A235

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

En el servidor

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

Editar:

El historial será visible para el usuario, llamar varias veces resultaría en múltiples versiones.

La solución fue verificar si la versión era única antes de crearla.

roo2
fuente

Respuestas:

11

Las personas que redactaron HTTP / 2 fueron mucho más detalladas sobre sus ideas de lo que HTTP debería hacer, mientras conservaban el significado anterior. Veamos qué dice el borrador HTTP / 2 sobre la idempotencia:

4.2.2 Métodos idempotentes

Un método de solicitud se considera "idempotente" si el efecto deseado en el servidor de múltiples solicitudes idénticas con ese método es el mismo que el efecto de una sola solicitud de este tipo. De los métodos de solicitud definidos por esta especificación, PUT, DELETE y solicitud segura Los métodos son idempotentes.

Al igual que la definición de caja fuerte, la propiedad idempotente solo se aplica a lo que ha solicitado el usuario; un servidor es libre de registrar cada solicitud por separado, retener un historial de control de revisión o implementar otros efectos secundarios no idempotentes para cada solicitud idempotente .

El efecto previsto en el servidor para cada solicitud PUT de este tipo es actualizar el recurso identificado por ese URI . Esto es exactamente lo que sucede en su caso.

Que decidas versionar recursos realmente no importa aquí. Si no desea crear una nueva versión cuando nada ha cambiado, deberá comparar la carga útil en la solicitud PUT con la versión más reciente (o identificada) del recurso, y cuando ninguna de las propiedades ha cambiado puedes elegir no crear una nueva versión .


Tu edición:

El historial será visible para el usuario, llamar varias veces daría como resultado múltiples versiones

En lo que respecta al recurso, eso no es un efecto secundario . El recurso en ese URI no cambia (las mismas propiedades obtienen PUT). El historial es solo metadatos, ya que probablemente lo solicite un URI diferente o con diferentes encabezados de solicitud.

CodeCaster
fuente
Excepto porque responde a mi problema específico: "¿es aceptable que PUT cree un historial visible para el usuario", y
deme
¿Para qué problema es esa una solución? ¿Que la timepropiedad se actualiza? Creo que también son metadatos, aunque estén en el recurso.
CodeCaster
1
El problema era que si se enviaban múltiples PUT, el usuario obtendría un largo historial de deshacer con información redundante. comprobar la unicidad resuelve eso
roo2
12

HTTP distingue entre dos propiedades:

  • Idempotencia
  • La seguridad

La idempotencia se define por la especificación de la siguiente manera:

Los métodos también pueden tener la propiedad de " idempotencia " en que (aparte de los problemas de error o caducidad) los efectos secundarios de N> 0 solicitudes idénticas son las mismas que para una solicitud única. Los métodos GET, HEAD, PUTy DELETEcomparten esta propiedad. Además, los métodos OPTIONSy TRACE NO DEBEN tener efectos secundarios, por lo que son inherentemente idempotentes.

Y seguridad:

En particular, se ha establecido que la convención GETy los HEADmétodos NO DEBEN tener la importancia de tomar una acción que no sea la recuperación. Estos métodos deben considerarse " seguros ". Esto permite a los agentes de usuario representar otros métodos, como POST, PUTy DELETE, de manera especial, para que el usuario sea consciente del hecho de que se está solicitando una acción posiblemente insegura.

Naturalmente, no es posible garantizar que el servidor no genere efectos secundarios como resultado de realizar una GETsolicitud; de hecho, algunos recursos dinámicos lo consideran una característica. La distinción importante aquí es que el usuario no solicitó los efectos secundarios, por lo tanto, no puede ser considerado responsable de ellos.

Tenga en cuenta que la seguridad implica idempotencia: si un método no tiene efectos secundarios, realizarlo varias veces producirá el mismo efecto secundario que realizarlo una vez, es decir, ninguno.

Esto pone los métodos en tres categorías:

  • caja de seguridad (y por tanto también idempotente): GET, HEAD, OPTION,TRACE
  • idempotente pero no necesariamente segura: PUT,DELETE
  • ni idempotente ni seguro: POST

PUT no debe tener efectos secundarios.

Eso está mal. PUTes idempotente pero no seguro. El punto entero de PUTes tener un efecto secundario, es decir, la actualización de un recurso. Lo que significa idempotencia es que actualizar el mismo recurso con el mismo contenido varias veces debería tener el mismo efecto que actualizarlo solo una vez.

Tenga en cuenta el último párrafo en la sección sobre seguridad [énfasis mío]:

Naturalmente, no es posible garantizar que el servidor no genere efectos secundarios como resultado de realizar una GETsolicitud; de hecho, algunos recursos dinámicos lo consideran una característica. La distinción importante aquí es que el usuario no solicitó los efectos secundarios, por lo tanto, no puede ser considerado responsable de ellos .

Aunque esta oración habla de GETseguridad, podemos suponer que los autores también tenían la intención de aplicar el mismo razonamiento PUTe idempotencia. IOW: PUTdebe tener solo un efecto secundario visible para el usuario , es decir, actualizar el recurso nombrado. Se puede tener otros efectos secundarios, pero el usuario no puede ser considerado responsable de los mismos.

Por ejemplo, el hecho de que PUTsea ​​idempotente significa que puedo volver a intentarlo tantas veces como quiera: la especificación garantiza que ejecutarlo varias veces será exactamente lo mismo que ejecutarlo una vez. Es perfectamente válido crear una acumulación de revisiones antiguas como efecto secundario de esas PUTsolicitudes múltiples . Sin embargo, si, como resultado de múltiples reintentos, su base de datos se llena con una acumulación de revisiones antiguas, ese no es mi problema, es suyo.

IOW: puedes tener tantos efectos secundarios como quieras, pero

  1. debe mirar al usuario como si sus solicitudes fueran idempotentes
  2. usted es responsable de esos efectos secundarios, no el usuario
Jörg W Mittag
fuente
Sí, la idempotencia se trata del estado del recurso que se está poniendo, no de cualquier otro estado del servidor / servicio que se vea afectado por el acto del PUT.
Marjan Venema
Voto a favor de una gran explicación, de seguridad e idempotencia en Rest
roo2
Gran explicación Sin embargo, hace varias declaraciones como esta: "El objetivo de PUT es tener un efecto secundario, es decir, actualizar un recurso". Eso parece una contradicción a menos que se refiera a algo diferente por el término "efecto secundario" que "algo secundario o no intencional que ocurre además del efecto primario deseado".
MarredCheese
@MarredCheese: estoy usando el término en su significado de programación estándar, que básicamente significa "cualquier 'resultado' que no sea el valor de retorno".
Jörg W Mittag
Ah, por supuesto. Gracias por la aclaración.
MarredCheese
1

Tienes razón en que PUT no debe tener efectos secundarios , sin embargo, agregaría algo a esto.

PUT no debe tener efectos secundarios en el recurso para el que se realiza esa operación PUT

Está actualizando un personrecurso que se identifica como F02E395A235, por lo que usar PUT es correcto. Ahora, como regla comercial, también realiza un seguimiento de los cambios que son invisibles para la entidad que realiza la llamada (consumidor del servicio REST). Esto no agregará un nuevo elemento en el personrecurso. La instantánea histórica no será accesible utilizando el /person/punto final. Así que creo, PUT debería ser perfectamente aceptable en este caso.

Aziz Shaikh
fuente
1
No hay efectos secundarios en el recurso que se está utilizando, pero cualquier número de efectos secundarios en otras cosas (contadores, registros, seguimientos de auditoría, ...) son perfectamente aceptables.
Marjan Venema