adrianmak Posted March 2, 2015 Share Posted March 2, 2015 It's seems that pw core doesn't manipulate http header regarding caching. Therefore, putting a reverse proxy in front of a web server is taking no effect on caching. Could I write a module to plugin into pw to take care of http heder cache control ? or should it be done in pw's core ? Link to comment Share on other sites More sharing options...
teppo Posted March 3, 2015 Share Posted March 3, 2015 Easiest way to define custom headers is to do it in your .htaccess file, using mod_headers. WillyC's post about caching settings is a good example. 1 Link to comment Share on other sites More sharing options...
adrianmak Posted March 4, 2015 Author Share Posted March 4, 2015 Easiest way to define custom headers is to do it in your .htaccess file, using mod_headers. WillyC's post about caching settings is a good example. It is just for caching static file like css, js and images. I'm talking about caching a page instead Link to comment Share on other sites More sharing options...
LostKobrakai Posted March 4, 2015 Share Posted March 4, 2015 Before ProcessWire hands of to your templates' code it does not output any markup. So you should be able to change headers anytime before that and even in your templates' files if you're not outputting markup by yourself before that. Link to comment Share on other sites More sharing options...
teppo Posted March 4, 2015 Share Posted March 4, 2015 It is just for caching static file like css, js and images. I'm talking about caching a page instead Nope. That's just what the rules wrapped with FilesMatch-checks do. If you take a closer look, you'll spot that some rules are defined without any FilesMatch rules: <IfModule mod_headers.c> ... Header unset ETag Header append Cache-Control "public" </IfModule> Of course you can specify whatever value you want to for these headers. What @LostKobrakai mentioned above is possible too, but I mostly prefer to use that for headers that depend on very specific page settings, need to contain some page-specific details, etc. 1 Link to comment Share on other sites More sharing options...
adrianmak Posted March 4, 2015 Author Share Posted March 4, 2015 I'm added few lines of code for page/template required caching. $maxAge = 300; // 5mins header('Expires: '.gmdate('D, d M Y H:i:s', time() + $maxAge).' GMT', true); header('Cache-Control: public, max-age='.$maxAge, true); header('Pragma: ', true); And it is working fine. As we can see cached content is hit. However, when a page's content is updated, front-end users have to wait for the cache expire date in order to get the new content. In the above example. Users have to wait for 5 mins at most. Is there something to do, to let the reverse proxy cache know the requested url is updated. In order to fetch cached copy, a new copy should fetch to the user. Link to comment Share on other sites More sharing options...
adrianmak Posted March 5, 2015 Author Share Posted March 5, 2015 To find a way to make updating a page will let the reverse proxy cache know to grab a new copy. I found this article https://css-tricks.com/snippets/php/intelligent-php-cache-control/ The original code is <?php //get the last-modified-date of this very file $lastModified=filemtime(__FILE__); //get a unique hash of this file (etag) $etagFile = md5_file(__FILE__); //get the HTTP_IF_MODIFIED_SINCE header if set $ifModifiedSince=(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false); //get the HTTP_IF_NONE_MATCH header if set (etag: unique file hash) $etagHeader=(isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : false); //set last-modified header header("Last-Modified: ".gmdate("D, d M Y H:i:s", $lastModified)." GMT"); //set etag-header header("Etag: $etagFile"); //make sure caching is turned on header('Cache-Control: public'); //check if page has changed. If not, send 304 and exit if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])==$lastModified || $etagHeader == $etagFile) { header("HTTP/1.1 304 Not Modified"); exit; } //your normal code echo "This page was last modified: ".date("d.m.Y H:i:s",time()); ?> I modified a little bit. Instead of generate a md5 checksum from filename. I used to generate md5 from a URI the $etagFile will be $etagFile = md5($_SERVER['REQUEST_URI']; The caching works. After updating the php file content, I will get a new copy almost instantly Then I applied the same logic to a pw template. The pw site is using default multi-language installation profile. I applied the code on basic-page.php template with some modification The $lastModified var will get from a template field last_modified. This field will hook to a custom module, for every page save, this field will be update with the current date&time. The $etagFile var will get from $page->URL Then, the final code of basic-page.php will be <?php $lastModified=($page->last_modified); $etagFile = md5($page->url); $ifModifiedSince=(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false); $etagHeader=(isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : false); header("Last-Modified: ".gmdate("D, d M Y H:i:s", $lastModified)." GMT"); header("Etag: $etagFile"); header('Cache-Control: public'); //check if page has changed. If not, send 304 and exit if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])==$lastModified || $etagHeader == $etagFile) { header("HTTP/1.1 304 Not Modified"); exit; } // basic-page.php template file // Primary content is the page's body copy $content = $page->body; $content .= $etagFile; // for debug info // If the page has children, then render navigation to them under the body. // See the _func.php for the renderNav example function. if($page->hasChildren) $content .= renderNav($page->children, 0, 'summary'); // if the rootParent (section) page has more than 1 child, then render // section navigation in the sidebar if($page->rootParent->hasChildren > 1) { $sidebar = renderNav($page->rootParent, 3) . $page->sidebar; } Everything all set. Clicking several page refresh,The response header always showing X-Cache-Stauts MISS That's mean the page is not cached obviously. Link to comment Share on other sites More sharing options...
adrianmak Posted March 6, 2015 Author Share Posted March 6, 2015 To simplify my test, I eliminated prependTemplateFile and appendTemplateFile file, and in the basic-page.php template, output the content body directly. No other content. But page is still not be cached. I'm not sure it is a pw's problem (may be need special nginx tweaks to work with pw) anybody could help ? /etc/nginx/nginx.conf user www-data; worker_processes 4; pid /run/nginx.pid; events { worker_connections 768; # multi_accept on; } http { ## # Basic Settings ## sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; # server_tokens off; # server_names_hash_bucket_size 64; # server_name_in_redirect off; include /etc/nginx/mime.types; default_type application/octet-stream; ## # Content caching ## include /etc/nginx/cache.conf; ## # Logging Settings access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; gzip_vary on; # gzip_proxied any; # gzip_comp_level 6; # gzip_buffers 16 8k; # gzip_http_version 1.1; # gzip_types text/plain text/css application/json application/x-javascript text/xm l application/xml application/xml+rss text/javascript; ## # nginx-naxsi config ## # Uncomment it if you installed nginx-naxsi ## #include /etc/nginx/naxsi_core.rules; ## # nginx-passenger config ## # Uncomment it if you installed nginx-passenger ## #passenger_root /usr; #passenger_ruby /usr/bin/ruby; ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } /etc/nginx/cache.conf proxy_cache_path /etc/nginx/cache levels=1:2 keys_zone=one:100m inactive=60m loader_threshold=300 loader_files=200 max_size=200m; proxy_cache_key "$scheme$proxy_host$uri$is_args$args"; /etc/nginx/sites-available/default.conf server { listen 80 default_server; proxy_cache one; add_header X-Cache-Status $upstream_cache_status; proxy_cache_valid any 1m; proxy_cache_min_uses 3; ##proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment; root /var/www/html; index index.php index.html index.htm; # Make site accessible from http://localhost/ server_name dev.local.net; location / { try_files $uri $uri/ /index.php?it=$uri&$args; } location ~ \.php$ { # First attempt to serve request as file, then # as directory, then fall back to displaying a 404. #try_files $uri $uri/ /index.php; # Uncomment to enable naxsi on this location # include /etc/nginx/naxsi.rules #add_header X-Cache-Status $upstream_cache_status; #proxy_cache_valid any 1m; #proxy_cache_min_uses 3; #proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment; proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } location ~ /\. { deny all; } } Link to comment Share on other sites More sharing options...
adrianmak Posted March 6, 2015 Author Share Posted March 6, 2015 will pw send cookie to anonymous users ? Link to comment Share on other sites More sharing options...
Recommended Posts