Como saber quando para enviar uma resposta 304 não modificado

votos
10

Eu estou escrevendo um método de manipulação de recursos onde eu controlar o acesso a vários arquivos, e eu gostaria de ser capaz de fazer uso de cache do navegador. A minha pergunta é dupla:

  1. Quais os cabeçalhos HTTP definitivas que eu preciso verificar, a fim de saber com certeza se eu deveria enviar uma resposta 304, e o que eu estou procurando quando eu vê-los?

  2. Além disso, existem cabeçalhos que eu preciso para enviar quando eu inicialmente enviar o arquivo (como 'Last-Modified') como uma resposta 200?

Alguns pseudo-código provavelmente seria a resposta mais útil.


E sobre o cabeçalho de controle de cache? Pode os vários valores possíveis de que afetam o que você envia para o cliente (ou seja, máximo de idade) ou se apenas se-Modified-Since ser obedecida?

Publicado 07/08/2008 em 08:54
fonte usuário
Em outras línguas...                            


5 respostas

votos
8

Aqui está como eu implementou. O código tem vindo a trabalhar para um pouco mais de um ano e com vários navegadores, então eu acho que é bastante confiável. Isto é baseado no RFC 2616 e observando o que e quando os vários navegadores estavam enviando.

Aqui está o pseudocódigo:

server_etag = gen_etag_for_this_file (meuarquivo)
etag_from_browser = get_header ( "Etag")

se etag_from_browser não existe:
    etag_from_browser = get_header ( "If-None-Match")
se o navegador citou o etag:
    extraem as aspas (por exemplo, "foo" -> foo)

conjunto server_etag em cabeçalho HTTP

se etag_from_browser corresponde server_etag
    enviar 304 código de retorno para o navegador

Aqui está um trecho da minha lógica do servidor que lida com isso.

/ * O cliente deve definir tanto Etag ou If-None-Match * /
/ * Alguns clientes citar o parm, citações tira se assim for * /
mketag (etag, & SB);

etagin = apr_table_get (r-> headers_in, "Etag");
se (etagin == NULL)
    etagin = apr_table_get (r-> headers_in, "If-None-Match");
if (etag! = NULL && etag [0] == ''') {
    int SL; 
    sl = strlen (GATE);
    memmove (etag, etag + 1, sl + 1);
    etag [sl-2] = 0;
    logit (2, "etag =:% s:", GATE);
}   
... 
apr_table_add (r-> headers_out, "ETag", etag);
... 
if (etagin! = NULL && strcmp (etagin, etag) == 0) {
    / * Se o etag corresponde, voltamos a 304 * /
    rc = HTTP_NOT_MODIFIED;
}   

Se você quer alguma ajuda com pós geração etag outra pergunta e eu vou desenterrar algum código que faz isso bem. HTH!

Respondeu 07/08/2008 em 09:30
fonte usuário

votos
4

A 304 resposta não modificado pode resultar de um pedido GET ou HEAD com qualquer um If-Modified-Since ( "IMS") ou um cabeçalho If-Not-Match ( "INM").

A fim de decidir o que fazer quando você recebe esses cabeçalhos, imagine que você está lidando com a solicitação GET sem esses cabeçalhos condicionais. Determinar que os valores de sua ETag e cabeçalhos Last-Modified estaria nessa resposta e usá-los para tomar a decisão. Esperamos que você tenha construído seu sistema de tal forma que determinar isso é menos caro do que construir a resposta completa.

Se houver um INM e o valor desse cabeçalho é o mesmo que o valor que você colocaria na ETag, em seguida, responder com 304.

Se houver um IMS e o valor da data em que o cabeçalho é mais tarde do que o que você colocaria no Last-Modified, então responder com 304.

Else, proceder como se o pedido não continha esses cabeçalhos.

Para uma abordagem menos esforço para a parte 2 da sua pergunta, descobrir qual o (expirar, ETag, e Last-Modified) cabeçalhos você pode facilmente e corretamente produzir em sua aplicação Web.

Para material de leitura sugerida:

http://www.w3.org/Protocols/rfc2616/rfc2616.html

http://www.mnot.net/cache_docs/

Respondeu 09/08/2008 em 14:27
fonte usuário

votos
3

Você deve enviar um 304 se o cliente declarou explicitamente que ele já pode ter a página em seu cache. Isso é chamado de GET condicional, que deve incluir o If-Modified-Since cabeçalho no pedido.

Basicamente, este cabeçalho de solicitação contém uma data a partir da qual o cliente alega ter uma cópia em cache. Você deve verificar se o conteúdo mudou depois dessa data e enviar um 304 se não tem.

Veja http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 para a respectiva secção na RFC.

Respondeu 07/08/2008 em 09:01
fonte usuário

votos
2

Estamos também a manipulação em cache, mas garantiu, recursos. Se você enviar / gerar um cabeçalho ETag (que RFC 2616 seção 13.3 recomenda que você deve), então o cliente deve usá-lo em uma solicitação condicional (tipicamente em uma If-None-Match - HTTP_IF_NONE_MATCH - cabeçalho). Se você enviar um cabeçalho Last-Modified (novamente você deve), então você deve verificar o If-Modified-Since - header - HTTP_IF_MODIFIED_SINCE. Se você enviar ambos, então o cliente deve enviar ambos, mas ele deve enviar o ETag. Observe também que validtion está apenas definido como verificar os cabeçalhos condicionais para estrita igualdade contra os que você iria enviar para fora. Além disso, apenas um validador forte (tal como uma eTag) vai ser utilizado para solicitações à distância (em que apenas uma parte de um recurso é solicitada).

Na prática, uma vez que os recursos que estão protegendo são bastante estática, e uma segunda vez lag é aceitável, estamos fazendo o seguinte:

  1.  Verifique se o usuário está autorizado a acessar o recurso solicitado

         Se eles não são, redirecioná-los ou enviar uma resposta 4xx conforme apropriado. Vamos gerar 404 respostas às solicitações que se parecem com as tentativas de hack ou tentativas flagrantes para realizar uma corrida final de segurança.

  2.  Comparar o If-Modified-Since cabeçalho para o cabeçalho Last-Modified gostaríamos de enviar (veja abaixo) para igualdade estrita

         Se forem iguais, envie um processamento de resposta e página de saída não modificado 304

  3.  Criar um cabeçalho Last-Modified usando o tempo de modificação do recurso solicitado

        Olhe para cima o formato HTTP Data em RFC 2616

  4.  Enviar o conteúdo do cabeçalho e de recursos, juntamente com um apropriado Content-Type

Decidimos evitar o cabeçalho ETag uma vez que é um exagero para os nossos propósitos. Suponho que também poderia usar apenas o carimbo de data e hora como um ETag. Se passar para um sistema ETag verdade, nós provavelmente iria armazenar hashes calculadas para os recursos e utilizá-las como ETags.

Se os recursos são gerados dinamicamente, a partir do conteúdo do banco de dados digamos, em seguida, ETags pode ser melhor para suas necessidades, uma vez que são apenas texto a ser povoada como você vê o ajuste.

Respondeu 13/10/2009 em 15:05
fonte usuário

votos
1

sobre cache-control:

Você não deveria ter que se preocupar com o cache-controle quando servindo para fora, diferente de defini-lo como um valor razoável. É basicamente dizendo ao navegador e outras entidades a jusante (como um proxy) o tempo máximo que deve decorrer antes do tempo limite do cache.

Respondeu 07/08/2008 em 09:47
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more