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?


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.


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.


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.


+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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.