¿Qué ofrece HATEOAS para descubrir y desacoplar además de la capacidad de cambiar su estructura de URL más o menos libremente?

62

Últimamente he estado leyendo sobre Hypermedia como el motor del estado de la aplicación (HATEOAS), la restricción que se dice que hace que una API web sea "realmente RESTful". Se reduce básicamente a incluir enlaces con cada respuesta a las posibles transiciones que puede realizar desde el estado actual.

Permítame ilustrar lo que HATEOAS se basa en mi comprensión, y corríjame si me perdí algo.

/
    GET: {
        "_links": {
            "child": [
                { "href": "http://myapi.com/articles", "title": "articles" }
            ]
        }
    }

/articles?contains=HATEOAS
    GET: {
        "_items": [
            { "uri": "http://myapi.com/articles/0", "title": "Why Should I Care About HATEOAS?" },
            { "uri": "http://myapi.com/articles/1", "title": "HATEOAS: Problem or Solution?" }
        ],
        "_links": {
            "self": { "href": "http://myapi.com/articles", "title": "articles" },
            "parent": { "href": "http://myapi.com/", "title": "home" }
        }
    }

    POST: {
        "title": "A New Article",
        "body": "Article body",
        "tags": [ "tag1", "tag2" ]
    }

/articles/0
    GET: {
        "title": "Why Should I Care About HATEOAS?",
        "body": "Blah blah blah"
        "tags": [ "REST", "HATEOAS" ],
        "_links": {
            "self": { "href": "http://myapi.com/articles/0", "title": "article" },
            "parent": { "href": "http://myapi.com/articles", "title": "articles" }
        }
    }

Se afirma que HATEOAS proporciona dos beneficios principales:

  1. Se puede descubrir todo el servicio a partir del URI raíz, ya no se necesita documentación.

  2. El cliente está desacoplado del servidor que ahora puede cambiar la estructura de URI libremente. Esto elimina la necesidad de versiones de API.

Pero en mi opinión, un servicio es mucho más que su estructura URI. Para usarlo de manera efectiva, también necesita saber:

  • qué parámetros de consulta puede usar y sus posibles valores
  • la estructura de JSON / XML / cualquier documento que necesite enviar en sus solicitudes POST / PATCH / etc.
  • La estructura de la respuesta enviada por el servidor
  • los posibles errores que pueden ocurrir
  • ...

Basado en lo anterior, HATEOAS solo resuelve una pequeña fracción de los problemas de descubrimiento y acoplamiento. Todavía necesita documentar los cuatro aspectos anteriores y los clientes aún estarán fuertemente acoplados al servidor debido a ellos. Para evitar romper clientes, aún necesita versionar su API.

El único beneficio que proporciona es que puede cambiar su estructura de URL más o menos libremente (por cierto, ¿qué pasó con el principio "Los URI geniales no cambian" ?). ¿Es correcto mi entendimiento?

Botá Balázs
fuente

Respuestas:

47

Creo que tus instintos son en gran medida correctos; esos beneficios proclamados realmente no son tan buenos, ya que para cualquier aplicación web no trivial los clientes tendrán que preocuparse por la semántica de lo que están haciendo, así como la sintaxis.

¡Pero eso no significa que no deba hacer que su aplicación siga los principios de HATEOAS!

¿Qué significa realmente HATEOAS ? Significa estructurar su aplicación para que, en principio, sea como un sitio web , y que todas las operaciones que desee realizar puedan ser descubiertas sin tener que descargar un esquema complejo. (Los sofisticados esquemas WSDL pueden cubrir todo, pero para cuando lo hacen, han excedido la capacidad de casi todos los programadores de entender, ¡y mucho menos escribir! Puede ver a HATEOAS como una reacción contra tal complejidad).

HATEOAS no solo significa enlaces ricos. Significa usar los mecanismos de error del estándar HTTP para indicar más exactamente qué salió mal; no tienes que responder simplemente con "¡waaah! no "y en su lugar puede proporcionar un documento que describa lo que realmente estuvo mal y lo que el cliente podría hacer al respecto. También significa admitir cosas como las solicitudes OPTIONS (la forma estándar de permitir que los clientes descubran qué métodos HTTP pueden usar) y la negociación del tipo de contenido para que el formato de la respuesta pueda adaptarse a un formulario que los clientes puedan manejar. Significa poner un texto explicativo(o, más probablemente, enlaces a él) para que los clientes puedan buscar cómo usar el sistema en casos no triviales si no lo saben; el texto explicativo puede ser legible por humanos o por máquina (y puede ser tan complejo como desee). Finalmente, significa que los clientes no sintetizan enlaces (excepto los parámetros de consulta); los clientes solo usarán un enlace si se lo dijiste.

Debe pensar en que el sitio sea navegado por un usuario (que puede leer JSON o XML en lugar de HTML, un poco extraño) con una gran memoria para enlaces y un conocimiento enciclopédico de los estándares HTTP, pero por lo demás no sabe qué hacer. hacer.

Y, por supuesto, puede usar la negociación de tipo de contenido para entregar un cliente HTML (5) / JS que les permitirá usar su aplicación, si eso es lo que su navegador está dispuesto a aceptar. Después de todo, si su API RESTful es buena, ¿debería ser "trivial" implementarla?

Compañeros de Donal
fuente
6

La cuestión es que HATEOAS debe venir con un segundo pilar que defina qué es una API RESTful: tipo de medio estandarizado. Roy mismo se dijo

Una API REST debería dedicar casi todo su esfuerzo descriptivo a definir los tipos de medios utilizados para representar los recursos ".

Con un tipo de medio estandarizado que define la transición explícitamente y el hipertexto para apuntar recursos entre sí, puede crear un gráfico de recursos que puede tomar cualquier forma sin romper ningún cliente. Al igual que el trabajo web, realmente: tienes un enlace entre el documento, y el documento está escrito en HTML que define cómo seguir esos enlaces. <a href>es un GET, <form>es GET o POST (y define la plantilla de URL para usar en caso de GET), <link type="text/css">es GET ... etc. Así es como los navegadores pueden navegar por páginas HTML estructuradas arbitrarias y la Web.

Todo el punto que hiciste

  • qué parámetros de consulta puede usar y sus posibles valores
  • la estructura de JSON / XML / cualquier documento que necesite enviar en sus solicitudes POST / PATCH / etc.
  • La estructura de la respuesta enviada por el servidor
  • los posibles errores que pueden ocurrir

Son puntos que deben ser abordados por la definición de su tipo de medio estandarizado . Por supuesto, esto es mucho más difícil, y no es algo en lo que la mayoría de la gente piensa cuando define una API "REST". No puede simplemente tomar sus entidades comerciales e insertar sus atributos en un documento JSON para tener una API RESTful.

Por supuesto, lo que sucedió es que REST se diluyó de alguna manera para que significara "usar HTTP en lugar de una complicada cosa SOAPy". Solo usar HTTP e HyperText no es suficiente para RESTAR, esto es lo que la mayoría de la gente se equivoca.

No es que esto sea necesariamente algo malo: REST sacrifica el rendimiento y facilita el desarrollo a cambio de una capacidad de mantenimiento y evolutividad a largo plazo. Fue hecho para una gran integración de aplicaciones empresariales. Una pequeña API web con estructura JSON codificada puede ser lo que necesita. Simplemente no lo llame REST, es una API web ad-hoc, nada más. Y eso no significa que apesta, solo significa que no intenta seguir la restricción de REST.

Otras lecturas

Espero que esta ayuda aclare un poco :)

Laurent Bourgault-Roy
fuente
2

Hay algunos formatos de Hypermedia que se esfuerzan por proporcionar respuestas más completas que incluyen más información sobre qué tipo de solicitudes enviar, y no hay nada que le impida enriquecer la respuesta con aún más información.

Aquí hay un ejemplo de documento de Siren :

{
  "class": [ "order" ],
  "properties": { 
      "orderNumber": 42, 
      "itemCount": 3,
      "status": "pending"
  },
  "entities": [
    {
      "class": [ "info", "customer" ],
      "rel": [ "http://x.io/rels/customer" ], 
      "properties": { 
        "customerId": "pj123",
        "name": "Peter Joseph"
      },
      "links": [
        { "rel": [ "self" ], "href": "http://api.x.io/customers/pj123" }
      ]
    }
  ],
  "actions": [
    {
      "name": "add-item",
      "title": "Add Item",
      "method": "POST",
      "href": "http://api.x.io/orders/42/items",
      "type": "application/x-www-form-urlencoded",
      "fields": [
        { "name": "orderNumber", "type": "hidden", "value": "42" },
        { "name": "productCode", "type": "text" },
        { "name": "quantity", "type": "number" }
      ]
    }
  ],
  "links": [
    { "rel": [ "self" ], "href": "http://api.x.io/orders/42" },
    { "rel": [ "previous" ], "href": "http://api.x.io/orders/41" },
    { "rel": [ "next" ], "href": "http://api.x.io/orders/43" }
  ]
}

Como puede ver, actionsen el mensaje se proporciona información acerca de cómo llamar relacionado , y luego al interpretar esta información, el cliente se vuelve más resistente al cambio.

Se vuelve particularmente poderoso si los rels son URI que se pueden buscar, en lugar de un vocabulario fijo.

mcintyre321
fuente
0

¿Dónde leyó que "ya no se necesita documentación" para los servicios de HATEAOS? Como usted dice, aún necesita documentar la semántica de los enlaces. Sin embargo, con HATEOAS no necesita documentar y, por lo tanto, conservar para siempre la estructura de la mayoría de los URI.

HATEOAS permite que un implementador de servicios modifique y escale la implementación de manera significativa y eficiente sin cambiar un pequeño conjunto de URI de los que depende el cliente. Es más fácil mantener un pequeño número de puntos de entrada sin cambios que un conjunto grande. Por lo tanto, reducir el número de puntos de entrada públicos al servicio y proporcionar dinámicamente enlaces a recursos secundarios (HATEOAS) en realidad es compatible con "Los URI geniales no cambian" mejor que los servicios que no son HATEOAS.

Jonathan Giddy
fuente
Un lugar donde se puede leer que "ya no se necesita documentación" es la disertación de Roy Fielding, quien acuñó el término.
meriton - en huelga
1
Acabo de buscar en la disertación de Fielding usos de "documentación" y no encontré nada parecido a la declaración "ya no se necesita documentación". ¿Puede indicar dónde encontró este reclamo en la disertación de Fielding?
Jonathan Giddy
0

(HATEOAS), la restricción que se afirma que hace que una API web sea "verdaderamente RESTful"

Lo único que lo convierte en una verdadera API REST es cumplir con todas las restricciones, no solo una.

Pero en mi opinión, un servicio es mucho más que su estructura URI. Para usarlo de manera efectiva, también necesita saber: ...

Es por eso que necesitamos otras restricciones, mensajes autodescriptivos, etc.

Para evitar romper clientes, aún necesita versionar su API.

No importa cómo lo intentes, necesitarás versionar tu API. En un cliente REST, aún necesita saber cómo llegar a una página donde desea hacer cosas, qué enlaces seguir y qué propiedades debe recopilar en función del vocabulario RDF que describe el mensaje. Si necesita reemplazar o eliminar algo de ese vocabulario, probablemente romperá a todos sus clientes y necesitará una nueva versión. Así que creo que REST no es algo que debas publicar antes (y descifrar el modelo mientras cambias constantemente la API), de lo contrario tendrás muchas versiones. Primero necesita un modelo de dominio estable en el que pueda construir ...

inf3rno
fuente