r4331 HTTP-cache headers support for static content returned by module=chrome
authorAlexey Andriyanov <alan@al-an.info>
Sat, 12 Mar 2011 20:00:27 +0000 (20:00 +0000)
committerAlexey Andriyanov <alan@al-an.info>
Sat, 12 Mar 2011 20:00:27 +0000 (20:00 +0000)
checkCachedResponse: former checkIMSCondition, sets Cache-Control and Last-Modified headers
HTTPDateToUnixTime: moved from render_image.php to the new file caching.php
proxyStaticURI: adapded to support caching
dispatchImageRequest: no more setting of http headers for caching: now checkCachedResponse is resposible for that
index.php: handler of 'image' supports caching for 'progressbar'

wwwroot/inc/caching.php [new file with mode: 0644]
wwwroot/inc/functions.php
wwwroot/inc/render_image.php
wwwroot/index.php

diff --git a/wwwroot/inc/caching.php b/wwwroot/inc/caching.php
new file mode 100644 (file)
index 0000000..aa77b0c
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/*
+*
+*  This file is a library of HTTP cache functions.
+*  Intended to be small and effective and to be included only for some request types.
+*
+*/
+
+// if client passes If-Modified-Since header, and it is greater or equal to $creation_ts, and 
+// $expire seconds not elapsed since IMS, the function sends HTTP-304 with $creation_ts
+// returns TRUE on cache-hit, FALSE otherwise. Calling side should call exit if the result is TRUE.
+function checkCachedResponse ($creation_ts, $expire)
+{
+
+       $client_time = HTTPDateToUnixTime (@$_SERVER['HTTP_IF_MODIFIED_SINCE']);
+       $server_time = time();
+       $result = 
+       (
+               $client_time !== FALSE && $client_time !== -1 && // IMS header is readable
+               ! in_array ('no-cache', preg_split ('/\s*,\s*/', @$_SERVER['HTTP_CACHE_CONTROL'])) && // no-cache parameter unset
+               $client_time <= $server_time && // not in future
+               $client_time >= $creation_ts && // not modified since
+               (! $expire || $client_time + $expire >= $server_time) // expiration timeout is not set, or not expired
+       );
+       $last_modified = $creation_ts > 0 ? $creation_ts : ($client_time > 0 ? $client_time : $server_time);
+
+       header ("Cache-Control: private, max-age=$expire, pre-check=$expire");
+       if ($result)
+               header ('Last-Modified: ' . gmdate (DATE_RFC1123, $last_modified), TRUE, 304);
+       else
+               header ('Last-Modified: ' . gmdate (DATE_RFC1123, $last_modified));
+       return $result;
+}
+
+function HTTPDateToUnixTime ($string)
+{
+       //Written per RFC 2616 3.3.1 - Full Date
+       //http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
+       $month_number = array
+       (
+               'Jan' => 1,
+               'Feb' => 2,
+               'Mar' => 3,
+               'Apr' => 4,
+               'May' => 5,
+               'Jun' => 6,
+               'Jul' => 7,
+               'Aug' => 8,
+               'Sep' => 9,
+               'Oct' => 10,
+               'Nov' => 11,
+               'Dec' => 12,
+       );
+
+       $formats = array();
+       # RFC2616 dictates exchanged timestamps to be in GMT TZ, and RFC822
+       # (which RFC1123 relies on) explicitly defines, that "GMT" is equivalent
+       # to "-0000" and "+0000".
+       $formats['rfc1123'] = '/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (?:GMT|[-+]0000)$/';
+       $formats['rfc850'] = '/^(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{2}):(\d{2}):(\d{2}) (?:GMT|[-+]0000)$/';
+       $formats['asctime'] = '/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{2}|\d{1}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/';
+
+       $matches = array();
+       if (preg_match ($formats['rfc1123'], $string, $matches)) {
+               $hours = $matches[5];
+               $minutes = $matches[6];
+               $seconds = $matches[7];
+               $month = $month_number[$matches[3]];
+               $day = $matches[2];
+               $year = $matches[4];
+       } elseif (preg_match ($formats['rfc850'], $string, $matches)) {
+               $hours = $matches[5];
+               $minutes = $matches[6];
+               $seconds = $matches[7];
+               $month = $month_number[substr($matches[3],0,3)];
+               $day = $matches[2];
+               $year = $matches[4];
+       } elseif (preg_match ($formats['asctime'], $string, $matches)) {
+               $hours = $matches[4];
+               $minutes = $matches[5];
+               $seconds = $matches[6];
+               $month = $month_number[$matches[2]];
+               $day = $matches[3];
+               $year = $matches[7];
+       } else
+               return false;
+       return gmmktime ($hours, $minutes, $seconds, $month, $day, $year);
+}
+
+?>
index 656f633cd9c2724401cb7e58f30f20b94c3d2108..23455f6a209c2e578b68ae8530a4bafe3c453c88 100644 (file)
@@ -4760,10 +4760,20 @@ function proxyStaticURI ($URI)
        )
                printStatic404();
        global $racktables_staticdir;
-       if (! file_exists ("${racktables_staticdir}/${URI}"))
+       if (FALSE === $fh = fopen ("${racktables_staticdir}/${URI}", 'r'))
                printStatic404();
-       header ('Content-type: ' . $content_type[$matches[2]]);
-       readfile ("${racktables_staticdir}/${URI}");
+       else
+       {
+               if (FALSE !== $stat = fstat ($fh))
+               {
+                       require_once 'inc/caching.php';
+                       if (checkCachedResponse (max ($stat['mtime'], $stat['ctime']), 0))
+                               exit;
+               }
+               header ('Content-type: ' . $content_type[$matches[2]]);
+               fpassthru ($fh);
+               fclose ($fh);   
+       }
 }
 
 ?>
index d39261eff286b775cba12cc5b8501c6c9a3a7e84..c3703eb02cb300929fa936ef588cad023fd841ce 100644 (file)
@@ -1,29 +1,5 @@
 <?php
 
-define ('CACHE_DURATION', 604800); // 7 * 24 * 3600
-
-function checkIMSCondition()
-{
-       if
-       (
-               ! array_key_exists ('HTTP_IF_MODIFIED_SINCE', $_SERVER)
-               or ! array_key_exists ('img', $_REQUEST)
-               or $_REQUEST['img'] != 'progressbar'
-       )
-               return;
-       $client_time = HTTPDateToUnixTime ($_SERVER['HTTP_IF_MODIFIED_SINCE']);
-       if ($client_time !== FALSE && $client_time !== -1) // readable
-       {
-               $server_time = time();
-               // not in future and not yet expired
-               if ($client_time <= $server_time && $client_time + CACHE_DURATION >= $server_time)
-               {
-                       header ('Last-Modified: ' . $_SERVER['HTTP_IF_MODIFIED_SINCE'], TRUE, 304);
-                       exit;
-               }
-       }
-}
-
 function dispatchImageRequest()
 {
        genericAssertion ('img', 'string');
@@ -42,8 +18,6 @@ function dispatchImageRequest()
        case 'progressbar': // no security context
                assertUIntArg ('done', TRUE);
                // 'progressbar's never change, make browser cache the result
-               header ('Cache-Control: private, max-age=' . CACHE_DURATION . ', pre-check=' . CACHE_DURATION);
-               header ('Last-Modified: ' . gmdate (DATE_RFC1123));
                renderProgressBarImage ($_REQUEST['done']);
                break;
        case 'preview': // file security context
@@ -60,62 +34,6 @@ function dispatchImageRequest()
        }
 }
 
-//------------------------------------------------------------------------
-function HTTPDateToUnixTime ($string)
-{
-       //Written per RFC 2616 3.3.1 - Full Date
-       //http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html
-       $month_number = array
-       (
-               'Jan' => 1,
-               'Feb' => 2,
-               'Mar' => 3,
-               'Apr' => 4,
-               'May' => 5,
-               'Jun' => 6,
-               'Jul' => 7,
-               'Aug' => 8,
-               'Sep' => 9,
-               'Oct' => 10,
-               'Nov' => 11,
-               'Dec' => 12,
-       );
-
-       $formats = array();
-       # RFC2616 dictates exchanged timestamps to be in GMT TZ, and RFC822
-       # (which RFC1123 relies on) explicitly defines, that "GMT" is equivalent
-       # to "-0000" and "+0000".
-       $formats['rfc1123'] = '/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat), (\d{2}) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d{2}):(\d{2}):(\d{2}) (?:GMT|[-+]0000)$/';
-       $formats['rfc850'] = '/^(Sunday|Monday|Tuesday|Wednesday|Thursday|Friday|Saturday), (\d{2})-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d{2}) (\d{2}):(\d{2}):(\d{2}) (?:GMT|[-+]0000)$/';
-       $formats['asctime'] = '/^(Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{2}|\d{1}) (\d{2}):(\d{2}):(\d{2}) (\d{4})$/';
-
-       $matches = array();
-       if (preg_match ($formats['rfc1123'], $string, $matches)) {
-               $hours = $matches[5];
-               $minutes = $matches[6];
-               $seconds = $matches[7];
-               $month = $month_number[$matches[3]];
-               $day = $matches[2];
-               $year = $matches[4];
-       } elseif (preg_match ($formats['rfc850'], $string, $matches)) {
-               $hours = $matches[5];
-               $minutes = $matches[6];
-               $seconds = $matches[7];
-               $month = $month_number[substr($matches[3],0,3)];
-               $day = $matches[2];
-               $year = $matches[4];
-       } elseif (preg_match ($formats['asctime'], $string, $matches)) {
-               $hours = $matches[4];
-               $minutes = $matches[5];
-               $seconds = $matches[6];
-               $month = $month_number[$matches[2]];
-               $day = $matches[3];
-               $year = $matches[7];
-       } else
-               return false;
-       return gmmktime ($hours, $minutes, $seconds, $month, $day, $year);
-}
-
 function renderErrorImage ()
 {
        header("Content-type: image/png");
index f25c6c3c06d5af2175ed58b4ba78e278eff11202..1ee8b1c0e7081d9efd363edc6ad17171f75f17df 100644 (file)
@@ -66,10 +66,13 @@ try {
                echo $file['contents'];
                break;
        case 'image' == $_REQUEST['module']:
+               require_once 'inc/caching.php';
+               // 'progressbar's never change, attempt an IMS shortcut before loading init.php
+               if (@$_REQUEST['img'] == 'progressbar')
+                       if (checkCachedResponse (0, 604800)) // 7 * 24 * 3600
+                               exit;
+               require_once 'inc/init.php'; // for authentication check
                require_once 'inc/render_image.php';
-               // 'progressbar's never change, attempt an IMS chortcut before loading init.php
-               checkIMSCondition();
-               require_once 'inc/init.php';
                try
                {
                        dispatchImageRequest();