Si bien la especificación HTTP 1.1 parece permitir cuerpos de mensaje en solicitudes DELETE , parece indicar que los servidores deben ignorarla ya que no hay una semántica definida para ella.
4.3 Cuerpo del mensaje
Un servidor DEBE leer y reenviar el cuerpo de un mensaje en cualquier solicitud; si el método de solicitud no incluye la semántica definida para un cuerpo de entidad, entonces el cuerpo del mensaje DEBE ignorarse al manejar la solicitud.
Ya revisé varias discusiones relacionadas sobre este tema en SO y más allá, como:
- ¿Se permite un cuerpo de entidad para una solicitud HTTP DELETE?
- Cargas útiles de métodos de solicitud HTTP
- HTTP GET con cuerpo de solicitud
La mayoría de las discusiones parecen coincidir en que se puede permitir proporcionar un cuerpo de mensaje en un DELETE , pero generalmente no se recomienda.
Además, he notado una tendencia en varias bibliotecas de cliente HTTP en las que parece que se registran más y más mejoras para que estas bibliotecas admitan los cuerpos de solicitud en DELETE. La mayoría de las bibliotecas parecen complacer, aunque ocasionalmente con un poco de resistencia inicial.
Mi caso de uso requiere la adición de algunos metadatos requeridos en un DELETE (por ejemplo, el "motivo" de la eliminación, junto con algunos otros metadatos necesarios para la eliminación). He considerado las siguientes opciones, ninguna de las cuales parece completamente apropiada y en línea con las especificaciones HTTP y / o las mejores prácticas de REST:
- Cuerpo del mensaje : la especificación indica que los cuerpos del mensaje en DELETE no tienen valor semántico; no es totalmente compatible con los clientes HTTP; no es una práctica estándar
- Encabezados HTTP personalizados : exigir encabezados personalizados generalmente va en contra de las prácticas estándar ; usarlos es inconsistente con el resto de mi API, ninguno de los cuales requiere encabezados personalizados; Además, no hay una buena respuesta HTTP disponible para indicar valores de encabezado personalizados incorrectos (probablemente una pregunta separada por completo)
- Encabezados HTTP estándar : ningún encabezado estándar es apropiado
- Parámetros de consulta : agregar parámetros de consulta en realidad cambia el URI de solicitud que se está eliminando; contra las prácticas estándar
- Método POST : (por ejemplo
POST /resourceToDelete { deletemetadata }
) POST no es una opción semántica para eliminar; POST en realidad representa la acción opuesta deseada (es decir, POST crea subordinados de recursos; pero necesito eliminar el recurso) - Múltiples métodos : dividir la solicitud DELETE en dos operaciones (por ejemplo, PUT delete metadata, luego DELETE) divide una operación atómica en dos, dejando potencialmente un estado inconsistente. El motivo de la eliminación (y otros metadatos relacionados) no forman parte de la representación del recurso en sí.
Mi primera preferencia probablemente sería usar el cuerpo del mensaje, después de los encabezados HTTP personalizados; sin embargo, como se indicó, existen algunas desventajas en estos enfoques.
¿Existen recomendaciones o mejores prácticas en línea con los estándares REST / HTTP para incluir tales metadatos requeridos en las solicitudes DELETE? ¿Existen otras alternativas que no he considerado?
fuente
Jersey
no permiten el cuerpo para lasdelete
solicitudes.Respuestas:
A pesar de algunas recomendaciones de no usar el cuerpo del mensaje para las solicitudes DELETE, este enfoque puede ser apropiado en ciertos casos de uso. Este es el enfoque que terminamos usando después de evaluar las otras opciones mencionadas en la pregunta / respuestas, y luego de colaborar con los consumidores del servicio.
Si bien el uso del cuerpo del mensaje no es ideal, ninguna de las otras opciones encajaba perfectamente. El cuerpo de la solicitud DELETE nos permitió agregar semántica de manera fácil y clara alrededor de datos / metadatos adicionales que se necesitaban para acompañar la operación DELETE.
Todavía estaría abierto a otros pensamientos y discusiones, pero quería cerrar el círculo sobre esta pregunta. ¡Agradezco los pensamientos y discusiones de todos sobre este tema!
fuente
Lo que parece querer es una de dos cosas, ninguna de las cuales es pura
DELETE
:PUT
del motivo de eliminación seguida de unaDELETE
del recurso. Una vez eliminado, el contenido del recurso ya no es accesible para nadie. El 'motivo' no puede contener un hipervínculo al recurso eliminado. O,state=active
astate=deleted
mediante elDELETE
método. Los recursos con estado = eliminado son ignorados por su API principal, pero aún pueden ser leídos por un administrador o alguien con acceso a la base de datos. Esto está permitido:DELETE
no es necesario borrar los datos de respaldo de un recurso, solo para eliminar el recurso expuesto en ese URI.Cualquier operación que requiera un cuerpo de mensaje en una
DELETE
solicitud se puede dividir en su forma más general, unaPOST
para hacer todas las tareas necesarias con el cuerpo del mensaje y unaDELETE
. No veo ninguna razón para romper la semántica de HTTP.fuente
PUT
razón tiene éxito y losDELETE
recursos fallan? ¿Cómo se puede prevenir el estado inconsistente?Dada la situación que tiene, tomaría uno de los siguientes enfoques:
resource/:id
. Puede hacerlo visible con encabezados de enlace en el recurso por cada motivo (con unarel
etiqueta en cada uno para identificar el motivo).resource/:id/canceled
. En realidad, esto cambia el Request-URI y definitivamente no es RESTful. Nuevamente, los encabezados de los enlaces pueden hacer que esto sea detectable.Recuerde que el DESCANSO no es ley ni dogma. Piense en ello más como una guía. Entonces, cuando tenga sentido no seguir la guía para el dominio de su problema, no lo haga. Solo asegúrese de que sus consumidores de API estén informados de la variación.
fuente
/orders/:id
devolvería el mismo recurso que/orders/:id?exclude=orderdetails
. La cadena de consulta solo da pistas al servidor, en este caso para excluir los detalles del pedido en la respuesta (si es compatible). De manera similar, si envía DELETE a/orders/:id
o/orders/:id?reason=canceled
o/orders/:id?reason=bad_credit
, todavía está actuando sobre el mismo recurso subyacente. Para mantener una 'interfaz uniforme', tendría una razón predeterminada para que no sea necesario enviar el parámetro de consulta./foo?123
significa que está eliminando un recurso diferente que si tuviera que enviar DELETE a/foo?456
.Le sugiero que incluya los metadatos necesarios como parte de la jerarquía de URI en sí. Un ejemplo (ingenuo):
Si necesita eliminar entradas basadas en un rango de fechas, en lugar de pasar la fecha de inicio y la fecha de finalización en el cuerpo o como parámetros de consulta, estructure el URI de tal manera que pase la información requerida como parte del URI.
p.ej
DELETE /entries/range/01012012/31122012
- Eliminar todas las entradas entre el 1 de enero de 2012 y el 31 de diciembre de 2012Espero que esto ayude.
fuente
range
especificado en los parámetros de consulta o la carga útil, que es la esencia de esta pregunta: para comprender el enfoque de las mejores prácticas para el problema, que yo diría que no es este.