REST - Tradeoffs entre negociação de conteúdo via cabeçalho Accept versus extensões

40

Estou trabalhando no projeto de uma API RESTful. Sabemos que queremos retornar JSON e XML para qualquer recurso. Eu estava pensando que faríamos algo assim:

GET /api/something?param1=value1
Accept:  application/xml (or application/json)

No entanto, alguém jogou fora usando extensões para isso, assim:

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Quais são as vantagens e desvantagens dessas abordagens? É melhor confiar no cabeçalho de aceitação quando uma extensão não é especificada, mas respeitar extensões quando especificado? Existe uma desvantagem nessa abordagem?

Brandon Linton
fonte
Qual servidor da web você está usando? e como ele analisa URLs?
Dipan Mehta
11
Não tenho idéia do lado técnico (servidor) das coisas. Dito isto, prefiro sua abordagem, porque ela usa o padrão http, o que facilita a compreensão (por exemplo, quando alguém deve fazer alguma manutenção nela alguns anos depois). Você pode confiar na extensão quando a aceitação não for especificada ou tiver um valor inesperado, mas eu sempre seguiria o caminho padrão primeiro.
Treb
@ Dipan Estou hackeando isso com a MVC4 Web API (ainda em beta). Ele usa as abstrações de roteamento do ASP.NET, que são bastante agradáveis.
Brandon Linton
11
@ Treb Sim, eu sou muito mais fã de usar o valor do cabeçalho Accept. Gostaria de saber se há alguma desvantagem em apoiar os dois.
Brandon Linton

Respostas:

38

Isso, "No entanto, filosoficamente - a primeira abordagem é a única abordagem.", E este "O método RESTful oficial adequado é usar o cabeçalho Accept:". são amplamente percebidos como o caso, mas também são absolutamente incorretos .

Aqui está um breve trecho de Roy Fielding (que definiu REST) ​​...

"a seção 6.2.1 não diz que a negociação de conteúdo deve ser usada o tempo todo." citar

Essa conversa em particular está no contexto do cabeçalho 'Accept-Language:', mas o mesmo se aplica igualmente ao cabeçalho 'Accept:', como ficou claro posteriormente em sua resposta ...

"Não faço ideia por que as pessoas não conseguem ver o segundo e o terceiro link na página superior

http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

apontam para as duas edições em PDF ".

O que ele quer dizer com isso é que não há problema em usar pontos de extremidade diferentes para diferentes representações dos mesmos dados de origem. (Nesse caso, um ponto final .html e dois pontos finais .pdf diferentes.)

Também em uma discussão semelhante, desta vez sobre as virtudes do uso de parâmetros de consulta versus o uso de extensões de arquivo para diferentes tipos de mídia ...

"É por isso que eu sempre prefiro extensões. Nenhuma das opções tem algo a ver com o REST." citar

Novamente, isso é um pouco diferente das extensões Accept vs. filename, mas a posição de Fielding ainda é clara.

Resposta - isso realmente não importa muito. As trocas entre os dois não são muito significativas e ambos são estilos aceitáveis.

Tom Christie
fonte
3
Ótima resposta equilibrada. Acho que acrescentaria que, às vezes, é "óbvio" do URI que um determinado conteúdo se destina. por exemplo, extensão .html ou extensão .pdf no URI. E, nesse caso, não há realmente nenhuma necessidade de oferecer suporte à negociação de conteúdo, e ter conteúdo implícito no URI facilita o compartilhamento do URI por seres humanos e o utiliza para vincular as coisas da maneira que elas podem consumir imediatamente. Em outros casos, como você deseja evitar extensões em seus URIs e / ou deseja expor uma API da web que suporta vários tipos de conteúdo json / XML igualmente, um cabeçalho de aceitação pode se encaixar melhor.
Tim Lovell-Smith
Resposta atualizada para conter novos links. Eu acho que os grupos do Yahoo mudaram sua estrutura.
Phil Sturgeon
Discordo. O idioma de descrição do recurso retornado pelo servidor deve ser irrelevante para a lógica de negócios executada pelo terminal em serviço. Ter vários URIs para o mesmo ponto de extremidade de serviço, apenas para acomodar diferentes linguagens de descrição de recursos, parece um mal-entendido de como os URIs REST devem ser construídos.
Dejay Clayton
10

A abordagem RESTful oficial adequada é usar o Accept:cabeçalho.

No entanto, você deve ter cuidado para não quebrar a capacidade de cache, que é um dos requisitos do REST. Você precisa ter um Vary: Acceptcabeçalho e um cache que o entendam. No mundo ideal, você teria, mas na vida real sua milhagem pode variar. Portanto, a segunda solução não é tão limpa, mas pode ser mais prática.

Além disso, observe que alguns navegadores muito antigos costumavam ignorar cabeçalhos, dependendo da extensão.

vartec
fonte
11
Factualmente impreciso. Veja a resposta aceita.
Phil Sturgeon
9

Tecnicamente, isso realmente não importa - seu servidor da Web poderá passar pelo processo de maneira apropriada. (Estou assumindo isso, mas não parece um showstopper).

No entanto, filosoficamente - a primeira abordagem é a única abordagem. No REST, na verdade, o URL apenas aponta para um URI - que é apenas um recurso. Pense por um momento esse recurso, igual ao objeto na programação orientada a objetos. Você fala com esse recurso através de apenas 4 métodos (também conhecidos como GET / POST / PUT / DELETE - ou se algo que o transporte permitir), mas esse método não se torna descrição do objeto. Da mesma forma, os aspectos em que o valor retornado não é o URI. O objeto ainda é algo e não algo.xml ou algo.json

Suponha que, se você não quiser usar o cabeçalho Accept, mas se ainda quiser ser verdadeiramente REST filosoficamente, não me importo com algo como:

GET /api/something?parm1=value1&return_type=xml

em oposição a

GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Mas como eu disse, essa diferença é apenas filosófica.

Dipan Mehta
fonte
+1 Dipan, você está certo, exceto por uma coisa: / api / something? Return_type = xml ainda não é tranquilo . O motivo de não ser RESTful é que os URLs são opacos. IOW, do ponto de vista do protocolo, não há diferença entre / api / something / xml e / api / something? Xml. Consulte w3.org/DesignIssues/Axioms.html .
Mark E. Haase
0

@artec: Eu acho que você está errado

O princípio RESTful oficial apropriado diz que nada deve ser oculto nos cabeçalhos HTTP, pois é o URI que é exposto ou referenciado; qualquer detalhe sobre a solicitação / resposta deve ser fornecido como parte do URI

Por isso, recomendo fortemente evitar o uso do cabeçalho para obter detalhes sobre a solicitação e resposta e manter

 GET /api/something.xml?parm1=value1 (or /api/something.json?param1=value1)

Não consigo encontrar as referências rapidamente, mas vou postá-las de volta com elas (na verdade, você pode consultar o livro de publicação O'reilly "RESTful web services" ( http://shop.oreilly.com/product/9780596529260.do ) o que confirma o mesmo

Basav
fonte
17
-1 Completamente errado. Por um lado, a URL é enviada nos cabeçalhos HTTP. Além disso, cada URL distinto deve representar um recurso distinto. As codificações XML e JSON do mesmo conteúdo claramente não são 2 recursos diferentes; elas são 2 representações diferentes do mesmo recurso.
Mark E. Haase
Os cabeçalhos HTTP são um local legítimo e recomendado para armazenar "metadados de mensagens", como: credenciais de segurança, identificador de correlação, ID da sessão, contexto transacional, formatos de dados. Esse tipo de informação não deve sobrecarregar seus URLs ou sua carga útil da mensagem.
Paulo Merson 06/06