Essa API REST é realmente RPC? Roy Fielding parece pensar assim

99

Muito do que pensei que sabia sobre REST está aparentemente errado - e não estou sozinho. Esta pergunta tem uma longa introdução, mas parece necessária porque a informação está um pouco dispersa. A questão real vem no final se você já estiver familiarizado com este tópico.

Desde o primeiro parágrafo das APIs REST de Roy Fielding deve ser orientado por hipertexto , está bastante claro que ele acredita que seu trabalho está sendo amplamente mal interpretado:

Estou ficando frustrado com o número de pessoas chamando qualquer interface baseada em HTTP de API REST. O exemplo de hoje é a API REST SocialSite . Isso é RPC. Grita RPC. Há tanto acoplamento em exibição que deveria receber uma classificação X.

Fielding segue listando vários atributos de uma API REST. Alguns deles parecem ir contra a prática comum e os conselhos comuns sobre SO e outros fóruns. Por exemplo:

  • Uma API REST deve ser inserida sem nenhum conhecimento prévio além do URI inicial (marcador) e um conjunto de tipos de mídia padronizados que são apropriados para o público-alvo (ou seja, deve ser entendido por qualquer cliente que possa usar a API). ...

  • Uma API REST não deve definir nomes ou hierarquias de recursos fixos (um acoplamento óbvio de cliente e servidor). ...

  • Uma API REST deve gastar quase todo o seu esforço descritivo na definição do (s) tipo (s) de mídia usado (s) para representar recursos e direcionar o estado do aplicativo, ou na definição de nomes de relações estendidas e / ou marcação habilitada para hipertexto para tipos de mídia padrão existentes. ...

A ideia de "hipertexto" desempenha um papel central - muito mais do que a estrutura URI ou o que os verbos HTTP significam. "Hipertexto" é definido em um dos comentários:

Quando eu [Fielding] digo hipertexto, quero dizer a apresentação simultânea de informações e controles de forma que a informação se torne a disponibilidade por meio da qual o usuário (ou autômato) obtém escolhas e seleciona ações. A hipermídia é apenas uma expansão sobre o que o texto significa incluir âncoras temporais dentro de um fluxo de mídia; a maioria dos pesquisadores abandonou a distinção.

O hipertexto não precisa ser HTML em um navegador. As máquinas podem seguir links quando entendem o formato dos dados e os tipos de relacionamento.

Eu estou supondo neste ponto, mas os dois primeiros pontos acima parecem sugerir que a documentação da API para um recurso Foo que se parece com o seguinte leva a um acoplamento estreito entre cliente e servidor e não tem lugar em um sistema RESTful.

GET   /foos/{id}  # read a Foo
POST  /foos/{id}  # create a Foo
PUT   /foos/{id}  # update a Foo

Em vez disso, um agente deve ser forçado a descobrir os URIs para todos os Foos, por exemplo, emitindo uma solicitação GET contra / foos. (Esses URIs podem seguir o padrão acima, mas isso não vem ao caso.) A resposta usa um tipo de mídia que é capaz de transmitir como acessar cada item e o que pode ser feito com ele, dando origem ao terceiro ponto acima . Por esse motivo, a documentação da API deve se concentrar em explicar como interpretar o hipertexto contido na resposta.

Além disso, toda vez que um URI para um recurso Foo é solicitado, a resposta contém todas as informações necessárias para um agente descobrir como proceder, por exemplo, acessando recursos associados e pais por meio de seus URIs ou tomando uma ação após a criação / exclusão de um recurso.

A chave para todo o sistema é que a resposta consiste em hipertexto contido em um tipo de mídia que, por sua vez, transmite ao agente opções para prosseguir. Não é diferente da maneira como um navegador funciona para humanos.

Mas este é apenas meu melhor palpite neste momento particular.

Fielding postou um follow-up no qual ele respondeu às críticas de que sua discussão era muito abstrata, sem exemplos e rica em jargões:

Outros tentarão decifrar o que escrevi de maneiras mais diretas ou aplicáveis ​​a alguma preocupação prática de hoje. Provavelmente não irei, porque estou muito ocupado lutando com o próximo tópico, me preparando para uma conferência, escrevendo outro padrão, viajando para algum lugar distante ou apenas fazendo as pequenas coisas que me fazem sentir que mereci meu salário.

Então, duas perguntas simples para os especialistas em REST com uma mentalidade prática: como você interpreta o que Fielding está dizendo e como você o coloca em prática ao documentar / implementar APIs REST?

Edit: esta pergunta é um exemplo de como pode ser difícil aprender algo se você não tiver um nome para o que está falando. O nome nesse caso é "Hipermídia como o mecanismo do estado do aplicativo" (HATEOAS).

Rich Apodaca
fonte
26
John, Rich está apenas explicando a mudança de mentalidade que ele teve. Não há nada de subjetivo ou argumentativo nisso. Vote para se manter aberto - essa é uma das melhores perguntas com a tag 'descanso' que já vi no SO.
Keith Gaughan
4
Keith, "explicar a mudança de mentalidade" é algo que ele deveria fazer em seu blog, não no SO.
John Saunders
13
Ele não está explicando sua mudança de mentalidade, ele está perguntando se seu entendimento está correto.
aehlke
4
Excelente resumo. Aprendi mais com essa pergunta do que com a maioria das respostas.
Martin Konecny

Respostas:

21

Acho que sua explicação cobre principalmente isso. URIs são identificadores opacos que, em sua maior parte, não devem ser comunicados além do URI de indicador que é usado pelo agente do usuário para acessar o aplicativo.

Quanto à documentação, esta pergunta já foi feita algumas vezes. Você documenta seu tipo de mídia, juntamente com os controles de hiperlink que ele contém (links e formulários) e o modelo de interação, se desejar (consulte AtomPub).

Se você documentar os URIs ou como criá-los, está fazendo isso errado.

SerialSeb
fonte
Isso ainda é verdade? Existem especificações de resposta da API, como Ionspec, que criaram esses URIs como parte da resposta intencionalmente.
Sean Pianka
Sim eles tem. Nesse ponto, é uma questão de descobrir se esses URIs documentados são apenas pontos de entrada para o aplicativo, que são garantidos para permanecer (alguns deles não são incomuns e muito úteis) ou se, porque as pessoas querem geração de código, eles são incorporados a partir de uma especificação diretamente no código, evitando que o servidor deixe o cliente saber como ele pode fazer as coisas. Se o cliente pensa que sabe por causa daquele contrato, você não está na hipermídia, você está no modelo de sabonete openapi dos dias modernos, com os mesmos problemas que você encontrou com aquele há 18 anos.
SerialSeb
O que é verdade é que muitas linguagens de documentação de API surgiram nos últimos 11 anos, mas os fundamentos não mudaram. Acredito que o valor em descobrir esses links, ou pelo menos a descoberta de modelo de URI, está na construção de código de cliente genérico reutilizável que pode usá-los dinamicamente, permitindo que muitas implementações no lado do servidor reutilizem o mesmo código de cliente. A incorporação de URI continua a dificultar esses cenários, mas se você usar esses formatos, tende a acoplar fortemente um cliente gerado a partir dessas especificações, portanto, já perdeu esse recurso.
SerialSeb
8

Sua interpretação me parece correta. Eu acredito que as restrições de Fielding podem ser aplicadas na prática.

Eu realmente gostaria de ver alguém publicar alguns bons exemplos de como documentar uma interface REST. Existem tantos exemplos ruins, ter alguns válidos para apontar os usuários seria muito valioso.

Darrel Miller
fonte
2
Uau. Essa página do Modelo de Recursos trouxe uma lágrima aos meus olhos. Vamos torcer para que isso inicie uma tendência.
Darrel Miller
É uma pena que este seja basicamente o único exemplo dessa API na web! Pior ainda, não há bons exemplos de código de cliente que siga o princípio (que encontrei).
jkp
1
@DarrelMiller Mas esses tipos de mídia não são muito "específicos"? Parece-me que a API deles está realmente usando apenas um MIME: application/jsone que o Modelo de Recursos são realmente as relações. Eu entendi mal esse aspecto do REST? Eu também li uma de suas respostas de SO que parece apontar que aqueles contratos de "um atributo" devem ser evitados ...
edsioufi
2
@RichApodaca Seu link morreu de disenteria. web.archive.org/web/20170409132237/https://kenai.com/projects/…
forresthopkinsa
5

Tenho procurado por um bom exemplo de API escrita seguindo o HATEOAS e tive problemas para encontrar um (achei a API SunCloud e AtomPub difíceis de aplicar a uma situação de API "normal"). Então, tentei fazer um exemplo realista em meu blog que seguiu o conselho de Roy Fieldings sobre o que significa ser uma implementação REST adequada. Achei muito difícil dar o exemplo, apesar do fato de ser bastante simples em princípio (apenas confuso quando se trabalha com uma API em vez de uma página da web). Eu entendo o que Roy estava discutindo e concordo, é apenas uma mudança de mentalidade para implementar adequadamente para uma API.

Dê uma olhada: Exemplo de API usando Rest

jeremyh
fonte
4

A única exceção para dar instruções sobre como construir URIs é que é permitido enviar um modelo de URI na resposta de hipertexto, com campos a serem substituídos automaticamente pelo cliente, usando outros campos no hipertexto. Isso geralmente não acaba economizando muita largura de banda, já que a compactação gzip irá lidar com as partes repetidas dos URIs bem o suficiente para não se preocupar com isso.

Algumas boas discussões sobre REST e os HATEOAS relacionados:

Vantagens (também) de usar HATEOAS em APIs RESTFul

Como OBTER uma xícara de café

aehlke
fonte
4

Para os interessados, encontrei um exemplo detalhado do HATEOAS na prática na API Sun Cloud .

Rich Apodaca
fonte
2
Link está morto. Arquivo
qualquer que seja
4

A coisa que a maioria das pessoas erram é que (pelo menos eu acho) no mundo REST você não documenta sua "interface Rest", o que você documenta é um tipo de mídia, independentemente do seu servidor ou serviço.

Redben
fonte
2

Acho que ao longo dos anos em que o REST está disponível agora, os tecnólogos chegaram a um acordo com o conceito de um recurso e o que realmente é ou não é RESTful.

De acordo com o modelo de maturidade de Richardson, existem 4 níveis (0-3) que definem o quão RESTful é sua API, com 3 significando uma API verdadeiramente RESTful, exatamente como Roy Fielding pretendia que fosse.

O nível 0 é quando você tem um URI de ponto de entrada - como SOAP.

Nível 1 significa que a API é capaz de distinguir entre diferentes recursos e tem mais de um ponto de entrada - ainda tem cheiro de SOAP.

O nível 2 é quando você usa verbos HTTP - GET, POST, DELETE principalmente. Este é o nível em que REST realmente entra em cena.

No Nível 3, você começa a usar controles hipermídia para tornar sua API verdadeiramente RESTful.

Links sugeridos para leituras adicionais:

Sampada
fonte
1

Absolutamente correto. Além disso, eu observaria que os modelos de URI são perfeitamente adequados em um aplicativo RESTful, desde que os padrões sejam de documentos recebidos do servidor (OpenSearch sendo um exemplo adequado). Para modelos de URI, você documenta onde eles estão sendo usados ​​e quais são os espaços reservados esperados no modelo, mas não os próprios modelos. Um pouco ao contrário do que Wahnfrieden disse, esta não é uma exceção.

Por exemplo, em meu trabalho, temos um sistema de gerenciamento de domínio interno e o documento de serviço especifica dois modelos de URI: um para produzir uma URI de melhor estimativa para um recurso de domínio e outro para construir um URI para consultar a disponibilidade do domínio. Ainda é possível percorrer a coleção de domínios para descobrir qual é o URI de um determinado domínio, mas dado o imenso número de domínios que gerencia, isso não seria viável para o cliente, dando-lhes uma maneira de adivinhar qual O URI de um recurso de domínio pode ser uma grande vitória em termos de facilidade de implementação da perspectiva do cliente e largura de banda do servidor.

Para sua pergunta: Nossa documentação normativa é recursos expostos, o efeito de vários métodos sobre esses recursos e os tipos de mídia de representação usados ​​e seus esquemas, e para quais tipos de recursos os URIs nessas representações apontam.

Também incluímos documentação não normativa (informativa) que contém um aviso de isenção de responsabilidade para não ler demais os URIs mencionados no documento, que fornece exemplos de interações cliente-servidor típicas. Isso coloca a documentação normativa um tanto abstrata em termos concretos.

Keith Gaughan
fonte
1
Não há problema em fornecer modelos de URI como parte de sua API, fora de banda. Apenas NÃO se refira a isso como REST, porque não é. É uma grande quantidade de acoplamento e exatamente o que o REST foi feito para evitar. Mas, como você disse, REST não é para todos os aplicativos. Portanto, não finja que todos os aplicativos são REST.
aehlke
1
Na verdade, eu concordo. Eu acredito que foi isso que eu disse. No entanto, não consigo ver nenhuma boa razão para fornecer modelos de URI fora de banda.
Keith Gaughan
0

Vamos supor que GET /foos/createFormé invocado para obter valores de campos de formulário para os quais devem ser fornecidos quando vamos criar POST /foos. Agora, este URL específico, ou seja, o 1 usado para criar foos, deve ser mencionado na resposta GET /foos/createFormcomo um link de ação de envio de acordo com a proposição de Fielding, certo?
Então, qual é o benefício de mapear ações para verbos Http bem conhecidos para ações, "convenção sobre código / configuração" é anulada.

Redzedi
fonte