Eliminar un recurso usando http DELETE

123

Entonces, dado que el verbo DELETE en Http es idempotente, cuando publico la siguiente solicitud, ¿qué debería pasar con el segundo (o tercero, o cuarto, etc.)?

DELETE /person/123

La primera vez, el recurso se elimina y devuelvo un 204 (exitoso, sin contenido). ¿Debo devolver un 204 en llamadas posteriores o un 404 (no encontrado)?

Craig Wilson
fuente

Respuestas:

153

Como las solicitudes HTTP en un sistema sin estado deberían ser independientes, los resultados de una solicitud no deberían depender de una solicitud anterior. Considere lo que debería suceder si dos usuarios hicieron una ELIMINACIÓN en el mismo recurso simultáneamente. Tiene sentido que la segunda solicitud obtenga un 404. Lo mismo debería ser cierto si un usuario realiza dos solicitudes.

Supongo que tener DELETE devolver dos respuestas diferentes no te parece idempotente. Me resulta útil pensar que las solicitudes idempotentes dejan el sistema en el mismo estado y no necesariamente tienen la misma respuesta. Por lo tanto, independientemente de si ELIMINA un recurso existente o si intenta ELIMINAR un recurso que no existe, el estado del recurso del servidor es el mismo.

Darrel Miller
fuente
44
Gracias. Eso tiene mucho sentido. De hecho, estaba pensando en idempotente como devolver la misma respuesta.
Craig Wilson
44
@ Craig ¡Cuidado! En el libro de cocina, Subbu contradice completamente lo que acabo de decir. Él dice que la idempotencia significa que debería devolver la misma respuesta. Afortunadamente, Subbu estará en RESTFest, así que voy a aclarar con él allí.
Darrel Miller
57
Si ELIMINA algo que no existe, debería devolver un 204 (incluso si el recurso nunca existió). El cliente quería que el recurso se fuera y se fue. Devolver un 404 es exponer un procesamiento interno que no es importante para el cliente y dará como resultado una condición de error innecesaria.
Brian
9
@DarrelMiller Supongo que el concepto clave aquí es que no debes usar DELETE para verificar si existe un recurso, primero usarías GET para eso. Luego, si la respuesta es 200, realizarías una BORRADO; de lo contrario, ni siquiera te molestes en hacer eso. Así que creo que tiene sentido devolver siempre un 204 en DELETE.
manei_cc
10
@Brian El RFC dice que se supone que debe comportarse como rm. rmdevuelve un error si no existe. tools.ietf.org/html/rfc7231#section-4.3.5
Dax Fohl el
32

El libro de cocina de servicios web RESTful es un gran recurso para esto. Por casualidad, su vista previa de Google muestra la página sobre ELIMINAR (página 11):

El método DELETE es idempotente. Esto implica que el servidor debe devolver el código de respuesta 200 (OK) incluso si el servidor eliminó el recurso en una solicitud anterior. Pero en la práctica, la implementación de DELETE como una operación idempotente requiere que el servidor realice un seguimiento de todos los recursos eliminados. De lo contrario, puede devolver un 404 (no encontrado).

yves amsellem
fuente
Sí, eso parece un gran recurso. Sin embargo, la sección ELIMINAR no se está deteniendo para mí (es la página 23 y la vista previa tiene eso redactado). ¿Has leído este libro? ¿Sabes la respuesta a mi pregunta?
Craig Wilson
Este libro es imprescindible para construir REST (habla en particular, no en un idioma).
yves amsellem
77
@ Craig Al leer el libro de cocina, dice que DEBERÍA devolver 200 OK incluso si ya lo ha eliminado. Sin embargo, en la práctica eso requeriría que el servidor rastree todos los recursos eliminados, por lo tanto, PUEDE usar 404. Continúa diciendo que las preocupaciones de seguridad pueden requerir que siempre devuelva 404. Página 11.
Darrel Miller
+1 Segundo y recomiendo el libro para diseñar servicios RESTful.
Paul DelRe
18
Bueno, el libro está mal. La idempotencia no implica que el código de estado sea el mismo. Lo relevante es el estado final del servidor.
Julian Reschke
13

Estoy de acuerdo con lo que dice la respuesta elegida actual, que la 2da (y 3ra, 4ta, ...) BORRAR debería obtener un 404 . Y noté que la respuesta tiene 143 votos positivos, pero también tiene un comentario opuesto que tiene 54 votos positivos, por lo que la comunidad se divide en 2 campos en una proporción aproximada de 3: 1. Aquí viene más información para resolver este largo debate.

  1. En primer lugar, NO comencemos con lo que "yo" pienso, lo que "tú" piensas o lo que piensa otro autor del libro. Comencemos con las especificaciones HTTP, es decir, RFC 7231.

    • RFC 7231, sección 4.3.5 DELETE solo mencionó que una respuesta exitosa debería ser 2xx, pero no mencionó lo que obtendría un DELETE posterior. Así que profundicemos más.
    • RFC 7231, sección 6.5.4 404 No encontrado dice que la respuesta 404 es para un recurso que no existe. Dado que ningún método http específico (en particular, no ELIMINAR) se llama para ser tratado de otra manera, intuitivamente podemos tener una impresión (y con razón) de que mi solicitud DELETE /some/resource/which/does/not/existdebe dar como resultado un 404. Luego,DELETE /some/resource/which/happened/to/be/removed/by/someone/else/five/days/ago podría devolver un 404 Entonces, ¿por qué debería DELETE /some/resource/i/deleted/five/seconds/agoser diferente? "¡¿Pero qué hay de la idempotencia ?!", puedo escuchar que estás gritando eso. Espera, estamos a punto de entrar en eso.
    • Históricamente, RFC 2616, publicado en 1999, era la especificación HTTP 1.1 más referenciada. Lamentablemente, su descripción sobre la idempotencia fue vaga , lo que deja espacio para todos estos debates. Pero esas especificaciones han sido reemplazadas por RFC 7231. Citado de RFC 7231, sección 4.2.2 Métodos idempotentes , énfasis mío:

      Un método de solicitud se considera "idempotente" si el EFECTO pretendido 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 los métodos de solicitud seguros son idempotentes .

      Entonces, está escrito en las especificaciones, la idempotencia se trata del efecto en el servidor. El primer DELETE que devuelve un 204 y luego el DELETE posterior que devuelve 404, un código de estado diferente NO hace que el DELETE sea no idempotente. Usar este argumento para justificar un retorno 204 posterior es simplemente irrelevante.

  2. Bien, entonces no se trata de idempotencia. Pero entonces una pregunta de seguimiento puede ser, ¿qué pasa si todavía elegimos usar 204 en la SUPRIMACIÓN posterior? ¿Está bien?

    Buena pregunta. La motivación es comprensible: permitir que el cliente alcance el resultado deseado, sin preocuparse por el manejo de errores. Yo diría que devolver 204 en DELETE posterior, es una "mentira piadosa" del lado del servidor en gran parte inofensiva, que el lado del cliente no notará inmediatamente una diferencia. Es por eso que hay ~ 25% de personas haciendo eso en la naturaleza y aparentemente todavía funciona. Solo tenga en cuenta que dicha mentira puede considerarse semánticamente extraña, porque GET /non-existdevuelve 404 pero DELETE /non-existda 204, en ese momento el cliente descubriría que su servicio no cumple completamente con la sección 6.5.4 404 No encontrado .

    Pero quiero señalar que, la forma prevista por RFC 7231, es decir, devolver 404 en DELETE posterior, no debería ser un problema en primer lugar. Tres veces más desarrolladores decidieron hacer eso, ¿alguna vez escuchaste un incidente importante o una queja causada por un cliente que no puede manejar 404? Presumiblemente, no, y eso se debe a que cualquier cliente decente que implemente HTTP DELETE (o cualquier método HTTP, para el caso), no asumiría ciegamente que el resultado siempre sería exitoso 2xx. Y luego, una vez que el desarrollador comience a considerar el manejo de errores, 404 Not Found sería uno de los primeros errores que se le ocurra. En ese punto, él / ella probablemente sacaría una conclusión de que, es semánticamente seguro para una operación DELETE HTTP ignorar un error 404. Y lo hicieron así.

Problema resuelto.

RayLuo
fuente
2
+1 "la idempotencia se trata del efecto en el servidor". Meticulosamente respondió. ¡Bien hecho! Soy un creyente 404 para las solicitudes posteriores de BORRAR.
nwayve
11

Primer BORRAR : 200 o 204.

DELETES posteriores : 200 o 204.

Justificación : ELIMINAR debe ser idempotente. Si devuelve 404 en un segundo DELETE, su respuesta cambiará de un código de éxito a un código de error . El programa cliente puede tomar acciones incorrectas en base a la suposición de que DELETE falló.

Ejemplo :

  • Suponga que su operación DELETE es parte de una operación de varios pasos (o una "saga") ejecutada por el programa cliente.
  • El programa cliente puede ser una aplicación móvil que realice una transacción bancaria, por ejemplo.
  • Digamos que el programa cliente tiene un reintento automático para una operación DELETE (tiene sentido, porque DELETE se supone que es idempotente).
  • Digamos que el primer DELETE se ejecutó con éxito, pero la respuesta 200 se perdió en su camino hacia el programa cliente.
  • El programa cliente reintentará ELIMINAR.
  • Si el segundo intento devuelve 404, el programa cliente puede cancelar la operación general debido a este código de error.
  • Pero debido a que el primer DELETE se ejecutó con éxito en el servidor, el sistema puede quedar en un estado inconsistente .
  • Si el segundo intento devuelve 200 o 204, el programa cliente continuará como se esperaba.

Solo para ilustrar el uso de este enfoque, la guía de estilo HTTP API para PayPal tiene la siguiente directriz:

ELIMINAR: Este método DEBE devolver el código de estado 204 ya que no hay necesidad de devolver ningún contenido en la mayoría de los casos, ya que la solicitud es eliminar un recurso y se eliminó con éxito.

Como el método DELETE también DEBE ser idempotente, DEBE devolver 204, incluso si el recurso ya se ha eliminado. Por lo general, al consumidor de API no le importa si el recurso se eliminó como parte de esta operación o antes. Esta es también la razón por la cual 204 en lugar de 404 deben ser devueltos.

Paulo Merson
fuente
1
La pregunta es, qué es importante para el cliente, que se elimina el recurso, o que el recurso ha sido eliminado. ¿Qué pasa si algún otro cliente eliminó el recurso durante la saga? ¿Realmente quiere fracasar teniendo en cuenta que se ha logrado el objetivo del cliente?
Darrel Miller
1
@DarrelMiller Buen punto. Lo más importante depende del contexto empresarial. Pero en general, prefiero devolver 204 en un segundo intento de BORRAR, incluso si el recurso fue eliminado por otro cliente. No quiero que el servicio falle (es decir, 404) dado que se logró el objetivo del cliente.
Paulo Merson
2
Como otros mencionaron, la idempotencia no es el código de respuesta, sino el estado del servidor.
Niranjan
@Niranjan Estoy de acuerdo en que la idempotencia se trata del estado del servidor, pero un código de respuesta diferente puede llevar al cliente a cambiar el estado del servidor innecesariamente al cancelar una saga en curso.
Paulo Merson
@Paulo Merson, ¿qué código devolverá si el cliente solicita la eliminación de un elemento que NUNCA existió? 204? o 404? Si siempre devuelve 204, ¿cuál es el punto de verificar el código de retorno?
frenchone