Qual é a função do cabeçalho HTTP “Vary: Accept”?

93

Eu uso PHP para gerar páginas da Web dinâmicas. Conforme declarado no tutorial a seguir (veja o link abaixo), o tipo MIME de documentos XHTML deve ser "application / xhtml + xml" quando $ _SERVER ['HTTP_ACCEPT'] permitir. Uma vez que você pode servir a mesma página com 2 MIMEs diferentes ("application / xhtml + xml" e "text / html"), você deve definir o cabeçalho HTTP "Vary" para "Aceitar". Isso ajudará o cache em proxies.

Link: http://keystonewebsites.com/articles/mime_type.php

Agora eu não tenho certeza da implicação de: header ('Vary: Accept'); Não tenho certeza do que 'Vary: Aceitar' fará exatamente ...

A única explicação que encontrei é:

Após o cabeçalho Content-Type, um cabeçalho Vary é enviado para (se bem entendi) dizer aos caches intermediários, como servidores proxy, que o tipo de conteúdo do documento varia dependendo das capacidades do cliente que solicita o documento. http://www.456bereastreet.com/archive/200408/content_negotiation/

Qualquer um pode me dar uma explicação "real" deste cabeçalho ( com aquele valor ). Acho que entendo coisas como: Vary: Accept-Encoding em que o cache em proxies pode ser baseado na codificação da página veiculada, mas não entendo: Vary: Accept

AlexV
fonte
1
Francamente - não se preocupe. Deixando de lado as falhas de implementação nesse site, a única vez em que você obterá benefícios de servir com um tipo de conteúdo XML é quando você faz coisas que não podem ser feitas em texto / html - e se tudo o que você está fazendo está trocando o Doctype e o xmlns, então você não vai fazer essas coisas. Limite-se a text / html. Por falar nisso, você também pode usar o HTML 4.01.
Quentin
Sim, eu entendo isso e acho que "problemas" como esse surgem com muita frequência no desenvolvimento da Web. Graças a "deveria" nas especificações / RFCs!
AlexV
2
Você provavelmente deve ler isto: blogs.msdn.com/ieinternals/archive/2009/06/17/… antes de considerar o uso de VARY.
EricLaw
1
Este vídeo tem uma boa explicação sobre o Vary:cabeçalho.
Kannan Mohan

Respostas:

94
  • O cache-controlcabeçalho é o principal mecanismo de um servidor HTTP para informar a um proxy de armazenamento em cache a "atualização" de uma resposta. (ou seja, como / se tempo para armazenar a resposta no cache)

  • Em algumas situações, as cache-controldiretivas são insuficientes. Uma discussão do grupo de trabalho HTTP está arquivada aqui, descrevendo uma página que muda apenas com o idioma. Este não é o caso de uso correto para o cabeçalho vary, mas o contexto é valioso para nossa discussão. (Embora eu acredite que o cabeçalho Vary resolveria o problema nesse caso, existe uma maneira melhor.) Nessa página:

Vary é estritamente para os casos em que é impossível ou excessivamente complicado para um proxy replicar o que o servidor faria.

Um exemplo inventado:

Seu servidor HTTP tem uma grande página de destino. Você tem duas páginas ligeiramente diferentes com o mesmo URL, dependendo se o usuário já esteve lá antes. Você distingue entre solicitações e "contagem de visitas" de um usuário com base em Cookies. Mas, como a página de destino do seu servidor é muito grande, você deseja que os proxies intermediários armazenem a resposta em cache, se possível.

Os cabeçalhos URL, Last-Modified e Cache-Control são insuficientes para fornecer esse insight a um proxy de armazenamento em cache, mas se você adicionar Vary: Cookie, o mecanismo de cache adicionará o cabeçalho Cookie em suas decisões de armazenamento em cache.

Finalmente, para sites dinâmicos e de pequeno tráfego - sempre achei o simples Cache-Control: no-cache, no-storee Pragma: no-cachesuficiente.

Editar - para responder mais precisamente à sua pergunta: o cabeçalho da solicitação HTTP 'Aceitar' define os Tipos de Conteúdo que um cliente pode processar. Se você tiver duas cópias do mesmo conteúdo na mesma URL, diferindo apenas no tipo de conteúdo, o uso Vary: Acceptpode ser apropriado.

Atualização 11 de setembro de 12:

Estou incluindo alguns links que apareceram nos comentários desde que este foi publicado originalmente. Ambos são recursos excelentes para exemplos do mundo real (e problemas) com Vary: Accept; Se estiver lendo esta resposta, você também precisa ler esses links.

O primeiro, do excelente EricLaw, sobre o comportamento do Internet Explorer com o cabeçalho Vary e alguns dos desafios que ele apresenta aos desenvolvedores: o cabeçalho Vary impede o cache no IE . Resumindo, o IE (pré-IE9) não armazena em cache nenhum conteúdo que use o cabeçalho Vary porque o cache de solicitação não inclui cabeçalhos de solicitação HTTP. EricLaw (Eric Lawrence no mundo real) é gerente de programa da equipe do IE.

A segunda é de Eran Medan e é uma discussão contínua sobre o comportamento inesperado relacionado a Vary no Chrome: o backing não manipula o cabeçalho Vary corretamente . Está relacionado ao comportamento do IE, exceto que os desenvolvedores do Chrome adotaram uma abordagem diferente - embora não pareça ter sido uma escolha deliberada.

JJ
fonte
3
Cuidado com isso em conjunto com o botão Voltar do navegador no Chrome, há uma espécie de guerra contra esse bug (que agora não foi corrigido por algum motivo) code.google.com/p/chromium/issues/detail?id=94369
Eran Medan,
6
@EranMedan O bug do Chrome já foi corrigido.
59

Vary: Acceptsimplesmente diz que a resposta foi gerada com base no Acceptcabeçalho da solicitação. Uma solicitação com um Acceptcabeçalho diferente pode obter uma resposta diferente.

(Você pode ver que o código PHP vinculado olha $HTTP_ACCEPT. Esse é o valor do Acceptcabeçalho da solicitação.)

Para caches HTTP, isso significa que a resposta deve ser armazenada em cache com cuidado extra. Só vai ser uma correspondência válida para solicitações posteriores com exatamente o mesmo Acceptcabeçalho .

Agora, isso só importa se a página puder ser armazenada em cache em primeiro lugar. Por padrão, as páginas PHP não são. Uma página PHP pode marcar a saída como armazenável em cache, enviando certos cabeçalhos ( Expirespor exemplo). Mas se e como fazer isso é uma questão diferente.

Jason Orendorff
fonte
é "poderia obter" ou "deveria obter"?
Pacerier,
6
@Pacerier "pode ​​obter" está correto. Vary: Acceptnão significa que cada Acceptvalor de cabeçalho distinto possível produz uma resposta diferente e única. Significa apenas que um Acceptcabeçalho diferente pode produzir uma resposta diferente.
Jason Orendorff
2

Na verdade, há um número significativo de novos recursos em breve (e já no Chrome) que tornam o Varycabeçalho extremamente útil. Por exemplo, considere a sugestão do cliente . Quando usado em conexão com imagens, por exemplo, a sugestão de cliente permite que um servidor otimize recursos, como imagens, dependendo de:

  • Largura da imagem
  • Largura da janela de visualização
  • Tipo de codificação compatível com o navegador (pense em WebP)
  • Downlink (essencialmente velocidade da rede)

Portanto, um servidor que oferece suporte a esses recursos definiria o Varycabeçalho para indicar isso.

O Chrome anuncia o suporte WebP definindo "image / webp" como parte do Varycabeçalho de cada solicitação. Portanto, um servidor pode reescrever uma imagem como WebP se o navegador oferecer suporte, então o proxy precisará verificar o cabeçalho para não armazenar em cache uma imagem WebP e, em seguida, veiculá-la em um navegador que não ofereça suporte a WebP. Obviamente, se o seu servidor não fizer isso, não importa. Portanto, como a resposta do servidor varia no Acceptcabeçalho da solicitação, a resposta deve incluir isso para não confundir os proxies:

Vary: Accept

Outro exemplo pode ser a largura da imagem. Em um navegador móvel, o Widthcabeçalho pode ser bem pequeno para uma imagem responsiva, em comparação com o que seria se visualizado em um navegador de desktop. Portanto, nesse caso Widthseria adicionado ao Varycabeçalho é essencial para o proxy não armazenar em cache a versão móvel pequena e veiculá-la em navegadores de desktop, ou vice-versa. Nesse caso, o cabeçalho pode incluir:

Vary: Accept, Width

Ou, no caso de um servidor suportar todas as especificações de dicas do cliente, o cabeçalho seria algo como:

Vary: Accept, DPR, Width, Save-Data, Downlink
Brad Berger
fonte