Detección de tiempo de ejecución de API RESTful / diseño de cliente HATEOAS

79

Para una startup de SaaS en la que estoy involucrado, estoy construyendo una API web RESTful y un par de aplicaciones cliente en diferentes plataformas que la consumen. Creo que tengo la API resuelta, pero ahora me dirijo a los clientes. Mientras leía sobre REST, veo que una parte clave de REST es el descubrimiento , pero parece haber mucho debate entre dos interpretaciones diferentes de lo que realmente significa descubrimiento:

  1. Descubrimiento del desarrollador : el desarrollador codifica grandes cantidades de detalles de API en el cliente, como URI de recursos, parámetros de consulta, métodos HTTP compatibles y otros detalles que han descubierto al examinar los documentos y experimentar con las respuestas de la API. Este tipo de descubrimiento, en mi humilde opinión, necesita un enlace genial y la pregunta de control de versiones de la API, y conduce a un acoplamiento duro del código del cliente a la API. Parece que no es mucho mejor que usar una colección bien documentada de RPC.

  2. Descubrimiento en tiempo de ejecución : la aplicación cliente en sí misma es capaz de descubrir todo lo que necesita con poca o ninguna información fuera de banda (presumiblemente, solo un conocimiento de los tipos de medios con los que se ocupa la API). Los enlaces pueden ser candentes. Pero para que la API sea muy eficiente, parece que se necesitan muchas plantillas de enlaces para los parámetros de consulta, lo que hace que la información fuera de banda vuelva a aparecer. Es posible que haya otras dificultades en las que no he pensado todavía, ya que no he llegado a ese punto en el desarrollo. Pero me gusta la idea de un acoplamiento suelto.

El descubrimiento en tiempo de ejecución parece ser el santo grial de REST, pero veo muy poca discusión sobre cómo implementar tal cliente. Casi todas las fuentes REST que he encontrado parecen asumir el descubrimiento del desarrollador. ¿Alguien conoce algunos recursos de descubrimiento en tiempo de ejecución? ¿Mejores prácticas? ¿Ejemplos o bibliotecas con código real? Estoy trabajando en PHP (Zend Framework) para un cliente. Objective-C (iOS) para el otro.

¿Es el descubrimiento en tiempo de ejecución un objetivo realista, dado el conjunto actual de herramientas y conocimientos en la comunidad de desarrolladores? Puedo escribir a mi cliente para que trate todos los URI de una manera opaca, pero cómo hacerlo de manera más eficiente es una pregunta, especialmente en conexiones de bajo ancho de banda. De todos modos, las URI son solo una parte de la ecuación. ¿Qué pasa con las plantillas de enlaces en el contexto de tiempo de ejecución? ¿Qué tal comunicar qué métodos son compatibles, además de realizar muchas solicitudes de OPCIONES?

curtisdf
fuente
2
Solo un pequeño aparte en su referencia de OPCIONES. Puede usar el encabezado 'Permitir' para comunicar las operaciones de recursos permitidas fuera de una solicitud de OPCIONES. Roy Fielding llega tan lejos como para considerar el encabezado como una forma de hipertexto, ver aquí .
Paulkmoore
tats a gr8 question, las cuestiones clave se dan en la lista de métodos aplicables, ¿debería el cliente ser capaz de formar direcciones URL para la operación CRUD regular o se llamará "fuera de banda"? Digamos, si también proporcionamos enlaces para operaciones CRUD, ¿cómo se hacen "formularios" en json? Puede ser que si está utilizando tipos de medios específicos de la aplicación no necesita hacer "formularios", pero wat es la forma estándar de descubrir tipos de medios (es decir, el esquema json), el proceso de descubrimiento de esquemas se considerará no "fuera de banda "para clientes?
redzedi
xhtml se ve tan bien y fluido, pero si tienes que hacer json, supongo que ahora es bastante amorfo
redzedi

Respuestas:

19

Este es definitivamente un hueso duro de roer. En Google, hemos implementado nuestro Discovery Service con el que se construyen todas nuestras nuevas API. La versión TL; DR es que generamos una especificación similar a un esquema JSON que nuestros clientes pueden analizar, muchos de ellos de forma dinámica.

Ese resultado significa actualizaciones de SDK más fáciles para el desarrollador y un mantenimiento más fácil / mejor para nosotros.

De ninguna manera es la solución perfecta, pero a muchos de nuestros desarrolladores parece gustarles.

Consulte el enlace para obtener más detalles (y asegúrese de ver el video).

Jonathanberi
fuente
¿Existe algún estándar para implementar dicho servicio de descubrimiento para nuestras propias API?
Çağatay Gürtürk
12

Fascinante. Lo que está describiendo es básicamente el principio HATEOAS. ¿Qué es HATEOAS, preguntas? Lea esto: http://en.wikipedia.org/wiki/HATEOAS

En términos sencillos, HATEOAS significa seguimiento de enlace. Este enfoque desacopla a su cliente de URL específicas y le brinda la flexibilidad de cambiar su API sin dañar a nadie.

Sam
fuente
4

Uno de los requisitos que debe cumplirse antes de poder llamar a una API 'RESTful' es que debería ser posible escribir una aplicación de cliente genérica sobre esa API. Con el cliente genérico, un usuario debería poder acceder a todas las funciones de la API. Un cliente genérico es una aplicación de cliente que no asume que ningún recurso tenga una estructura específica más allá de la estructura definida por el tipo de medio. Por ejemplo, un navegador web es un cliente genérico que sabe cómo interpretar HTML, incluidos formularios HTML, etc.

Ahora, supongamos que tenemos una API HTTP / JSON para una tienda web y queremos crear un cliente HTML / CSS / JavaScript que brinde a nuestros clientes una excelente experiencia de usuario. ¿Sería una opción realista dejar que ese cliente sea un genérico? aplicación de cliente ? No. Queremos proporcionar una apariencia específica para cada elemento de datos específico y cada estado de aplicación específico. No queremos incluir todo el conocimiento sobre estos aspectos específicos de la presentación en la API, por el contrario, el cliente debe definir la apariencia y la API solo debe llevar los datos. Esto implica que el cliente tiene un acoplamiento codificado de elementos de recursos específicos con diseños e interacciones de usuario específicos.

¿Es este el final de HATEOAS y, por tanto, el final de REST? Sí y no .

, porque si codificamos el conocimiento sobre la API en el cliente, perdemos el beneficio de HATEOAS: los cambios del lado del servidor pueden romper el cliente.

No , por dos razones:

  1. Ser "RESTful" es una propiedad de la API, no del cliente. Siempre que sea posible, en teoría , construir un cliente genérico que ofrezca todas las capacidades de la API, la API se puede llamar RESTful. El hecho de que los clientes no obedezcan las reglas no es culpa de la API. El hecho de que un cliente genérico tenga una pésima experiencia de usuario no es un problema. ¿Por qué es importante saber que es posible tener un cliente genérico, si en realidad no tenemos ese cliente genérico? Esto me lleva a la segunda razón:
  2. Una API RESTful ofrece a los clientes la opción de elegir qué tan genéricos quieren ser, es decir, qué tan resistentes a los cambios del lado del servidor quieren ser. Los clientes que necesitan brindar una excelente experiencia de usuario pueden seguir siendo resistentes a los cambios de URI, a los cambios en los valores predeterminados y más. Los clientes que realizan trabajos por lotes sin la interacción del usuario pueden ser resistentes a otros tipos de cambios.

Si está interesado en ejemplos prácticos, consulte mi documento JAREST . La última sección trata sobre HATEOAS. Verá que con JAREST, incluso los clientes altamente interactivos y visualmente atractivos pueden ser bastante resistentes a los cambios del lado del servidor, aunque no al 100%.

www.admiraalit.nl
fuente
1

Creo que el punto importante sobre HATEOAS no es que sea un santo grial del lado del cliente, sino que aísla al cliente de los cambios de URI; se supone que está utilizando relaciones de enlace conocidas (o personalizadas descubiertas por el desarrollo) que permitirán al sistema saber qué enlace de un objeto es el formulario editable. El punto importante es utilizar un tipo emdia que sea compatible con hipermedia (por ejemplo, HTML, XHTML, etc.).

Falkayn
fuente
0

Usted escribe:

Para que la API sea muy eficiente, parece que se necesitan muchas plantillas de enlaces para los parámetros de consulta, lo que hace que la información fuera de banda vuelva a aparecer.

Si esa plantilla de enlace se proporciona en la solicitud anterior, entonces no hay información fuera de banda. Por ejemplo, un formulario de búsqueda HTML utiliza plantillas de enlaces ( /search?q=%@) para generar una URL ( /search?q=hateoas), pero el cliente (el navegador web) no sabe nada más que cómo utilizar formularios HTML y GET.

Nicholas Shanks
fuente
de hecho, no hay información fuera de banda: el cliente es responsable de expandir las plantillas de uri utilizando los datos de instancia / recurso proporcionados (y debe saber cómo hacerlo) - json-schema.org/latest/json-schema- hypermedia.html # anchor18
fusi