Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattab <matthieu.aubry@gmail.com>2013-09-14 04:03:04 +0400
committermattab <matthieu.aubry@gmail.com>2013-09-14 04:03:04 +0400
commitdf470ed7170e4b323b4623fd55453abc2d7810ad (patch)
treed2e234b0562e8b85f9aa847fe0a6de468e554808
parent6ea0fe5c49de11a0693e0f588ae06484cf3f6503 (diff)
Refactoring ProxyStaticFile class:
Small static file server proxy, with compression, caching. Used to server piwik.js and the merged+minified CSS and JS files
-rw-r--r--core/AssetManager.php11
-rw-r--r--core/Piwik.php175
-rw-r--r--js/index.php4
-rw-r--r--plugins/Proxy/Controller.php11
-rw-r--r--tests/PHPUnit/Core/ServeStaticFileTest.php23
-rw-r--r--tests/resources/staticFileServer.php26
6 files changed, 37 insertions, 213 deletions
diff --git a/core/AssetManager.php b/core/AssetManager.php
index 3013f1d41d..e65639b12f 100644
--- a/core/AssetManager.php
+++ b/core/AssetManager.php
@@ -12,13 +12,8 @@ namespace Piwik;
use Exception;
use JSMin;
-use Piwik\Config;
-use Piwik\Piwik;
-use Piwik\Common;
-use Piwik\Version;
-use Piwik\PluginsManager;
-use Piwik\Translate;
use lessc;
+use Piwik\Translate;
/**
* @see libs/jsmin/jsmin.php
@@ -492,7 +487,7 @@ class AssetManager
* Also tries to remove compressed version of the merged file.
*
* @param string $filename filename of the merged asset
- * @see Piwik::serveStaticFile()
+ * @see ProxyStaticFile::serveStaticFile(serveFile
* @throws Exception if the file couldn't be deleted
*/
private static function removeMergedAsset($filename)
@@ -505,7 +500,7 @@ class AssetManager
}
// Tries to remove compressed version of the merged file.
- // See Piwik::serveStaticFile() for more info on static file compression
+ // See Piwik::serveFile() for more info on static file compression
$compressedFileLocation = PIWIK_USER_PATH . Piwik::COMPRESSED_FILE_LOCATION . $filename;
@unlink($compressedFileLocation . ".deflate");
diff --git a/core/Piwik.php b/core/Piwik.php
index a96e0122b8..6d178f45eb 100644
--- a/core/Piwik.php
+++ b/core/Piwik.php
@@ -189,22 +189,6 @@ class Piwik
}
/**
- * Set response header, e.g., HTTP/1.0 200 Ok
- *
- * @param string $status Status
- * @return bool
- */
- static public function setHttpStatus($status)
- {
- if (substr_compare(PHP_SAPI, '-fcgi', -5)) {
- @header($_SERVER['SERVER_PROTOCOL'] . ' ' . $status);
- } else {
- // FastCGI
- @header('Status: ' . $status);
- }
- }
-
- /**
* Workaround IE bug when downloading certain document types over SSL and
* cache control headers are present, e.g.,
*
@@ -666,163 +650,6 @@ class Piwik
}
/**
- * Test if php output is compressed
- *
- * @return bool True if php output is (or suspected/likely) to be compressed
- */
- static public function isPhpOutputCompressed()
- {
- // Off = ''; On = '1'; otherwise, it's a buffer size
- $zlibOutputCompression = ini_get('zlib.output_compression');
-
- // could be ob_gzhandler, ob_deflatehandler, etc
- $outputHandler = ini_get('output_handler');
-
- // output handlers can be stacked
- $obHandlers = array_filter(ob_list_handlers(), function($var) {
- return $var !== "default output handler";
- });
-
- // user defined handler via wrapper
- $autoPrependFile = ini_get('auto_prepend_file');
- $autoAppendFile = ini_get('auto_append_file');
-
- return !empty($zlibOutputCompression) ||
- !empty($outputHandler) ||
- !empty($obHandlers) ||
- !empty($autoPrependFile) ||
- !empty($autoAppendFile);
- }
-
- /**
- * Serve static files through php proxy.
- *
- * It performs the following actions:
- * - Checks the file is readable or returns "HTTP/1.0 404 Not Found"
- * - Returns "HTTP/1.1 304 Not Modified" after comparing the HTTP_IF_MODIFIED_SINCE
- * with the modification date of the static file
- * - Will try to compress the static file according to HTTP_ACCEPT_ENCODING. Compressed files are store in
- * the /tmp directory. If compressing extensions are not available, a manually gzip compressed file
- * can be provided in the /tmp directory. It has to bear the same name with an added .gz extension.
- * Using manually compressed static files requires you to manually update the compressed file when
- * the static file is updated.
- * - Overrides server cache control config to allow caching
- * - Sends Very Accept-Encoding to tell proxies to store different version of the static file according
- * to users encoding capacities.
- *
- * Warning:
- * Compressed filed are stored in the /tmp directory.
- * If this method is used with two files bearing the same name but located in different locations,
- * there is a risk of conflict. One file could be served with the content of the other.
- * A future upgrade of this method would be to recreate the directory structure of the static file
- * within a /tmp/compressed-static-files directory.
- *
- * @param string $file The location of the static file to serve
- * @param string $contentType The content type of the static file.
- * @param bool $expireFarFuture If set to true, will set Expires: header in far future.
- * Should be set to false for files that don't have a cache buster (eg. piwik.js)
- */
- static public function serveStaticFile($file, $contentType, $expireFarFuture = true)
- {
- if (file_exists($file)) {
- // conditional GET
- $modifiedSince = '';
- if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
- $modifiedSince = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
-
- // strip any trailing data appended to header
- if (false !== ($semicolon = strpos($modifiedSince, ';'))) {
- $modifiedSince = substr($modifiedSince, 0, $semicolon);
- }
- }
-
- $fileModifiedTime = @filemtime($file);
- $lastModified = gmdate('D, d M Y H:i:s', $fileModifiedTime) . ' GMT';
-
- // set HTTP response headers
- self::overrideCacheControlHeaders('public');
- @header('Vary: Accept-Encoding');
- @header('Content-Disposition: inline; filename=' . basename($file));
-
- if ($expireFarFuture) {
- // Required by proxy caches potentially in between the browser and server to cache the request indeed
- @header("Expires: " . gmdate('D, d M Y H:i:s', time() + 86400 * 100) . ' GMT');
- }
-
- // Returns 304 if not modified since
- if ($modifiedSince === $lastModified) {
- self::setHttpStatus('304 Not Modified');
- } else {
- // optional compression
- $compressed = false;
- $encoding = '';
- $compressedFileLocation = PIWIK_USER_PATH . self::COMPRESSED_FILE_LOCATION . basename($file);
-
- $phpOutputCompressionEnabled = self::isPhpOutputCompressed();
- if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && !$phpOutputCompressionEnabled) {
- $acceptEncoding = $_SERVER['HTTP_ACCEPT_ENCODING'];
-
- if (extension_loaded('zlib') && function_exists('file_get_contents') && function_exists('file_put_contents')) {
- if (preg_match('/(?:^|, ?)(deflate)(?:,|$)/', $acceptEncoding, $matches)) {
- $encoding = 'deflate';
- $filegz = $compressedFileLocation . '.deflate';
- } else if (preg_match('/(?:^|, ?)((x-)?gzip)(?:,|$)/', $acceptEncoding, $matches)) {
- $encoding = $matches[1];
- $filegz = $compressedFileLocation . '.gz';
- }
-
- if (!empty($encoding)) {
- // compress-on-demand and use cache
- if (!file_exists($filegz) || ($fileModifiedTime > @filemtime($filegz))) {
- $data = file_get_contents($file);
-
- if ($encoding == 'deflate') {
- $data = gzdeflate($data, 9);
- } else if ($encoding == 'gzip' || $encoding == 'x-gzip') {
- $data = gzencode($data, 9);
- }
-
- file_put_contents($filegz, $data);
- }
-
- $compressed = true;
- $file = $filegz;
- }
- } else {
- // manually compressed
- $filegz = $compressedFileLocation . '.gz';
- if (preg_match('/(?:^|, ?)((x-)?gzip)(?:,|$)/', $acceptEncoding, $matches) && file_exists($filegz) && ($fileModifiedTime < @filemtime($filegz))) {
- $encoding = $matches[1];
- $compressed = true;
- $file = $filegz;
- }
- }
- }
-
- @header('Last-Modified: ' . $lastModified);
-
- if (!$phpOutputCompressionEnabled) {
- @header('Content-Length: ' . filesize($file));
- }
-
- if (!empty($contentType)) {
- @header('Content-Type: ' . $contentType);
- }
-
- if ($compressed) {
- @header('Content-Encoding: ' . $encoding);
- }
-
- if (!_readfile($file)) {
- self::setHttpStatus('505 Internal server error');
- }
- }
- } else {
- self::setHttpStatus('404 Not Found');
- }
- }
-
- /**
* Create CSV (or other delimited) files
*
* @param string $filePath filename to create
@@ -1734,7 +1561,7 @@ class Piwik
static public function disconnectDatabase()
{
\Zend_Registry::get('db')->closeConnection();
-}
+ }
/**
* Checks the database server version against the required minimum
diff --git a/js/index.php b/js/index.php
index 6c67ffdc81..4ee43b7e64 100644
--- a/js/index.php
+++ b/js/index.php
@@ -5,7 +5,7 @@
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
-use Piwik\Piwik;
+use Piwik\ProxyStaticFile;
/**
* Tracker proxy
@@ -31,6 +31,6 @@ $file = '../piwik.js';
// There is no cache buster parameter so we don't set Expires: header
$expireFarFuture = false;
-Piwik::serveStaticFile($file, "application/javascript; charset=UTF-8", $expireFarFuture);
+ProxyStaticFile::serveFile($file, "application/javascript; charset=UTF-8", $expireFarFuture);
exit;
diff --git a/plugins/Proxy/Controller.php b/plugins/Proxy/Controller.php
index af251fe32a..9378a6f3e1 100644
--- a/plugins/Proxy/Controller.php
+++ b/plugins/Proxy/Controller.php
@@ -10,9 +10,10 @@
*/
namespace Piwik\Plugins\Proxy;
-use Piwik\Piwik;
-use Piwik\Common;
use Piwik\AssetManager;
+use Piwik\Common;
+use Piwik\Piwik;
+use Piwik\ProxyStaticFile;
use Piwik\Url;
/**
@@ -34,7 +35,7 @@ class Controller extends \Piwik\Controller
public function getCss()
{
$cssMergedFile = AssetManager::getMergedCssFileLocation();
- Piwik::serveStaticFile($cssMergedFile, "text/css");
+ ProxyStaticFile::serveFile($cssMergedFile, "text/css");
}
/**
@@ -46,7 +47,7 @@ class Controller extends \Piwik\Controller
public function getJs()
{
$jsMergedFile = AssetManager::getMergedJsFileLocation();
- Piwik::serveStaticFile($jsMergedFile, self::JS_MIME_TYPE);
+ ProxyStaticFile::serveFile($jsMergedFile, self::JS_MIME_TYPE);
}
/**
@@ -64,7 +65,7 @@ class Controller extends \Piwik\Controller
AssetManager::removeTranslationsJsFile();
$translationsJsFile = AssetManager::getTranslationsJsFileLocation();
- Piwik::serveStaticFile($translationsJsFile, self::JS_MIME_TYPE);
+ ProxyStaticFile::serveFile($translationsJsFile, self::JS_MIME_TYPE);
}
/**
diff --git a/tests/PHPUnit/Core/ServeStaticFileTest.php b/tests/PHPUnit/Core/ServeStaticFileTest.php
index 116edab40a..a5cbaa1d39 100644
--- a/tests/PHPUnit/Core/ServeStaticFileTest.php
+++ b/tests/PHPUnit/Core/ServeStaticFileTest.php
@@ -1,19 +1,20 @@
<?php
/**
- * This php file is used to unit test Piwik::serveStaticFile()
+ * This php file is used to unit test Piwik::serveFile()
* Unit tests for this method should normally be located in /tests/core/Piwik.test.php
- * To make a comprehensive test suit for Piwik::serveStaticFile() (ie. being able to test combinations of request
+ * To make a comprehensive test suit for Piwik::serveFile() (ie. being able to test combinations of request
* headers, being able to test response headers and so on) we need to simulate static file requests in a controlled
* environment
- * The php code which simulates requests using Piwik::serveStaticFile() is provided in the same file (ie. this one)
- * as the unit testing code for Piwik::serveStaticFile()
+ * The php code which simulates requests using Piwik::serveFile() is provided in the same file (ie. this one)
+ * as the unit testing code for Piwik::serveFile()
* This decision has a structural impact on the usual unit test file structure
- * serveStaticFile.test.php has been created to avoid making too many modifications to /tests/core/Piwik.test.php
+ * serveFile.test.php has been created to avoid making too many modifications to /tests/core/Piwik.test.php
*/
// This is Piwik logo, the static file used in this test suit
-use Piwik\Piwik;
use Piwik\Common;
+use Piwik\Piwik;
+use Piwik\ProxyStaticFile;
define("TEST_FILE_LOCATION", realpath(dirname(__FILE__) . "/../../resources/lipsum.txt"));
define("TEST_FILE_CONTENT_TYPE", "text/plain");
@@ -25,7 +26,7 @@ define("ZLIB_OUTPUT_REQUEST_VAR", "zlibOutput");
/**
* These constants define the mode in which this php file is used :
- * - for unit testing Piwik::serveStaticFile() or
+ * - for unit testing Piwik::serveFile() or
* - as a static file server
*/
define("STATIC_SERVER_MODE", "staticServerMode");
@@ -52,11 +53,11 @@ class Test_Piwik_ServeStaticFile extends PHPUnit_Framework_TestCase
*/
public function test_phpOutputCompression()
{
- $this->assertFalse(Piwik::isPhpOutputCompressed());
+ $this->assertFalse(ProxyStaticFile::isPhpOutputCompressed());
}
/**
- * Checks that "HTTP/1.0 404 Not Found" is returned when Piwik::serveStaticFile is called with a null file
+ * Checks that "HTTP/1.0 404 Not Found" is returned when Piwik::serveFile is called with a null file
*
* @group ServeStaticFile
*/
@@ -73,7 +74,7 @@ class Test_Piwik_ServeStaticFile extends PHPUnit_Framework_TestCase
}
/**
- * Checks that "HTTP/1.0 404 Not Found" is returned when Piwik::serveStaticFile is called with a non existing file
+ * Checks that "HTTP/1.0 404 Not Found" is returned when Piwik::serveFile is called with a non existing file
*
* @group ServeStaticFile
*/
@@ -90,7 +91,7 @@ class Test_Piwik_ServeStaticFile extends PHPUnit_Framework_TestCase
}
/**
- * Checks that "HTTP/1.0 505 Internal server error" is returned when Piwik::serveStaticFile is called with a
+ * Checks that "HTTP/1.0 505 Internal server error" is returned when Piwik::serveFile is called with a
* non-readable file
*
* @group ServeStaticFile
diff --git a/tests/resources/staticFileServer.php b/tests/resources/staticFileServer.php
index 3860cf1910..0646b6b3cc 100644
--- a/tests/resources/staticFileServer.php
+++ b/tests/resources/staticFileServer.php
@@ -1,16 +1,16 @@
<?php
/**
- * This php file is used to unit test Piwik::serveStaticFile()
- * To make a comprehensive test suit for Piwik::serveStaticFile() (ie. being able to test combinations of request
+ * This php file is used to unit test Piwik::serveFile()
+ * To make a comprehensive test suit for Piwik::serveFile() (ie. being able to test combinations of request
* headers, being able to test response headers and so on) we need to simulate static file requests in a controlled
* environment
- * The php code which simulates requests using Piwik::serveStaticFile() is provided in the same file (ie. this one)
- * as the unit testing code for Piwik::serveStaticFile()
+ * The php code which simulates requests using Piwik::serveFile() is provided in the same file (ie. this one)
+ * as the unit testing code for Piwik::serveFile()
* This decision has a structural impact on the usual unit test file structure
- * serveStaticFile.test.php has been created to avoid making too many modifications to /tests/core/Piwik.test.php
+ * serveFile.test.php has been created to avoid making too many modifications to /tests/core/Piwik.test.php
*/
-use Piwik\Piwik;
use Piwik\Common;
+use Piwik\ProxyStaticFile;
define('PIWIK_DOCUMENT_ROOT', dirname(__FILE__).'/../../');
if(file_exists(PIWIK_DOCUMENT_ROOT . '/bootstrap.php'))
@@ -58,7 +58,7 @@ define("TEST_FILE_SRV_MODE", "testFile");
/**
* If the static file server has been requested, the response sent back to the browser will be the content produced by
- * the execution of Piwik:serveStaticFile(). In this case, unit tests won't be executed
+ * the execution of Piwik:serveFile(). In this case, unit tests won't be executed
*/
// Getting the server mode
$staticFileServerMode = Common::getRequestVar(SRV_MODE_REQUEST_VAR, "");
@@ -72,21 +72,21 @@ if ($staticFileServerMode === "") {
}
switch ($staticFileServerMode) {
- // The static file server calls Piwik::serveStaticFile with a null file
+ // The static file server calls Piwik::serveFile with a null file
case NULL_FILE_SRV_MODE:
- Piwik::serveStaticFile(null, TEST_FILE_CONTENT_TYPE);
+ ProxyStaticFile::serveFile(null, TEST_FILE_CONTENT_TYPE);
break;
- // The static file server calls Piwik::serveStaticFile with a non-existing file
+ // The static file server calls Piwik::serveFile with a non-existing file
case GHOST_FILE_SRV_MODE:
- Piwik::serveStaticFile(TEST_FILE_LOCATION . ".ghost", TEST_FILE_CONTENT_TYPE);
+ ProxyStaticFile::serveFile(TEST_FILE_LOCATION . ".ghost", TEST_FILE_CONTENT_TYPE);
break;
- // The static file server calls Piwik::serveStaticFile with the test file
+ // The static file server calls Piwik::serveFile with the test file
case TEST_FILE_SRV_MODE:
- Piwik::serveStaticFile(TEST_FILE_LOCATION, TEST_FILE_CONTENT_TYPE);
+ ProxyStaticFile::serveFile(TEST_FILE_LOCATION, TEST_FILE_CONTENT_TYPE);
break;
} \ No newline at end of file