Come posso precomprimere i file con mod_deflate in Apache 2.x?
-
09-06-2019 - |
Domanda
Sto servendo tutti i contenuti tramite Apache con Content-Encoding: zip
ma questo si comprime al volo.Una buona parte dei miei contenuti sono file statici sul disco.Voglio comprimere i file in anticipo anziché comprimerli ogni volta che vengono richiesti.
Questo è qualcosa che, credo, mod_gzip
lo faceva automaticamente in Apache 1.x, ma aveva solo il file con .gz accanto.Non è più così mod_deflate
.
Soluzione
Questa funzionalità era comunque fuori posto in mod_gzip.In Apache 2.x, lo fai con la negoziazione dei contenuti.Nello specifico, è necessario abilitare MultiViews
con il Options
direttiva ed è necessario specificare i tipi di codifica con il file AddEncoding
direttiva.
Altri suggerimenti
Per rispondere alla mia domanda con la riga davvero semplice che mi mancava nella mia configurazione:
Options FollowSymLinks MultiViews
Mi mancava l'opzione MultiViews.È presente nella configurazione predefinita del server Web di Ubuntu, quindi non fare come me e lascialo perdere.
Inoltre ho scritto una rapida attività Rake per comprimere tutti i file.
namespace :static do
desc "Gzip compress the static content so Apache doesn't need to do it on-the-fly."
task :compress do
puts "Gzipping js, html and css files."
Dir.glob("#{RAILS_ROOT}/public/**/*.{js,html,css}") do |file|
system "gzip -c -9 #{file} > #{file}.gz"
end
end
end
Temo che MultiViews non funzionerà come previsto:il documento dice che Multiviews funziona "se il server riceve una richiesta per /some/dir/foo, se /some/dir ha MultiViews abilitato e /some/dir/foo non esiste...", in altre parole:se hai un file foo.js e foo.js.gz nella stessa directory, la semplice attivazione di MultiViews non causerà l'invio del file .gz anche se l'intestazione gzip AcceptEncoding viene trasmessa dal browser (puoi verificare questo comportamento tramite disabilitando temporaneamente mod_deflate e monitorando la risposta con ad es.HTTPFox).
Non sono sicuro che ci sia un modo per aggirare questo problema con MultiViews (forse puoi rinominare il file originale e quindi aggiungere una speciale direttiva AddEncoding), ma credo che tu possa costruire una regola mod_rewrite per gestirlo.
Ho un Apache 2 creato dal sorgente e ho scoperto che dovevo modificare quanto segue nel mio file httpd.conf file:
Aggiungi MultiView alle Opzioni:
Options Indexes FollowSymLinks MultiViews
Decommenta AddEncoding:
AddEncoding x-compress .Z AddEncoding x-gzip .gz .tgz
Aggiungi tipo commento:
#AddType application/x-compress .Z #AddType application/x-gzip .gz .tgz
È possibile servire file precompressi utilizzando mod_negotiation
anche se è un po' complicato.La difficoltà principale è questa vengono negoziate solo le richieste di file che non esistono.Quindi se foo.js
E foo.js.gz
esistono entrambi, risposte per /foo.js
sarà sempre non compresso (sebbene le risposte per /foo
funzionerebbe correttamente).
La soluzione più semplice che ho trovato (di François Marier) consiste nel rinominare i file non compressi con una doppia estensione di file, quindi foo.js
è distribuito come foo.js.js
quindi richieste di /foo.js
negoziare tra foo.js.js
(nessuna codifica) e foo.js.gz
(codifica gzip).
Combino questo trucco con la seguente configurazione:
Options +MultiViews
RemoveType .gz
AddEncoding gzip .gz
# Send .tar.gz without Content-Encoding: gzip
<FilesMatch ".+\.tar\.gz$">
RemoveEncoding .gz
# Note: Can use application/x-gzip for backwards-compatibility
AddType application/gzip .gz
</FilesMatch>
IO ha scritto un post che discute in dettaglio il ragionamento per questa configurazione e alcune alternative.
mod_gzip anche il contenuto compresso al volo.Puoi precomprimere i file accedendo effettivamente al tuo server e facendolo dalla shell.
cd /var/www/.../data/
for file in *; do
gzip -c $file > $file.gz;
done;
Puoi usare mod_cache
per eseguire il proxy del contenuto locale in memoria o su disco.Non so se funzionerà come previsto con mod_deflate
.
Ho molti file .json di grandi dimensioni.La maggior parte dei lettori si trova in questa situazione.Le risposte in anteprima non parlavano del "tipo di contenuto" restituito.
Desidero che la seguente richiesta restituisca un file precompresso con "Content-Type:application/json" in modo trasparente, utilizzare Multiview con ForceType
http://www.domain.com/(...)/bigfile.json
-> Content-Encoding:gzip, Content-Type: Content-Encoding:gzip
1) i file devono essere rinominati:"file.ext.ext"
2) Multiview funziona alla grande con ForceType
Nel file system:
// Note there is no bigfile.json
(...)/bigfile.json.gz
(...)/bigfile.json.json
Nella configurazione di Apache:
<Directory (...)>
AddEncoding gzip .gz
Options +Multiviews
<Files *.json.gz>
ForceType application/json
</Files>
</Directory>
Breve e semplice :)