http - restful - servicios rest buenas practicas
Alternativas RESTful para ELIMINAR cuerpo de solicitud (4)
A pesar de algunas recomendaciones de no utilizar el cuerpo del mensaje para las solicitudes DELETE, este enfoque puede ser apropiado en ciertos casos de uso. Este es el enfoque que utilizamos después de evaluar las otras opciones mencionadas en las preguntas / respuestas y después de colaborar con los consumidores del servicio.
Si bien el uso del cuerpo del mensaje no es ideal, tampoco ninguna de las otras opciones encajaba perfectamente. El cuerpo de solicitud DELETE nos permitió agregar semántica fácil y claramente alrededor de datos / metadatos adicionales que se necesitaban para acompañar a la operación DELETE.
Todavía estaría abierto a otros pensamientos y discusiones, pero quería cerrar el círculo sobre esta cuestión. ¡Aprecio los pensamientos y discusiones de todos sobre este tema!
Si bien la especificación HTTP 1.1 parece permitir cuerpos de mensaje en las solicitudes DELETE , parece indicar que los servidores deberían ignorarla ya que no hay una semántica definida para ella.
4.3 Cuerpo del mensaje
Un servidor DEBERÍA 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 DEBERÍA ser ignorado al manejar la solicitud.
Ya he revisado varias discusiones relacionadas sobre este tema en SO y más allá, tales como:
- ¿Se permite el cuerpo de una entidad para una solicitud HTTP DELETE?
- Carga de los métodos de solicitud HTTP
- HTTP GET con cuerpo de solicitud
La mayoría de las discusiones parecen coincidir en que se puede permitir el envío de un cuerpo de mensaje a un DELETE, pero generalmente no se recomienda.
Además, he notado una tendencia en varias bibliotecas de clientes HTTP en las que cada vez más mejoras parecen registrarse para que estas bibliotecas admitan cuerpos de solicitud en DELETE. La mayoría de las bibliotecas parecen obligar, aunque ocasionalmente con un poco de resistencia inicial.
Mi caso de uso requiere la adición de algunos metadatos necesarios en un DELETE (por ejemplo, el "motivo" para la eliminación, junto con algunos otros metadatos necesarios para su 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 de mensaje en DELETE no tienen ningún valor semántico; no totalmente compatible con clientes HTTP; no es una práctica estándar
- Encabezados HTTP personalizados : requerir encabezados personalizados generalmente es contrario a 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 : no son adecuados los encabezados estándar
- Parámetros de consulta : la adición de parámetros de consulta realmente cambia el URI de solicitud que se elimina; 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 borrar metadatos, luego DELETE) divide una operación atómica en dos, lo que puede dejar un estado incoherente. El motivo de eliminación (y otros metadatos relacionados) no son parte de la representación del recurso en sí.
Mi primera preferencia probablemente sea utilizar el cuerpo del mensaje, en segundo lugar a los encabezados HTTP personalizados; sin embargo, como se indicó, hay algunas desventajas de estos enfoques.
¿Existen recomendaciones o mejores prácticas en línea con los estándares REST / HTTP para incluir dichos metadatos requeridos en las solicitudes DELETE? ¿Hay alguna otra alternativa que no haya considerado?
Dada la situación que tiene, tomaría uno de los siguientes enfoques:
- Enviar un PUT o PATCH : deduzco que la operación de eliminación es virtual, por la naturaleza de necesitar una razón de eliminación. Por lo tanto, creo que actualizar el registro a través de una operación PUT / PATCH es un enfoque válido, aunque no es una operación DELETE per se.
- Use los parámetros de consulta : el uri de recursos no se cambia. De hecho, creo que este es también un enfoque válido. La pregunta que enlazó estaba hablando de no permitir la eliminación si el parámetro de consulta faltaba. En su caso, solo tendré un motivo predeterminado si el motivo no está especificado en la cadena de consulta. El recurso seguirá siendo
resource/:id
. Puede hacer que sea reconocible con encabezados de enlace en el recurso por cada razón (con una etiquetarel
en cada uno para identificar el motivo). - Use un punto final separado por cada razón : usando una url como
resource/:id/canceled
. Esto realmente cambia el Request-URI y definitivamente no es RESTful. Nuevamente, los encabezados de los enlaces pueden hacer que esto sea detectable.
Recuerde que REST no es ley o dogma. Piénsalo más como una guía. Entonces, cuando tiene sentido no seguir la guía para su dominio de problema, no lo haga. Solo asegúrese de que sus consumidores API estén informados de la variación.
Lo que pareces querer es una de dos cosas, ninguna de las cuales es un DELETE
puro:
- Tiene dos operaciones, una
PUT
de la razón de eliminación seguida de unDELETE
del recurso. Una vez eliminado, el contenido del recurso ya no es accesible para nadie. La ''razón'' no puede contener un hipervínculo al recurso eliminado. O, - Está intentando modificar un recurso de
state=active
astate=deleted
utilizando el métodoDELETE
. Los recursos con estado = eliminado son ignorados por su API principal, pero aún pueden ser leíbles para un administrador o alguien con acceso a la base de datos. Esto está permitido:DELETE
no tiene que 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 solicitud DELETE
se puede desglosar en su más general, un POST
para realizar todas las tareas necesarias con el cuerpo del mensaje y un DELETE
. No veo ninguna razón para romper la semántica de HTTP.
Sugiero que incluya los metadatos necesarios como parte de la jerarquía de URI. 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 forma que pase la información requerida como parte del URI.
p.ej
DELETE /entries/range/01012012/31122012
- Borre todas las entradas entre el 1 de enero de 2012 y el 31 de diciembre de 2012
Espero que esto ayude.