Por que a especificação HTML \ DOM não permite que os hiperlinks definam um cabeçalho de aceitação?

10

O objetivo do Acceptcabeçalho do cliente é informar ao servidor que tipo de dados ele aceita como resposta à sua solicitação. Podemos definir esse cabeçalho em chamadas HTTP assíncronas em Javascript, mas não em HTML.

Por exemplo, considere um link como <a href="https://softwareengineering.stackexchange.com/some/resource">Get as CSV</a>. Se um atributo como accept="text/csv"fosse permitido e o navegador interpretasse isso para enviar um Accept: text/csvcabeçalho com essa solicitação, o servidor poderia responder à semântica da solicitação. Sem ele, podemos criar um link como <a href="https://softwareengineering.stackexchange.com/some/resource?format=csv">Get as CSV</a>, e o servidor deve responder ao parâmetro da string de consulta arbitrária.

Quais são os motivos, tanto técnicos quanto históricos, por trás da especificação HTML \ DOM que não permite a configuração de um Acceptcabeçalho por meio de marcação?

Andy Hunt
fonte
2
A Web é uma plataforma legada, dificultada pelo medo de mudar e por um comitê de padrões lentos: wtfhtmlcss.com wtfjs.com
Den

Respostas:

9

Porque os cabeçalhos não fazem parte do URL. O URL deve identificar o recurso, por si só, e deve fazê-lo exclusivamente. Os cabeçalhos Accept(e os mais úteis Accept-Encoding) não devem afetar a semântica da solicitação. Eles devem indicar os recursos do cliente para que o servidor possa formatar a resposta adequadamente.

Se você fizer uma chamada HTTP a partir do JavaScript, seu código JavaScript será o cliente e, portanto, definirá cabeçalhos. Mas, para o link HTML, o navegador é o cliente e, portanto, pode escolher.

Se você deseja fornecer CSV para um usuário, o recurso vinculado geralmente deve estar em um formato fixo. Imagine o usuário

Copy Link Address

$ wgetPasteEnter

Isso é uma coisa legítima para eles fazerem por várias razões. E como o link lhes prometeu CSV, é o que eles esperam. Mas o wget não terá nenhum outro atributo do link. Somente o URL. Portanto, as informações devem ser codificadas no URL.

De fato, não há muitos usos para o Acceptcabeçalho, porque a maioria dos recursos tem apenas seu formato e não faz muito sentido em outro. O Accept-Encodingé útil; se o cliente disser que Accept-Encoding: gzip,deflateisso significa que ele pode fazer descompactação transparente . Mas o único uso que eu pude pensar Accepté nos formatos de imagem e vídeo, por exemplo, para fornecer alternativa aos navegadores que não suportam digamos image/svg+xmlou video/webm. Exceto os navegadores, na verdade, não anunciam quais formatos de mídia são compatíveis, portanto, não funciona. E o HTML optou por implementar mecanismos diferentes, um pouco mais flexíveis, de qualquer maneira. E poucos outros tipos de dados têm vários formatos alternativos amplamente implementados para você escolher.

Jan Hudec
fonte
Além disso, com áudio e vídeo, existem as tags audioe video. Portanto, esse problema é agora (espero) mitigado a ponto de ser corrigido. Bem, para navegadores compatíveis com HTML5.
Tiro parta
@ParthianShot: Verdadeiro. Como não faço aplicativos da web, não me lembro como isso funciona. Aparentemente, é mais adequado fornecer ao cliente uma lista para escolher (que geralmente é curta) do que ter o cliente listando todas as coisas que ele suporta.
Jan Hudec 29/07
O URL deve identificar o recurso, e é exatamente por isso que eu queria adicionar parâmetros como cabeçalho úteis para rastrear as coisas do usuário, como onde ele estava quando clicou ou se ele foi redirecionado anteriormente de algum lugar, existe uma maneira melhor de fazer isso? isto?
santiago arizti 19/08/19
3

Como o Accept:cabeçalho se destina a indicar quais tipos de documentos o navegador do usuário pode manipular corretamente, e isso não é uma informação que você, como autor da página da web, possui.

Especificamente, o motivo pelo qual o protocolo HTTP fornece um cabeçalho Accept: é permitir a seleção de um tipo de arquivo apropriado quando o mesmo documento estiver disponível em mais de um formulário. Vamos supor que estou vinculando a uma imagem, por exemplo; meu navegador pode exibir imagens JPEG ou Tiff, mas pode não ter a capacidade de exibir uma imagem RAW. O navegador indicaria isso enviando os seguintes cabeçalhos com uma solicitação de imagem:

Accept: image/jpeg,image/tiff

Agora, se o servidor puder servir uma determinada imagem como RAW ou TIFF, ele responderá com uma versão TIFF da imagem (e defina o Content-Type:cabeçalho para indicar o tipo escolhido).

O que significaria para o autor da página da Web substituir as opções que o navegador envia? Se eu adicionasse um accept="image/raw"atributo hipotético , o navegador ainda não seria capaz de exibir uma imagem bruta - mas o servidor a enviaria.

jimwise
fonte
Bingo. O aplicativo não pode decidir quais tipos MIME o navegador aceita.
Svidgen
2

Um URI destina-se a identificar um recurso .

Recurso refere-se à coisa real que está sendo recuperada. Em um site, normalmente é uma página . Em uma API REST, normalmente seria uma entidade - pessoa, perfil, widget, foto etc.

Os cabeçalhos HTTP informam o servidor sobre o cliente - eles não descrevem nada sobre o recurso em si, nem fornecem qualquer ajuda para localizar esse recurso.

Por exemplo:

  • Accept-Encoding informa ao servidor que o cliente sabe como converter ou descompactar determinado conteúdo.
  • Accept-Language informa ao servidor que o cliente está em um determinado local e prefere conteúdo nesse local.
  • Authorization informa ao servidor que o cliente acha que está autorizado a acessar um recurso protegido.

Um tema comum com a maioria desses cabeçalhos de solicitação é que o servidor não é obrigado a honrá-los. Um Accept-Encodingdos gzipnão garante que a resposta será compactada. Um Accept-Languagedos ur-PKprovavelmente será ignorado ao acessar um site nos EUA, a menos que eles suportem especificamente o Urdu. E o servidor se reserva o direito de verificar o Authorizationcabeçalho e retornar um 401 ou 403 de qualquer maneira, se não gostar do que vê.

Nenhum desses cabeçalhos pretende alterar materialmente qualquer recurso sobre o qual o servidor fornece em resposta. O Acceptcabeçalho não é diferente. Se um cliente especificar application/xmle o servidor suportar apenas application/json, o servidor enviará JSON - não XML. Mais importante, o Acceptcabeçalho pode especificar vários tipos; nesse caso, o servidor está livre para retornar o que preferir (ou nenhum deles). Como você pode imaginar, isso pode facilmente levar a um comportamento indefinido para o usuário, mas vamos ignorá-lo por enquanto.

A intenção de um hiperlink é vincular a uma página - a página sendo um determinado tipo de recurso. Ou você pode ser justificado na definição mais vaga de simplesmente vincular a um recurso, mesmo se esse recurso for algo diferente de uma página (talvez uma imagem ou um conjunto de dados). O que definitivamente não se destina a fazer, no entanto, é o link para uma representação específica de um recurso. Isso é para o cliente e o servidor negociarem e o servidor finalmente decidir.

Accept-Languageé um exemplo óbvio de por que pode ser problemático permitir que hiperlinks controlem cabeçalhos. Realmente não faz sentido, se você pensar sobre isso. Cada usuário controla sua própria preferência de idioma; está configurado no sistema operacional e / ou no navegador. O navegador sempre deve enviar o mesmo Accept-Language cabeçalho, independentemente da página que está sendo visitada. Se o servidor suportar esse idioma, ótimo; caso contrário, responderá com o idioma que achar mais próximo.

Se isso puder ser alterado por hiperlinks, os links de entrada poderão forçá-lo a entrar na versão em chinês do site, mesmo quando o navegador e o sistema operacional não estiverem configurados para oferecer suporte a esse idioma. Isso não faz sentido. Se o site suportar inglês e seu navegador for inglês, ele deverá responder em inglês, independentemente do link indicado.

Da mesma forma, se o seu navegador souber exibir XML como dados estruturados e puder procurar XSLs para torná-lo bonito, mas não souber realmente o que fazer com o JSON, a não ser despejá-lo como texto simples, forçando-o a O conteúdo JSON por meio de um link (se isso fosse possível) é um comportamento agressivamente hostil ao usuário. O navegador deve sempre dizer: "Eu sei como exibir X, mas não Y, então eu realmente preferiria que você me desse X".

Entendo por que você pode pensar que é lógico permitir que o usuário de um navegador substitua essa decisão. Mas a verdade é que você está pensando em alguns casos minúsculos como baixar um relatório; 99% do tempo, quando essa opção existe, o usuário não está qualificado ou não possui informações suficientes para fazê-lo.

Em outras palavras, imagine seus pais ou avós fazendo o download de um arquivo e sendo solicitados a escolher text / csv ou text / plain. Eles provavelmente sabem a diferença? Não conheço o seu, mas o meu geralmente nem consegue identificar a diferença entre um banner e uma mensagem de erro, portanto não há como eles fazerem essa escolha de maneira inteligente. Por outro lado, pode haver um vislumbre de esperança se eles receberem links separados para baixar uma "pasta de trabalho do Excel" ou "Somente texto" - que, para eles, são realmente recursos separados , não apenas uma representação diferente do mesmo recurso, e os URIs devem refletir isso.

Não se pode confiar no usuário para entender que essas duas coisas são na verdade o mesmo recurso, mas uma representação diferente. E sem alterar tudo sobre o modo como a web funciona hoje, não podemos assumir nada sobre o que eles farão com esse hiperlink. Eles podem clicar ou clicar com o botão direito do mouse -> "salvar como" ou copiar e colar na barra de endereços ou usar um gerenciador de downloads ou ainda usar o IE6 ou pode estar usando algum tablet ou dispositivo móvel fora da marca com um navegador proprietário ... e em muitos desses casos, eles não obterão o conteúdo que desejam, porque perderão a parte do hiperlink que declara o tipo de conteúdo ou o navegador não será compatível.

A especificação HTML poderia ter sido projetada há 40 anos para oferecer suporte a um atributo de tipo de conteúdo em hiperlinks? Talvez, embora, como descrevi nos primeiros parágrafos, houvesse fortes razões contra isso, especialmente durante um período em que a largura de banda e os recursos do servidor eram escassos e a ideia de poder baixar o mesmo relatório em vários formatos (ou, francamente , baixar qualquer relatório) honestamente não havia ocorrido a ninguém. Mas certamente no mundo de hoje seria insano tentar adicionar algo assim às especificações; quebraria completamente a compatibilidade com versões anteriores e levaria ao temido "comportamento indefinido" em todos os navegadores existentes.

Aaronaught
fonte
Se um cliente especificar application / xml e o servidor suportar apenas application / json, o servidor enviará JSON - não XML. Então, para que serve o erro HTTP 406? Para citar rfc2616: Se um campo de cabeçalho Accept estiver presente, e se o servidor não puder enviar uma resposta aceitável de acordo com o valor combinado do campo Accept, o servidor DEVE enviar uma resposta 406 (não aceitável).
Jules Randolph
O que definitivamente não se destina a fazer, no entanto, é o link para uma representação específica de um recurso. Isso é para o cliente e o servidor negociarem e o servidor finalmente decidir. → E se o designer de aplicativos quiser participar da negociação? Existe alguma referência em que se afirma que o agente do usuário, ou seja, o cliente deve ser e é apenas o navegador da web ? Ficaria feliz se você pudesse me ajudar a entender isso.
Jules Randolph
0

A resposta principal é que um link em uma página da web deve ser renderizado como uma página da web. Se o servidor da Web retornar algum tipo que não seja uma página renderizável (imagem, arquivo baixado etc.), o conteúdo poderá ser renderizado pelo navegador ou não (ele poderá ser salvo como um arquivo).

Não há como um link em uma página da web que leva a um arquivo CSS ou JavaScript, etc, seja renderizado corretamente em um navegador.

Para alcançar o que você está tentando alcançar (você não disse), crie um link que chama uma função JavaScript que fornece a funcionalidade extra necessária.

BobDalgleish
fonte
0

A razão é realmente bastante simples ..

Navegador

O Acceptscabeçalho está dizendo ao servidor que eu aceito e sei como exibir esse tipo de arquivo / conteúdo do arquivo ....

Javascript

Por que você pode alterar o cabeçalho ao enviar uma solicitação em javascript, é possível que você tenha criado uma maneira para acceptesse novo tipo de conteúdo, digamos que criptografou algo e o enviou como tipo de arquivo, encrypted/myencryptionseu javascript pode saber como descriptografá-lo para que possa aceitar que tipo de conteúdo para informar ao servidor que pode aceitar esse conteúdo

Links de ancoragem <a></a>

Nada mais é do que dizer ao navegador para obter o arquivo no href e renderizá-lo. Se o navegador não conseguir entendê-lo, tente analisá-lo e mostrar um prompt de download para o arquivo. alguns servidores resolvem isso definindo o tipo como texto / sem formatação e, em seguida, o navegador apenas mostra o texto do arquivo.

Martin Barker
fonte