Apache не будет обслуживать ответы 304 Not Modified для статических файлов

Apache не будет обслуживать ответы 304 Not Modified для статических файлов

Я использую веб-сервер Apache, обслуживающий большие статические изображения из файловой системы. Я настроил сервер на возврат допустимого заголовка кэша, например так:Header merge Cache-Control "public, max-age=31536000, immutable"

Это все хорошо, но когда пользователь перезагружает изображение в браузере, Apache никогда не возвращает ответ 304 Not Modified.

Я выполнил эту команду curl (имя хоста я изменил в целях конфиденциальности):

curl -o /tmp/image.png -v -u test:example http://blah.example.com/static/images/covers/436g2gu94kxin4x7

Вот заголовки запроса от curl.

GET /static/images/covers/436g2gu94kxin4x7 HTTP/1.1
Host: blah.example.com
Authorization: Basic dGVzdDpleGFtcGxl
User-Agent: curl/7.64.1
Accept: */*
If-Modified-Since: Thu, 30 Apr 2020 02:21:47 GMT

Я ожидал ответ 304, но вместо этого получил:

HTTP/1.1 200 OK
Date: Fri, 28 Aug 2020 04:59:54 GMT
Server: Apache/2.4.25 (Debian)
Content-Type: image/png
Content-Length: 3115720
Last-Modified: Thu, 30 Apr 2020 02:21:47 GMT
Vary: Accept-Encoding
Cache-Control: public, max-age=31536000, immutable

Я прочиталРуководство по кэшированию Apache, но ничто из этого не имеет отношения к данной ситуации... все дело в настройке собственного кэша Apache, либо в памяти, либо на диске, особенно для поддержки случаев, когда Apache выступает в качестве обратного прокси-сервера для исходного сервера.

Но в этом случае файлы уже находятся на локальном диске. Исходного сервера нет. Я не хочу/не нуждаюсь в том, чтобы Apache хранил отдельную «кэшированную» копию файла; я просто хочу, чтобы Apache заметил, что дата Last-Modifiedфайла на диске совпадает с If-Modified-Sinceдатой, и 304 Not Modifiedв этом случае выполнил возврат.

Как мне это настроить? Нужно ли мне заставить Apache хранить свою собственную отдельную кэшированную копию файлов, чтобы включить условные GET? (Это будет очень большой кэш, предположительно, хранящийся на диске, что является пустой тратой времени.)

решение1

Во-первых, действительно ли это не кэширование?

Возможно, проблема в curl. Я утомил ваш код на URL, который, как я знаю, возвращает 304, и он всегда возвращает 200, используя ваш код выше. Вы пробовали инструменты разработчика веб-браузера? Пока не отмечено "отключить кэширование", вы сможете обновить свой URL и увидеть, что он возвращает 304 при втором обновлении.

Во-вторых, это может быть ошибка Apache.

Я не вижу заголовка ETag в ваших результатах. Если Apache действительно не добавляет это, то вы, вероятно, можете проигнорировать это. Но вы все равно можете попробовать добавить это в настройки Apache, просто на всякий случай:

<IfModule mod_headers.c>
    Header unset ETag
</IfModule>
FileETag None

(Обязательно включите мод заголовков с помощью a2enmod headers.)

Или, что еще лучше, если вы используете Apache версии 2.4.42 и более поздней ( apache2 -v), вы можете попробовать сделать это в своих настройках:

<IfModule mod_deflate.c>
    DeflateAlterETag NoChange
</IfModule>

Эта проблема была вызвана модулем deflate, который добавлял метод сжатия в конец ETag. Это заставляло Apache игнорировать кэширование и всегда возвращать 200. По их собственным словам, это:

...предотвращает отправку ответов «HTTP Not Modified» (304) на условные запросы сжатого контента.

Модуль Apache mod_deflate

Поэтому отключение этой функции может решить некоторые проблемы с кэшированием.

Связанный контент