Как настроить правильное кэширование в Apache?

Здравствуйте, уважаемые тостеровцы!

На разрабатываемом сайте обнаружил странную проблему с кэшированием изображений, css-, js-файлов.

На сервере использую LAMP:
- Debian GNU/Linux 7.5 (wheezy).
- Apache 2.2.22 (загруженные модули: alias, auth_basic, authn_file, authz_default, authz_groupfile, authz_host, authz_user, autoindex, cgid, deflate, dir, env, expires, fcgid, headers, mime, negotiation, reqtimeout, rewrite, setenvif, ssl, status, suexec, unique_id, xsendfile).
- PHP 5.4.4-14+deb7u11 (cgi-fcgi).

В директории с изображениями разместил файл .htaccess следующего содержания:
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
    Header append Cache-Control "public"
</IfModule>

При первом запросе страницы серверу передаются следующие заголовки:
GET /images/some_image.png HTTP/1.1
Host:            example.com
User-Agent:      Mozilla/5.0 (Windows NT 6.3; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Accept:          image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer:         https://example.com/
Connection:      keep-alive
Pragma:          no-cache
Cache-Control:   no-cache

И сервер отвечает следующим образом:
HTTP/1.1 200 OK
Date:            Tue, 01 Jul 2014 10:33:49 GMT
Server:          Apache/2.2.22 (Debian)
Last-Modified:   Mon, 09 Jun 2014 19:29:59 GMT
Etag:            "2016e1-50b-4fb6c3ca9a6b1"
Accept-Ranges:   bytes
Content-Length:  1291
Cache-Control:   max-age=2592000, public
Expires:         Thu, 31 Jul 2014 10:33:49 GMT
X-Frame-Options: sameorigin
Keep-Alive:      timeout=5, max=100
Connection:      Keep-Alive
Content-Type:    image/png

Как видно из них, сервер корректно устанавливает заголовки «Cache-Control» и «Expires».
При повторном запросе, когда изображение уже должно находиться в кэше, почему-то все равно отправляется запрос на сервер:
GET /images/some_image.png HTTP/1.1
Host:               example.com
User-Agent:         Mozilla/5.0 (Windows NT 6.3; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0
Accept:             image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language:    ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding:    gzip, deflate
Referer:            https://example.com/
Connection:         keep-alive
If-Modified-Since:  Mon, 09 Jun 2014 19:29:59 GMT
If-None-Match:      "2016e1-50b-4fb6c3ca9a6b1"
Cache-Control:      max-age=0

И вот здесь меня смущает «Cache-Control: max-age=0». Так должно быть?

Ответ от сервера:
HTTP/1.1 304 Not Modified
Date:          Tue, 01 Jul 2014 10:48:10 GMT
Server:        Apache/2.2.22 (Debian)
Connection:    Keep-Alive
Keep-Alive:    timeout=5, max=98
Etag:          "2016e1-50b-4fb6c3ca9a6b1"
Expires:       Thu, 31 Jul 2014 10:48:10 GMT
Cache-Control: max-age=2592000, public

Соответственно, это каждый раз вызывает задержку при отображении картинок.
Подскажите, пожалуйста, в чем может быть проблема? В какую сторону копать?
Заранее спасибо!
  • Вопрос задан
  • 9845 просмотров
Пригласить эксперта
Ответы на вопрос 3
MaXComp
@MaXComp
интересуюсь frontend html+css+JS+php. Linux, C
Может так, как универсальное решение.

.htaccess

<ifModule mod_headers.c>
    #кэшировать html и htm файлы на один день
    <FilesMatch "\.(html|htm)$">
        Header set Cache-Control "max-age=43200"
    </FilesMatch>
    #кэшировать css, javascript и текстовые файлы на одну неделю
    <FilesMatch "\.(js|css|txt)$">
        Header set Cache-Control "max-age=604800"
    </FilesMatch>
    #кэшировать флэш и изображения на месяц
    <FilesMatch "\.(flv|swf|ico|gif|jpg|jpeg|png)$">
        Header set Cache-Control "max-age=2592000"
    </FilesMatch>
    #отключить кэширование
    <FilesMatch "\.(pl|php|cgi|spl|scgi|fcgi)$">
        Header unset Cache-Control
    </FilesMatch>
</IfModule>
<ifModule mod_expires.c>
    ExpiresActive On
    #по умолчанию кеш в 5 секунд
    ExpiresDefault "access plus 5 seconds"
    #кэшировать флэш и изображения на месяц
    ExpiresByType image/x-icon "access plus 2592000 seconds"
    ExpiresByType image/jpeg "access plus 2592000 seconds"
    ExpiresByType image/png "access plus 2592000 seconds"
    ExpiresByType image/gif "access plus 2592000 seconds"
    ExpiresByType application/x-shockwave-flash "access plus 2592000 seconds"
    #кэшировать css, javascript и текстовые файлы на одну неделю
    ExpiresByType text/css "access plus 604800 seconds"
    ExpiresByType text/javascript "access plus 604800 seconds"
    ExpiresByType application/javascript "access plus 604800 seconds"
    ExpiresByType application/x-javascript "access plus 604800 seconds"
    #кэшировать html и htm файлы на один день
    ExpiresByType text/html "access plus 43200 seconds"
    #кэшировать xml файлы на десять минут
    ExpiresByType application/xhtml+xml "access plus 600 seconds"
</ifModule>
Ответ написан
Комментировать
RicoX
@RicoX
Ушел на http://ru.stackoverflow.com/
Почему не хотите раздавать статику и кешировать через фронтенд на nginx?
Ответ написан
@neol
Если повторный запрос делается методом нажатия на F5, то это нормально. В таком случае браузер (как минимум chrome и ff ) проверяет, что данные актуальны. Если просто ходить по сайту, то контент будет браться из кеша без проверки.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы