Cabeçalhos para impedir solicitações 304 / If-modified-since / HEAD


31

Quais cabeçalhos devo enviar para interromper imediatamente todas as solicitações ao servidor após o cache do conteúdo?

Como temos um servidor de latência muito alta (Suspiro, VMWare), o envio de uma HEADsolicitação ao servidor leva + 40ms.

Atualmente, esses são os cabeçalhos que estão sendo enviados / recebidos;

Primeiro pedido

Cliente envia;

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Pragma: no-cache, no-cache, no-cache
Cache-Control: no-cache, no-cache, no-cache

Servidor responde;

HTTP/1.1 200 OK
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:51:51 GMT
Content-Type: text/plain
Vary: Accept-Encoding
Last-Modified: Tue, 31 Jan 2012 10:45:11 GMT
Content-Length: 14
Expires: Thu, 31 Jan 2013 14:51:51 GMT
Cache-Control: max-age=31536000

Portanto, ele envia um cabeçalho Cache-Controle Expiresdefinido para 365 dias no futuro. Infelizmente, na segunda atualização, ele solicita o objeto novamente com um If-Modified-Sincecabeçalho.

Segundo pedido

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
If-Modified-Since: Tue, 31 Jan 2012 10:45:11 GMT
Cache-Control: max-age=0

Resposta;

HTTP/1.1 304 Not Modified
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:58:00 GMT
Vary: Accept-Encoding
Expires: Thu, 31 Jan 2013 14:58:00 GMT
Cache-Control: max-age=31536000

Infelizmente, devido ao software proxy bobo desatualizado, não podemos usar Keep-Aliveou colocar outros servidores / proxys na frente do aplicativo. Também não podemos melhorar o desempenho do servidor e reduzir a latência da rede. Eu tenho tentado descobrir quais cabeçalhos podemos enviar para nos livrarmos das 301 solicitações. Eu tentei usar ETags, mas isso não faz diferença, ele ainda envia umIf-modified-since cabeçalho. Eu também tentei remover o Last-Modifiedcabeçalho, mas isso apenas causa uma solicitação GET padrão sem cache (verifiquei os logs, o servidor ainda está recebendo solicitações).

Os clientes são uma mistura de Firefox (principalmente), IE 7, 8 e (alguns) 9, Chrome e Safari, mas esse comportamento parece estar aparecendo em todos os navegadores testados.

TL; DR;

Rede terrível, que cabeçalhos devo enviar para dizer aos clientes para nunca enviar If-modified-sincesolicitações ao servidor para validar seu cache e manter o conteúdo em cache até que o Expirescabeçalho seja atingido?

Provavelmente estou perdendo algo óbvio, mas tudo o que tento parece produzir os mesmos resultados.

Temos um servidor NGINX em frente ao servidor de aplicativos, para que eu possa adicionar / remover cabeçalhos como desejar. Nosso proxy não oferece suporte ao Keep-Alive e não tem como melhorar o desempenho atroz da rede. Devido ao péssimo design do software, o aplicativo Web carrega +100 recursos em cada carregamento de página (sim, o software corporativo é uma porcaria) com uma latência de ~ 40-50ms por objeto.


1
Hmm, isso é estranho. O envio dos cabeçalhos Expir e Max Age deve impedir solicitações adicionais da imagem. Edit: a propósito, como é o envio de um JPG text/plain?
DiscruntledGoat

1
@DisgruntledGoat Ahh, você assumiu que um arquivo .jpg é na verdade uma imagem e não um documento de texto. Bem-vindo ao meu mundo =) (Na verdade, é um arquivo de texto que contém 'Olá Mundo' para o meu teste, o software apenas renomeia todos os arquivos sequencialmente IMG_xxxx.jpg independentemente do tipo de fresco huh).?
Smudge

o que você estava usando para definir os cabeçalhos de solicitação http?
barlop 28/07

Respostas:


25

Você não pode realmente controlar quais cabeçalhos os agentes que os usuários decidem enviar para você. Se o arquivo em questão estiver no cache do navegador e decidir que precisa verificar uma nova versão, será necessário. De acordo com este artigo , estas são as situações que os navegadores solicitarão usando o If-Modified-Since:

  • A entrada em cache não tem data de validade e o conteúdo está sendo acessado pela primeira vez em uma sessão do navegador
  • A entrada em cache tem uma data de validade, mas expirou
  • O usuário solicitou uma atualização da página clicando no botão Atualizar ou pressionando F5

Portanto, se você estiver recarregando a página para testar seu cache, ele não funcionará, pois o navegador solicitará novamente as imagens. Tente clicar em um link e depois em outro link para a primeira página. Se seus usuários recarregam regularmente as páginas, talvez seja necessário repensar a estrutura do site / aplicativo para evitar isso.

Uma coisa que pode ajudar é adicionar "público" ao cabeçalho de controle de cache, ou seja Cache-Control: public, max-age=31536000. Também aprendi recentemente que uma data de validade de mais de um ano é inválida. Como sua data de validade é exatamente de um ano, talvez a redução de alguns dias ou semanas garanta que o arquivo permaneça nos caches do navegador e não seja descartado.


Interessante, reduzirei o prazo para 60 dias e adicionarei a bandeira pública e verei o que acontece. Este parecia estar acontecendo no link de cliques em vez de F5s (de acordo com Firebug e os logs do servidor)
Smudge

Tecnicamente, a especificação HTTP / 1.1 diz apenas que "os servidores NÃO DEVEM enviar datas de expiração mais de um ano no futuro" (presumivelmente porque isso é ridiculamente longo antes da expiração) e que "aproximadamente um ano" no futuro é a expiração apropriada hora de enviar um conteúdo que nunca se espera que expire.
Ilmari Karonen

1
Depois de um pouco de brincadeira, concluí que a expiração do 365d não está afetando nossos clientes, no entanto, deixei-a segura, parece que essa Cache-Control: public,...foi a chave para essa situação específica.
Smudge

Você quer dizer que o cabeçalho "público" corrigiu as viagens de ida e volta desnecessárias? Eu tentei, mas sem sucesso ...
phtrivier

2
Caso não esteja claro na minha resposta, recarregar a página no seu navegador solicitará os arquivos novamente . Basta clicar nos links para abrir as páginas e o navegador usa seu cache.
usar o seguinte


3

Eu tive o mesmo problema, e as solicitações definitivamente estão atingindo o servidor para que ele responda com o 304status - estou enviando o 304 por meio de C # e, com certeza, ele atinge o servidor.

Eu só tinha Cache-Control: privatedefinido. Não max-agee não ExpiresFuncionou como esperado; bata no servidor com If-Modified-Sinceonde testo o valor em comparação com o que espero e entrego 304com corpo de resposta vazio - senão 200e preenchendo o corpo de resposta.

A configuração do Expirescabeçalho teve os resultados desejados, 200 - (from cache)no cliente e nenhuma solicitação HTTP atingiu o servidor.

Mas .. achei que a configuração AMBOS max-age= & Expirespode fazer com que os navegadores não enviem If-Modified-Sincecabeçalho E não armazenem em cache se os valores não corresponderem .

Algo a ter em atenção se tiver problemas de cache e utilizar os diferentes cabeçalhos em combinação.


1

Um pouco fora de tópico, mas talvez útil. Outra melhoria para suas solicitações de conteúdo em cache é armazenar em cache o sessionStorage, para que você não precise pedir ao servidor para validar o cache e receber um 304. Procure, por exemplo, google, abra o console e escreva sessionStorage. Você verá que eles estão armazenando em cache CSS ou DOM com o sessionStorage. ofc, você não pode usá-lo em navegadores antigos do IE.


0

Examine seu código-fonte e verifique se não há META REFRESH para fazer a transição para outra página. Use algo como sendRedirect. Na minha configuração, o META REFRESH produz 304s no IE, mas não no Chrome. O sendRedirect não produz isso em nenhum navegador.

<meta http-equiv="refresh" content="0;URL='nextpage'" />    

vs

<% response.sendRedirect("nextpage") %>
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.