Al emitir una solicitud DELETE HTTP, el URI de la solicitud debe identificar completamente el recurso a eliminar. Sin embargo, ¿está permitido agregar metadatos adicionales como parte del cuerpo de la entidad de la solicitud?
Al emitir una solicitud DELETE HTTP, el URI de la solicitud debe identificar completamente el recurso a eliminar. Sin embargo, ¿está permitido agregar metadatos adicionales como parte del cuerpo de la entidad de la solicitud?
Respuestas:
La especificación no lo prohíbe o desalienta explícitamente, por lo que tendería a decir que está permitido.
Microsoft lo ve de la misma manera (puedo escuchar murmullos en la audiencia), declaran en el artículo de MSDN sobre el Método DELETE del Marco de Servicios de Datos ADO.NET :
Si una solicitud DELETE incluye un cuerpo de entidad, el cuerpo se ignora [...]
Además, esto es lo que RFC2616 (HTTP 1.1) tiene que decir con respecto a las solicitudes:
Content-Length
o Transfer-Encoding
(sección 4.3)Para las respuestas, esto se ha definido:
La última actualización de la especificación HTTP 1.1 ( RFC 7231 ) permite explícitamente un cuerpo de entidad en una solicitud DELETE:
Una carga útil dentro de un mensaje de solicitud DELETE no tiene semántica definida; enviar un cuerpo de carga útil en una solicitud DELETE puede causar que algunas implementaciones existentes rechacen la solicitud.
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
lo que viene con una advertencia de compatibilidad con versiones anteriores, sugiere que el siguiente estándar dirá: '¡sí! DELETE
puede tener un cuerpo ».
A payload within a DELETE request message has no defined semantics
. Entonces el cuerpo está permitido.
Algunas versiones de Tomcat y Jetty parecen ignorar el cuerpo de una entidad si está presente. Lo que puede ser una molestia si pretendía recibirlo.
Una razón para usar el cuerpo en una solicitud de eliminación es para un control de concurrencia optimista.
Has leído la versión 1 de un registro.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Su colega lee la versión 1 del registro.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Su colega cambia el registro y actualiza la base de datos, que actualiza la versión a 2:
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
Intenta eliminar el registro:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
Debería obtener una excepción de bloqueo optimista. Vuelva a leer el registro, vea que es importante y tal vez no lo elimine.
Otra razón para usarlo es eliminar varios registros a la vez (por ejemplo, una cuadrícula con casillas de selección de filas).
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
Tenga en cuenta que cada mensaje tiene su propia versión. Tal vez pueda especificar múltiples versiones usando múltiples encabezados, pero por George, esto es más simple y mucho más conveniente.
Esto funciona en Tomcat (7.0.52) y Spring MVC (4.05), posiblemente también en versiones anteriores:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
If-Unmodified-Since
o Etag
para eso están).
Me parece que RFC 2616 no especifica esto.
De la sección 4.3:
La presencia de un cuerpo de mensaje en una solicitud se señala mediante la inclusión de un campo de encabezado Content-Length o Transfer-Encoding en los encabezados de mensaje de la solicitud. Un cuerpo de mensaje NO DEBE incluirse en una solicitud si la especificación del método de solicitud (sección 5.1.1) no permite enviar un cuerpo de entidad en las solicitudes. Un servidor DEBE leer y reenviar un cuerpo de mensaje en cualquier solicitud; si el método de solicitud no incluye una semántica definida para un cuerpo de entidad, entonces el cuerpo del mensaje DEBE ignorarse al manejar la solicitud.
Y la sección 9.7:
El método DELETE solicita que el servidor de origen elimine el recurso identificado por el URI de solicitud. Este método PUEDE ser anulado por intervención humana (u otro medio) en el servidor de origen. No se puede garantizar al cliente que la operación se haya llevado a cabo, incluso si el código de estado devuelto por el servidor de origen indica que la acción se ha completado con éxito. Sin embargo, el servidor NO DEBE indicar éxito a menos que, en el momento en que se dé la respuesta, tenga la intención de eliminar el recurso o moverlo a una ubicación inaccesible.
Una respuesta exitosa DEBE ser 200 (OK) si la respuesta incluye una entidad que describe el estado, 202 (Aceptada) si la acción aún no se ha promulgado, o 204 (Sin contenido) si la acción se ha promulgado pero la respuesta no incluye una entidad.
Si la solicitud pasa a través de un caché y el URI de solicitud identifica una o más entidades actualmente en caché, esas entradas DEBERÍAN tratarse como obsoletas. Las respuestas a este método no se pueden almacenar en caché.
Por lo tanto, no está explícitamente permitido o no permitido, y existe la posibilidad de que un proxy en el camino elimine el cuerpo del mensaje (aunque DEBE leerlo y reenviarlo).
Solo un aviso, si proporciona un cuerpo en su solicitud DELETE y está utilizando un equilibrador de carga HTTPS de Google Cloud, rechazará su solicitud con un error 400. Estaba golpeándome la cabeza contra la pared y descubrí que Google, por cualquier razón, piensa que una solicitud ELIMINAR con un cuerpo es una solicitud con formato incorrecto.
for whatever reason
- porque la especificación lo dice: P
DELETE
es lo último.
Parece que ElasticSearch usa esto: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
Lo que significa que Netty admite esto.
Como se menciona en los comentarios, puede que ya no sea el caso
Roy Fielding en la lista de correo HTTP aclara que en la lista de correo http https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html y dice:
El cuerpo GET / DELETE tiene absolutamente prohibido tener algún impacto en el procesamiento o interpretación de la solicitud.
Esto significa que el cuerpo no debe modificar el comportamiento del servidor. Luego agrega:
además de la necesidad de leer y descartar los bytes recibidos para mantener el marco del mensaje.
Y finalmente, la razón para no prohibir el cuerpo:
La única razón por la que no prohibimos enviar un cuerpo es porque eso llevaría a implementaciones perezosas suponiendo que no se enviaría ningún cuerpo.
Entonces, si bien los clientes pueden enviar el cuerpo de la carga útil, los servidores deben descartarlo y las API no deben definir una semántica para el cuerpo de la carga útil en esas solicitudes.
Esto no está definido .
Una carga útil dentro de un mensaje de solicitud DELETE no tiene semántica definida; enviar un cuerpo de carga útil en una solicitud DELETE puede causar que algunas implementaciones existentes rechacen la solicitud.
https://tools.ietf.org/html/rfc7231#page-29
Usar DELETE con un cuerpo es arriesgado ... Prefiero este enfoque para Operaciones de lista en lugar de REST:
Operaciones regulares
OBTENER / objetos / Obtiene todos los objetos
GET / object / ID Obtiene un objeto con ID especificado
POST / objetos agrega un nuevo objeto
PUT / object / ID Agrega un objeto con la ID especificada, actualiza un objeto
DELETE / object / ID Elimina el objeto con la ID especificada
Todas las acciones personalizadas son POST
POST / objects / addList Agrega una lista o matriz de objetos incluidos en el cuerpo
POST / objects / deleteList Elimina una lista de objetos incluidos en el cuerpo
POST / objects / customQuery Crea una lista basada en una consulta personalizada en el cuerpo
Si un cliente no admite sus operaciones extendidas, puede trabajar de la manera habitual.
POST
no es una buena manera de RESTAR para crear nuevos recursos porque la semántica de las respuestas POST no está clara, especialmente en el contexto de los encabezados de Ubicación. Básicamente, está dejando atrás HTTP y apila RPC en la parte superior. La "forma HTTP / REST" adecuada es crear recursos utilizando PUT
w / el If-None-Match: *
encabezado (o especificando los métodos HTTP adecuados, ver MKCOL
etc.).
No creo que se haya publicado una buena respuesta a esto, aunque ha habido muchos comentarios excelentes sobre las respuestas existentes. Levantaré la esencia de esos comentarios a una nueva respuesta:
Este párrafo de RFC7231 ha sido citado varias veces, lo que lo resume.
Una carga útil dentro de un mensaje de solicitud DELETE no tiene semántica definida; enviar un cuerpo de carga útil en una solicitud DELETE puede causar que algunas implementaciones existentes rechacen la solicitud.
Lo que extrañé de las otras respuestas fue la implicación. Sí, se permite incluir un cuerpo en las DELETE
solicitudes, pero carece de sentido semántico. Lo que esto realmente significa es que emitir una DELETE
solicitud con un cuerpo de solicitud es semánticamente equivalente a no incluir un cuerpo de solicitud.
La inclusión de un cuerpo de solicitud no debería tener ningún efecto en la solicitud, por lo que nunca tiene sentido incluirla.
tl; dr: técnicamente DELETE
se permite una solicitud con un cuerpo de solicitud, pero nunca es útil hacerlo.
En caso de que alguien se encuentre con este problema, No, no es universalmente compatible.
Actualmente estoy probando con Sahi Pro y es muy evidente que una llamada http DELETE elimina todos los datos del cuerpo proporcionados (una gran lista de ID para eliminar en masa según el diseño del punto final).
Me he puesto en contacto con ellos varias veces y he enviado tres paquetes separados de secuencias de comandos, imágenes y registros para que los revisen y aún no lo han confirmado. Un parche fallido y llamadas de conferencia perdidas por su apoyo más tarde y todavía no he recibido una respuesta sólida.
Estoy seguro de que Sahi no es compatible con esto, y me imagino que muchas otras herramientas siguen la suite.
Podría ser la siguiente URL de GitHUb que te ayudará a obtener la respuesta. En realidad, el servidor de aplicaciones como Tomcat, Weblogic niega la llamada HTTP.DELETE con la carga útil de la solicitud. Entonces, teniendo en cuenta todas estas cosas, he agregado un ejemplo en github, por favor eche un vistazo a eso