Получите Apache для автоматической распаковки файла, но только при необходимости

Я бы хотел, чтобы все статические файлы моего веб-сервера были локально сжаты, и обслуживать их либо сжатыми, либо нет, в зависимости от запроса.

Ответы в разделе Как предварительно сжать файлы с помощью mod_deflate в Apache 2.x?, близко, так как действительно, включив MultiViews и используя правильное AddEncoding, я могу заставить Apache вернуть мне сжатый foo.tar.gz файл с моего веб-сервера, когда я запрашиваю foo.tarи это идет с надлежащим Content-Encoding: заголовок.

Но это работает только если клиент включает Accept-Encoding: gzip в заголовках он отправляет на сервер. OTOH, если клиент не поддерживает кодировку gzip, мой сервер просто говорит мне, что нет "приемлемого" foo.tar для меня.

Я могу заставить Apache распаковать этот tarball перед отправкой, если я использую AddOutputFilter INFLATE tar, Но если я это сделаю, то сервер также распаковывает содержимое, когда я запрашиваю foo.tar.gz (или когда я указываю, что принимаю кодировку gzip), чего я явно не хочу.

Так как же заставить Apache распаковывать файлы, когда клиент не поддерживает кодировку содержимого gzip, а обслуживает предварительно сжатый файл в других случаях?

РЕДАКТИРОВАТЬ: Основываясь на предложении @covener, я попробовал следующее:

AddEncoding x-gzip .gz .tgz
RemoveType application/x-gzip .gz .tgz
AddType application/x-tar .tgz

<Location /packages>
  FilterDeclare smgunzip CONTENT_SET
  FilterProvider smgunzip INFLATE req=Accept-Encoding !$gzip
  FilterChain smgunzip
</Location>

[Используя Apache-2.2.22 здесь. ] Но результат на самом деле хуже, чем с первыми тремя строками: когда я запрашиваю файл.tar.gz, он теперь возвращается без "Content-Encoding:", а когда я запрашиваю файл.tar, я получаю содержимое tar.gz (т.е. все еще сжатое) независимо от заголовка "Accept-Encoding:" и без содержимого "Content-Encoding:".

2 ответа

Решение

(убедитесь, что у вас есть AddEncoding gzip или x-gzip gz, иначе он сломается)

2,4:

<Directory /home/covener/SRC/2.4.x/built/htdocs>
  Options +MultiViews
  MultiviewsMatch Any
  FilterDeclare gzip CONTENT_SET
  FilterProvider gzip INFLATE "! req('Accept-Encoding') =~ /gzip/"
  FilterChain gzip
</Directory>

2,2:

<Directory /home/covener/SRC/2.2.x/built/htdocs>
  Options +MultiViews
  MultiviewsMatch Any
  FilterDeclare gzip CONTENT_SET
  FilterProvider gzip INFLATE req=Accept-Encoding !$gzip
  FilterChain gzip
</Directory>

Попробуй это:

      DirectoryIndex "index.html.gz" "index.html"

# Don't list the compressed files in directory indexes - you probably don't want to expose
# the .gz URLs to the outside. They're also misleading, since requesting them will give the
# original files rather than compressed ones.
IndexIgnore "*.html.gz" "*.css.gz"

RewriteEngine On

# Rewrite requests for .html/.css files to their .gz counterparts, if they exist.
RewriteCond "%{DOCUMENT_ROOT}%{REQUEST_FILENAME}.gz" -s
RewriteRule "^(.*)\.(html|css)$" "$1\.$2\.gz" [QSA]

# Serve compressed HTML/CSS with the correct Content-Type header.
RewriteRule "\.html\.gz$" "-" [T=text/html,E=no-gzip:1]
RewriteRule "\.css\.gz$"  "-" [T=text/css,E=no-gzip:1]

# Define a filter which decompresses the content using zcat.
# CAVEAT: This will fork a new process for every request made by a client that doesn't
# support gzip compression (most browsers do), so may not be suitable if you're running a
# very busy site.
ExtFilterDefine zcat cmd="/bin/zcat -"

<FilesMatch "\.(html|css)\.gz$">
  <If "%{HTTP:Accept-Encoding} =~ /gzip/">
    # Client supports gzip compression - pass it through.
    Header append Content-Encoding gzip
  </If>
  <Else>
    # Client doesn't support gzip compression - decompress it.
    SetOutputFilter zcat
  </Else>

  # Force proxies to cache gzipped & non-gzipped css/js files separately.
  Header append Vary Accept-Encoding
</FilesMatch>

Заимствовано Дэниэлом Коллинзом, « Обслуживание статического содержимого, сжатого с помощью gzip, с помощью Apache» .

Другие вопросы по тегам