O que o HATEOAS oferece para descoberta e dissociação, além da capacidade de alterar sua estrutura de URL mais ou menos livremente?

62

Ultimamente, tenho lido sobre a Hipermídia como o Estado do Mecanismo de Aplicativo (HATEOAS), a restrição reivindicada para tornar uma API da Web "verdadeiramente RESTful". Tudo se resume a incluir basicamente links com todas as respostas às possíveis transições que você pode fazer a partir do estado atual.

Deixe-me ilustrar o que o HATEOAS é baseado no meu entendimento - e, por favor, corrija-me se eu perder alguma coisa.

/
    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" }
        }
    }

Alega-se que o HATEOAS oferece dois grandes benefícios:

  1. Todo o serviço pode ser iniciado a partir do URI raiz, a documentação não é mais necessária.

  2. O cliente é dissociado do servidor, que agora pode alterar livremente a estrutura do URI. Isso elimina a necessidade de versionamento da API.

Mas, na minha opinião, um serviço é muito mais do que sua estrutura de URI. Para usá-lo efetivamente, você também precisa saber:

  • quais parâmetros de consulta você pode usar e seus possíveis valores
  • a estrutura do JSON / XML / quaisquer documentos que você precise enviar em suas solicitações POST / PATCH / etc
  • a estrutura da resposta enviada pelo servidor
  • os possíveis erros que podem ocorrer
  • ...

Com base no exposto, o HATEOAS resolve apenas uma pequena fração dos problemas de descoberta e acoplamento. Você ainda precisa documentar os quatro aspectos acima e os clientes ainda estarão fortemente acoplados ao servidor por causa deles. Para evitar a quebra de clientes, você ainda precisa fazer a versão da sua API.

O único benefício que ele oferece é que você pode alterar sua estrutura de URL mais ou menos livremente (a propósito, o que aconteceu com o princípio "URIs legais não mudam" ?). Meu entendimento está correto?

Botond Balázs
fonte

Respostas:

47

Eu acho que seus instintos estão amplamente corretos; esses benefícios proclamados realmente não são tão bons assim, como em qualquer aplicativo da web não trivial, os clientes terão que se preocupar com a semântica do que estão fazendo, bem como com a sintaxe.

Mas isso não significa que você não deve fazer com que seu aplicativo siga os princípios do HATEOAS!

O que HATEOAS realmente significa? Significa estruturar seu aplicativo para que ele seja, em princípio, como um site , e que todas as operações que você queira fazer possam ser descobertas sem precisar fazer o download de um esquema complexo. (Esquemas sofisticados de WSDL podem cobrir tudo, mas, quando o fazem, eles excederam a capacidade de praticamente todos os programadores de entender, e muito menos escrever! Você pode ver o HATEOAS como uma reação contra essa complexidade.)

HATEOAS não significa apenas links avançados. Significa usar os mecanismos de erro do padrão HTTP para indicar mais exatamente o que deu errado; você não precisa apenas responder com “waaah! não ”e, em vez disso, pode fornecer um documento descrevendo o que realmente estava errado e o que o cliente poderia fazer a respeito. Significa também apoiar coisas como pedidos OPÇÕES (a maneira padrão de permitir que clientes para descobrir métodos que HTTP podem usar) e tipo de conteúdo negociação para que o formato da resposta pode ser adaptado a uma forma que os clientes podem lidar. Significa colocar texto explicativo(ou, mais provavelmente, links para ele) para que os clientes possam procurar como usar o sistema em casos não triviais, se não souberem; o texto explicativo pode ser legível por humanos ou legível por máquina (e pode ser tão complexo quanto você desejar). Finalmente, significa que os clientes não sintetizam links (exceto para parâmetros de consulta); os clientes usarão um link apenas se você tiver contado a eles.

Você precisa pensar em ter o site navegado por um usuário (que pode ler JSON ou XML em vez de HTML, um pouco estranho) com uma ótima memória para links e um conhecimento enciclopédico dos padrões HTTP, mas, de outra forma, nenhum conhecimento sobre o que Faz.

E, é claro, você pode usar a negociação de tipo de conteúdo para atender um cliente HTML (5) / JS que permitirá que eles usem seu aplicativo, se é isso que o navegador deles está preparado para aceitar. Afinal, se sua API RESTful é boa, isso deve ser "trivial" para ser implementado em cima dela?

Donal Fellows
fonte
6

A questão é que o HATEOAS deve vir com um segundo pilar que define o que é uma API RESTful: tipo de mídia padronizado. Roy colocando-se disse

Uma API REST deve gastar quase todo o seu esforço descritivo na definição dos tipos de mídia usados ​​para representar recursos ".

Com um tipo de mídia padronizado que define explicitamente a transição e um hipertexto para apontar um recurso para o outro, é possível criar um gráfico de recurso que pode assumir qualquer forma sem interromper nenhum cliente. Como o trabalho na Web, na verdade: você tem um link entre o documento e o documento é escrito em HTML que define como seguir esses links. <a href>é um GET, <form>é GET ou POST (e define o modelo de URL a ser usado no caso de GET), <link type="text/css">é GET ... etc. É assim que os navegadores podem navegar na página HTML estruturada arbitrária e na Web.

Todo o argumento que você fez

  • quais parâmetros de consulta você pode usar e seus possíveis valores
  • a estrutura do JSON / XML / quaisquer documentos que você precise enviar em suas solicitações POST / PATCH / etc
  • a estrutura da resposta enviada pelo servidor
  • os possíveis erros que podem ocorrer

São pontos que devem ser abordados pela definição do seu tipo de mídia padronizado . Obviamente, isso é muito mais difícil, e não é algo que a maioria das pessoas pensa quando define uma API "REST". Você não pode simplesmente levar suas entidades de negócios e inserir seus atributos em um documento JSON para ter uma API RESTful.

Obviamente, o que aconteceu foi que o REST foi diluído de alguma forma para significar "use HTTP em vez de algo SOAPy complicado". Apenas usar HTTP e HyperText não é suficiente para ser RESTful, é isso que a maioria das pessoas erra.

Não que isso seja uma coisa ruim: o REST sacrifica o desempenho e a facilidade de desenvolvimento em troca de manutenção e evolutividade a longo prazo. Foi desenvolvido para grande integração de aplicativos empresariais. Uma pequena API da web com estrutura JSON codificada pode ser o que você precisa. Só não chame isso de REST, é uma API da Web ad-hoc, nada mais. E isso não significa que seja péssimo, apenas significa que não tenta seguir a restrição do REST.

Leitura adicional

Espero que esta ajuda esclareça um pouco :)

Laurent Bourgault-Roy
fonte
2

Existem alguns formatos Hypermedia que se esforçam para fornecer respostas mais ricas, que incluem mais informações sobre que tipo de solicitações a serem enviadas e não há nada que o impeça de enriquecer a resposta com ainda mais informações.

Aqui está um exemplo do documento 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 você pode ver, as informações sobre como ligar para relacionadas actionssão fornecidas na mensagem e, ao interpretar essas informações, o cliente se torna mais resistente a alterações.

Torna-se particularmente poderoso se rels são URIs que podem ser consultados, e não a partir de um vocabulário fixo.

mcintyre321
fonte
0

Onde você leu que "a documentação não é mais necessária" para os serviços HATEAOS? Como você diz, você ainda precisa documentar a semântica dos links. No entanto, com o HATEOAS, você não precisa documentar e, portanto, manter para sempre a estrutura da maioria dos URIs.

O HATEOAS permite que um implementador de serviço modifique e dimensione a implementação de maneira significativa e eficiente, sem alterar um pequeno conjunto de URIs dos quais o cliente depende. É mais fácil manter um pequeno número de pontos de entrada inalterado do que um conjunto grande. Portanto, a redução do número de pontos de entrada públicos para o serviço e o fornecimento dinâmico de links para sub-recursos (HATEOAS) realmente suportam "URIs legais não mudam" melhor do que os serviços que não são do HATEOAS.

Jonathan Giddy
fonte
Um lugar onde se pode ler que "a documentação não é mais necessária" é a dissertação de Roy Fielding, que cunhou o termo.
meriton - em greve 5/06/2015
1
Eu apenas procurei na dissertação de Fielding o uso de "documentação" e não encontrei nada parecido com a afirmação "a documentação não é mais necessária". Você pode indicar em que parte da dissertação de Fielding encontrou essa reivindicação?
27616 Jonathan Giddy
0

(HATEOAS), a restrição reivindicada para tornar uma API da Web "verdadeiramente RESTful"

A única coisa que a torna uma verdadeira API REST é atender a todas as restrições, não apenas uma.

Mas, na minha opinião, um serviço é muito mais do que sua estrutura de URI. Para usá-lo efetivamente, você também precisa saber: ...

É por isso que precisamos de outras restrições, mensagem auto-descritiva, etc.

Para evitar a quebra de clientes, você ainda precisa fazer a versão da sua API.

Não importa como você tente, precisará fazer a versão da sua API. Em um cliente REST, você ainda precisa saber como chegar a uma página na qual deseja fazer as coisas, quais links a seguir e quais propriedades você precisa coletar com base no vocabulário RDF que descreve a mensagem. Se você precisar substituir ou remover algo desse vocabulário, provavelmente quebrará todos os seus clientes e você precisará de uma nova versão. Portanto, acho que o REST não é algo que você deve publicar cedo (e descobrir o modelo enquanto altera constantemente a API); caso contrário, você terá várias versões. Você precisa de um modelo de domínio estável primeiro para construir ...

inf3rno
fonte