Como posso pré-compactar arquivos com mod_deflate no Apache 2.x?

Eu estou servindo todo o conteúdo através do apache com Content-Encoding: zip mas que comprime na hora. Uma boa parte do meu conteúdo é arquivos estáticos no disco. Eu quero gzip os arquivos de antemão em vez de comprimi-los toda vez que eles são solicitados.

Isso é algo que, creio eu, mod_gzip fez no Apache 1.x automaticamente, mas apenas tendo o arquivo com .gz próximo a ele. Isso não é mais o caso com mod_deflate .

Esta funcionalidade foi perdida no mod_gzip de qualquer maneira. No Apache 2.x, você faz isso com a negociação de conteúdo . Especificamente, você precisa habilitar MultiViews com a diretiva Options e precisa especificar seus tipos de codificação com a diretiva AddEncoding .

Para responder a minha própria pergunta com a linha realmente simples que faltava em minha confiuração:

 Options FollowSymLinks MultiViews 

Eu estava faltando a opção MultiViews. Ele está lá na configuração do servidor web padrão do Ubuntu, então não seja como eu e deixe-o desligado.

Também escrevi uma tarefa rápida de Rake para compactar todos os arquivos.

 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 

Eu tenho um Apache 2 construído a partir do código-fonte e descobri que tinha que modificar o seguinte no meu arquivo httpd.conf :

Adicione MultiViews às opções:

 Options Indexes FollowSymLinks MultiViews 

AddEncoding Uncomment:

 AddEncoding x-compress .Z AddEncoding x-gzip .gz .tgz 

Comentário AddType:

 #AddType application/x-compress .Z #AddType application/x-gzip .gz .tgz 

Receio que o MultiViews não funcionará como esperado: o documento diz que o Multiviews funciona “se o servidor receber um pedido para / some / dir / foo, se / some / dir tiver o MultiViews ativado e / algum / dir / foo não existir. .. “, em outras palavras: se você tiver um arquivo foo.js e foo.js.gz no mesmo diretório, apenas ativar MultiViews não fará com que o arquivo .gz seja enviado, mesmo que o header AcceptEncoding gzip seja transmitido pelo navegador (você pode verificar esse comportamento desativando temporariamente o mod_deflate e monitorando a resposta com, por exemplo, HTTPFox).

Eu não tenho certeza se há uma maneira de contornar isso com MultiViews (talvez você possa renomear o arquivo original e, em seguida, adicionar uma diretiva especial AddEncoding), mas eu acredito que você pode construir uma regra mod_rewrite para lidar com isso.

É possível servir arquivos pré-compactados usando mod_negotiation embora seja um pouco complicado. A principal dificuldade é que apenas as solicitações de arquivos que não existem são negociadas . Portanto, se foo.js e foo.js.gz existirem, as respostas para /foo.js sempre serão descompactadas (embora as respostas para /foo funcionem corretamente).

A solução mais fácil que encontrei ( de François Marier ) é renomear os arquivos descomprimidos com uma extensão de arquivo duplo, então o foo.js é implementado como foo.js.js então pedidos de /foo.js negociam entre foo.js.js ( sem codificação) e foo.js.gz (codificação gzip).

Eu combino esse truque com a seguinte configuração:

 Options +MultiViews RemoveType .gz AddEncoding gzip .gz # Send .tar.gz without Content-Encoding: gzip  RemoveEncoding .gz # Note: Can use application/x-gzip for backwards-compatibility AddType application/gzip .gz  

Eu escrevi um post que discute o raciocínio para essa configuração e algumas alternativas em detalhes.

mod_gzip compactou o conteúdo na hora também. Você pode pré-compactar os arquivos, fazendo login no seu servidor e fazendo isso a partir do shell.

 cd /var/www/.../data/ for file in *; do gzip -c $file > $file.gz; done; 

Você pode usar o mod_cache para proxy de conteúdo local na memory ou no disco. Eu não sei se isso funcionará como esperado com mod_deflate .

Eu tenho muitos arquivos .json grandes. A maioria dos leitores está nessa situação. As respostas de visualização não falaram sobre o “tipo de conteúdo” retornado.

Eu quero o seguinte pedido retornar um arquivo pré-compactado com “Content-Type: application / json” de forma transparente, use Multiview com ForceType

 http://www.domain.com/(...)/bigfile.json -> Content-Encoding:gzip, Content-Type: Content-Encoding:gzip 

1) os arquivos devem ser renomeados: “file.ext.ext”

2) Multiview funciona muito bem com o ForceType

No sistema de arquivos:

 // Note there is no bigfile.json (...)/bigfile.json.gz (...)/bigfile.json.json 

Na sua configuração do apache:

  AddEncoding gzip .gz Options +Multiviews  ForceType application/json   

Curto e simples 🙂