2009-05-22 10 views
22

Ho aggiunto la seguente linea nel mio httpd.conf Apache: -Apache non sta inviando 304 risposta (se mod_deflate e AddOutputFilterByType è abilitato)

AddOutputFilterByType DEFLATE text/html text/css application/javascript application/x-javascript application/json 

Ho un file html (test.html) con un script di inclusione: -

<script type="text/javascript" src="/test.js"></script> 

Il problema è che ogni volta che carico test.html, test.js è anche caricato con stato HTTP: 200.

La domanda è: perché i GET condizionale non è soddisfatto?

Se io commentare la riga "AddOutputFilterByType" in httpd.conf, Apache invia 304.

Se permetto AddOutputFilterByType in httpd.conf, l'intestazione di richiesta è: -

 
Host: optimize 
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 GTB5 (.NET CLR 3.5.30729) FirePHP/0.2.4 
Accept: */* 
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 
Keep-Alive: 300 
Connection: keep-alive 
Referer: http://optimize/ 
Cookie: PHPSESSID=nbq6h0eeahkshkcbc6ctu2j2b4 
If-Modified-Since: Tue, 19 May 2009 07:06:46 GMT 
If-None-Match: "2000000000717f-2c25a-46a3e8dcc2ad8"-gzip 
Cache-Control: max-age=0 

E l'intestazione di risposta è: -

 
Date: Fri, 22 May 2009 07:03:40 GMT 
Server: Apache/2.2.9 (Win32) PHP/5.2.6 
Last-Modified: Tue, 19 May 2009 07:06:46 GMT 
Etag: "2000000000717f-2c25a-46a3e8dcc2ad8"-gzip 
Accept-Ranges: bytes 
Vary: Accept-Encoding 
Content-Encoding: gzip 
Content-Length: 52583 
Keep-Alive: timeout=5, max=98 
Connection: Keep-Alive 
Content-Type: application/javascript 

UPDATE: ho notato, se io sono la disabilitazione ETag, funziona correttamente Voglio dire che manda 304.

FileETag None 

Ma ci tengo a mantenere ETag come lo è (lo so che c'è un problema di divulgazione inode).

+1

Hai mai trovato una soluzione alternativa? Apache 2.4 sembra fare lo stesso, inviando sempre 200 risposte per contenuti gzip – virtualeyes

+0

Qualche ragione per cui vuoi mantenere gli ETags? Non c'è alcun reale punto di averli se si sta solo servendo contenuto statico che ha già una data 'Last-Modified' per la riconvalida. Sicuramente, la loro scelta sarebbe la soluzione più semplice e conforme a RFC per ora. –

+0

Gli ETAG * sono * necessari *.Se si desidera sostituire il contenuto con una versione precedente (ad esempio, il file javascript che doveva essere ripristinato in una versione precedente senza un bug introdotto) e quando si ripristina la data precedente del file, un semplice confronto delle date non sarà sufficiente . –

risposta

0

Forse si utilizza un proxy (squid), che manipola le richieste HTTP?

+0

No, non sto usando alcun proxy. Ci sto provando anche nel mio localhost. Stesso risultato – Sabya

19

Questo è un bug noto in Apache. Vedere Apache bug #45023, e summary of Apache 304 etags and mod_deflate.

Ricostruire da svn risolverà il problema. La risoluzione era di annullare la modifica aggiunta "-gzip" all'etag. Tuttavia, vi sono problemi di conformità HTTP associati.

Se non è possibile ricostruire Apache, c'è una soluzione di configurazione runtime suggerito nella relazione bug:

RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\"" 
Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\"" 
+3

Su Apache 2.4, nient'altro che "200 OK" risposte: questa soluzione funziona davvero? – virtualeyes

+3

Questo è ANCORA un problema e non ho potuto andare oltre a lavorare (in Apache 2.4.7). Tuttavia, dopo un po 'di ricerche, ho anche deciso che gli ETag non sono comunque utili in Apache. Un ETag sarebbe molto utile se fosse un hash dei contenuti, quindi anche se il timestamp è cambiato, può ancora essere usato per decidere se i contenuti non lo sono. Per Apache l'ETag è una combinazione di inode, dimensioni e ultimi dati modificati (con dimensioni e ultimi valori modificati utilizzati per impostazione predefinita). Quindi, poiché utilizza gli attributi di file, piuttosto che un hash dei contenuti, ho deciso di disattivarlo e utilizzare invece Last-Modified. –

+2

Questo sembra essere ANCORA un problema? Sto usando Apache 2.4.10 – Inna

8

"Ho anche deciso che ETags non sono così utili in Apache comunque. "

sbagliato,
ad esempio si dispone di un file con data di modifica impostata su '2016.07.27 05:00:00', si carica al tuo sito, il browser ottiene questo file con codice HTTP 200, quindi memorizza nella cache e riconvalida ogni volta con HTTP 304.
successivo si carica un file con lo stesso nome del file di nuovo, ma con il timestamp più vecchio '2013.07.27 05:00:00' e con altri contenuti.

Se ETag è disabilitato sul server, il browser utilizzerà solo la richiesta If-Modified-Since: per determinare se il file è stato modificato sul server, quindi la richiesta sarà If-Modified-Since: 2016.07.27 05:00:00, ma il file non verrà modificato dopo questa data, quindi verrà restituito un HTTP 304, anche se il file è cambiato.

Se ETag è abilitato sul server, oltre a If-Modified-Since:, ci sarà un'intestazione If-None-Match: proveniente dal browser che rileverà che il file è stato modificato (per impostazione predefinita - mancata corrispondenza di data e ora) e il file verrà riscaricato.


Questo problema esiste ancora in Apache 2.4.23, quindi, ho scritto un codice migliore di sopra per risolvere questo problema. Spiegazione riga per riga:

    1) Se il browser invia una richiesta 'If-None-Match' che ha '-gzip' alla fine, impostare la variabile request_etag = gzip.
    2) Modificare l'intestazione della richiesta per rimuovere la parte '-gzip'.
    3) Modificare l'intestazione della risposta per aggiungere la parte '-gzip', ma solo se il browser invia inizialmente una richiesta '-gzip' o se il contenuto della risposta è codificato con gzip.


È possibile utilizzare uno lookahead negativo o lookbehind negativo, la velocità regex è lo stesso, Apache supporta entrambi

\"(.+(?<!-gzip))\"  #using negative lookbehind 
\"((?:.(?!-gzip\"))+)\" #using negative lookahead 

Casi di test:

    "2e2 -5388f9f70c580-afeg "
    "2e2-5388f9f70c580-Gzin"
    "2e2-5388f9f70c580-gzipd"
    "2e2-5388f9f70c580gzip"
    "2e2-5388f9f70c580gzip"

Copia-Incolla questo codice in Apache .conf

SetEnvIf   If-None-Match "-gzip\"$" request_etag=gzip 
RequestHeader edit If-None-Match "(.+)-gzip\"$" "$1\"" 
Header edit  ETag  "(.+(?<!-gzip))\"$" "$1-gzip\"" "expr=reqenv('request_etag') == 'gzip' || resp('Content-Encoding') == 'gzip'" 


Personalmente utilizzo il seguente codice, che inizialmente rimuove la parte '-gzip' se è una risposta gzip e non la ripresenta, quindi il browser non invierà mai un'intestazione '-gzip' 'If-None-Match'.

Header edit ETag "(.+)-gzip\"$" "$1\"" "expr=resp('Content-Encoding') == 'gzip'" 
+0

Il problema esiste ancora in Apache 2.4.25. Il codice a 3 righe sopra mi ha aiutato ma avevo bisogno di abilitare 'headers_module'. – ilhan

Problemi correlati