Tenemos una URL en el siguiente formato
/ instance / {instanceType} / {instanceId}
Puede llamarlo con los métodos HTTP estándar: POST, GET, DELETE, PUT. Sin embargo, hay algunas acciones más que tomamos como "Guardar como borrador" o "Conservar"
Pensamos que podríamos usar métodos HTTP personalizados como: DRAFT, VALIDATE, CURATE
Creo que esto es aceptable ya que las normas dicen
"El conjunto de métodos comunes para HTTP / 1.1 se define a continuación. Aunque este conjunto se puede ampliar, no se puede suponer que métodos adicionales compartan la misma semántica para clientes y servidores extendidos por separado".
Y herramientas como WebDav crean algunas de sus propias extensiones.
¿Hay problemas que alguien haya tenido con métodos personalizados? Estoy pensando en servidores proxy y firewalls, pero cualquier otra área de interés es bienvenida. ¿Debo permanecer en el lado seguro y solo tener un parámetro de URL como action = validate | curate | draft?
Respuestas:
Una de las limitaciones fundamentales de HTTP y la característica de diseño central de REST es una interfaz uniforme proporcionada por (entre otras cosas) un conjunto pequeño y fijo de métodos que se aplican universalmente a todos los recursos. La restricción de interfaz uniforme tiene una serie de ventajas y desventajas. Cito de Fielding generosamente aquí.
Una interfaz uniforme:
Por otro lado, una interfaz uniforme:
Las compensaciones están "diseñadas para el caso común de la Web" y han permitido construir un gran ecosistema que proporciona soluciones a muchos de los problemas comunes en las arquitecturas web. Adherirse a una interfaz uniforme permitirá que su sistema se beneficie de este ecosistema, mientras que romperlo lo dificultará. Es posible que desee usar un equilibrador de carga como nginx, pero ahora solo puede usar un equilibrador de carga que comprenda DRAFT y CURATE. Es posible que desee usar una capa de caché HTTP como Varnish, pero ahora solo puede usar una capa de caché HTTP que entienda DRAFT y CURATE. Es posible que desee pedir ayuda a alguien para solucionar un error del servidor, pero nadie más conoce la semántica de una solicitud CURATE. Puede ser difícil cambiar sus bibliotecas preferidas de cliente o servidor para comprender e implementar correctamente los nuevos métodos. Y así.
La forma correcta * de representar esto es como una transformación de estado en el recurso (o recursos relacionados). No DRAFT una publicación, transforma su
draft
estadotrue
o crea undraft
recurso que contiene los cambios y enlaces a versiones preliminares anteriores. No CURATE una publicación, transforma sucurated
estadotrue
o crea uncuration
recurso que vincula la publicación con el usuario que la seleccionó.* Correcto porque sigue más de cerca los principios arquitectónicos REST.
fuente
Preferiría diseñar estos como subrecursos, en los que realiza una solicitud POST.
Considere que tiene un recurso en
/instance/type/1
, me gustaría que la representación de ese recurso transmita un par de enlaces a 'acciones' que se pueden realizar en el recurso, como/instance/type/1/draft
y/instance/type/1/curate
. En JSON, esto podría ser tan simple como:Esto permite que el cliente sea muy explícito acerca de lo que debe suceder, durante la solicitud POST al enlace proporcionado por el
curate
miembro. El recurso publicado allí podría incluir argumentos que detallen el evento que, tal vez, infligiría una transición de estado.Seguir el enfoque 'ingenuo' de moverse entre los posibles estados en un recurso tiene la desventaja de no capturar qué eventos condujeron a estas transiciones.
Las transiciones de estado generalmente ocurren en respuesta a eventos específicos, y prefiero capturar esos eventos que dejar que el cliente decida que algo está ahora en un "estado" específico. También hace que la validación sea mucho más difícil. Además, no podrá capturar ningún 'argumento' a menos que también describa los del estado mismo. Y luego todo se vuelve desagradable cuando algunos códigos cambian aquellos sin transición de estado real, y se requiere la validación, y todo se convierte rápidamente en un desastre.
fuente
/vms/some-id
devuelve enlaces a acciones comoPOST /vms/some-id/restart
y lo usamos para determinar si las acciones deben habilitarse o deshabilitarse. Tengo una relación de amor / odio con HATEOAS :)Creo que el método HTTP personalizado es la mejor manera de implementar acciones de entidad. Agregar la acción al cuerpo de la entidad (POST) no parece correcto, no es parte de su entidad (aunque el resultado podría guardarse en él). Además, el uso de proxies de métodos HTTP personalizados podría determinar sus acciones sin la necesidad de analizar el cuerpo de la entidad.
Es como CRUD, siempre querrás implementarlos, pero también tienes tu propio conjunto específico de acciones (por entidad). Realmente no veo cuál sería el problema para extenderlos.
También @Rein Henrichs "No DIBUJAS una publicación, transformas su estado borrador en verdadero o creas un recurso borrador" me parece falso. Se
drafts
usaría una propiedad para guardar el estado de forma persistente, no para realizar la transformación. Las acciones ni siquiera resultan necesariamente en un 'estado' o se guardan en una propiedad. Crear una entidad separada para cada estado / transformación parece aún más confuso ... intente mantener la misma referencia (URI) a la entidad.fuente