Я пытаюсь принудительно кэшировать очень неприятный фрагмент PHP-скрипта, который без всяких на то оснований активно пытается сопротивляться кешированию, активно устанавливая все заголовки анти-кеша:
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Type: text/html; charset=UTF-8
Date: Thu, 22 May 2014 08:43:53 GMT
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Last-Modified:
Pragma: no-cache
Set-Cookie: ECSESSID=...; path=/
Vary: User-Agent,Accept-Encoding
Server: Apache/2.4.6 (Ubuntu)
X-Powered-By: PHP/5.5.3-1ubuntu2.3
Если это вообще можно избежать, я вообще не хочу изменять этот сторонний фрагмент кода, а вместо этого просто заставлю Apache на время кэшировать страницу. Я делаю это очень выборочно только для очень определенных страниц, которые не имеют реального влияния на файлы cookie сеанса и т.п., т.е. которые не содержат никакой персонализированной информации.
CacheDefaultExpire 600
CacheMinExpire 600
CacheMaxExpire 1800
CacheHeader On
CacheDetailHeader On
CacheIgnoreHeaders Set-Cookie
CacheIgnoreCacheControl On
CacheIgnoreNoLastMod On
CacheStoreExpired On
CacheStoreNoStore On
CacheLock On
CacheEnable disk /the/script.php
Apache - это кеширование страница в порядке:
[cache:debug] AH00698: cache: Key for entity /the/script.php?(null) is http://example.com:80/the/script.php?
[cache_disk:debug] AH00709: Recalled cached URL info header http://example.com:80/the/script.php?
[cache_disk:debug] AH00720: Recalled headers for URL http://example.com:80/the/script.php?
[cache:debug] AH00695: Cached response for /the/script.php isn't fresh. Adding conditional request headers.
[cache:debug] AH00750: Adding CACHE_SAVE filter for /the/script.php
[cache:debug] AH00751: Adding CACHE_REMOVE_URL filter for /the/script.php
[cache:debug] AH00769: cache: Caching url: /the/script.php
[cache:debug] AH00770: cache: Removing CACHE_REMOVE_URL filter.
[cache_disk:debug] AH00737: commit_entity: Headers and body for URL http://example.com:80/the/script.php? cached.
Однако он всегда настаивает на том, что «кешированный ответ не свежий» и никогда не обслуживает кешированную версию. я угадать это связано с Expires
заголовок, который отмечает документ как просроченный (но я не знаю, правильное ли это предположение). Я пытался перезаписать и сбросить заголовки с помощью mod_headers, но это не помогает; какую бы комбинацию я ни пробовал, кеш совершенно не впечатлил. Я предполагаю, что порядок работы неправильный, и заголовки переписываются после кеш их видит. early
обработка заголовка тоже не помогает. Я экспериментировал с CacheQuickHandler Off
и пытаюсь установить явные цепочки фильтров, но ничего не помогает. Но я действительно в основном ковыряюсь в темноте, так как у меня нет большого опыта настройки цепочек фильтров Apache.
Есть ли простое решение, как кэшировать этот неприятный фрагмент кода?
Пустой заголовок Last-Modified: делает запрос некэшируемым. Итак, первое, что нужно сделать, это создать его, одно из решений - использовать php auto_prepend_file
:
Создать файл prepend.php
с таким содержанием:
<?php header("Last-Modified:" . gmdate("D, d M Y H:i:s"), " GMT"); ?>
Затем добавьте в свою конфигурацию vhost директиву: php_value auto_prepend_file path_to_prepend.php
На этом этапе вы должны убедиться, что ответ сервера имеет правильный Last-Modified:
заголовок. В противном случае мы не сможем его кешировать, если да, может ваша работа с mod_headers и mod_cache теперь работает?
Если нет, вы можете использовать squid и apache следующим образом:
В вашем правильном vhost просто включите mod_rewrite
и используйте его для перенаправления трафика, который вы хотите кэшировать:
<VirtualHost your_current_virtual_host:80> ServerName your.site.com .. RewriteEngine on # This enables the caching server to see the request as http://your.site.com/.. ProxyPreserveHost on # This should be at VirtualHost level, not <Directory> or .htaccess # The DoSquid env variable decides if we send the request to the cache server # Adjust it for your needs RewriteRule /the/script.php - [E=DoSquid:Yes] # POSTs are not cacheable RewriteCond %{REQUEST_METHOD} ^POST$ RewriteRule .* - [E:DoSquid:No] # Feel free to add any rule which makes sense for your needs # Requests from localhost are calls from the "primary" vhost ( see below ) RewriteCond %{REMOTE_ADDR} ^127\.0\.0\.1$ [E:DoSquid:No] RewriteCond %{ENV:DoSquid} ^Yes$ RewriteRule /the/script.php http://ip_of_caching_server/this/script.php [P,L,QSA] .. .. <VirtualHost/> # This VirtualHost will be accessed by your caching server as the primary server for your site # Port 8009 can be anything, it just must be a separate virtual host <VirtualHost your_current_virtual_host:8009> ServerName your.site.com .. RewriteEngine on # Here a make a massive usage of mod_headers in order to have a cacheable response # Needless to say, this might completely break your application. The responses are # Completely anonymized Header unset Set-Cookie Header unset Etag Header unset Pragma RequestHeader unset Cookie # Now fix the Cache-Control header.. Header merge Cache-Control public # The max-age is a pain. We have to set one if it's not set, and we have to change it if it's 0 Header merge Cache-Control "max-age=bidon" # Case when we have: Cache-Control max-age=.., .... Header edit Cache-Control "^(.*)max-age=(.*)max-age=bidon, (.*)$" $1max-age=$2$3 # Case when we have: Cache-Control yyy=bidon, max-age=.." Header edit Cache-Control "^(.*)max-age=(.*), max-age=bidon$" $1max-age=$2 # Now Replace the value if there was not a max-age, set to 10mn Header edit Cache-Control "max-age=bidon" "max-age=600" # Now Replace the value if there was a max-age=0, set to 10mn Header edit Cache-Control "max-age=0" "max-age=600" # Remove Cache-Control parameters which prevent caching Header edit Cache-Control "no-cache, " "" Header edit Cache-Control "no-store, " "" Header edit Cache-Control "post-check=0, " "" Header edit Cache-Control "pre-check=0, " "" Header edit Cache-Control "must-revalidate, " "" # The request is now forwarded to the first vhost. It will not loop because we do not cache requests from 127.0.0.1 ProxyPreserveHost on RewriteRule ^(.*)$ http://127.0.0.1/$1 [P,L,QSA] .. .. <VirtualHost/>
Наверное, можно использовать что угодно: кальмар, апач, лак. с помощью squid вы должны настроить его как обратный прокси и объявить cache_peer your.site.com parent 8009 0 no-query originserver ..
Может быть, вы можете просто включить mod_cache
во втором vhost добиться желаемого.