diff --git a/app/server.php b/app/server.php index c46b2da89a..9a40b79f49 100644 --- a/app/server.php +++ b/app/server.php @@ -2,6 +2,7 @@ require_once __DIR__.'/../vendor/autoload.php'; +use Appwrite\Utopia\Files; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Swoole\Process; @@ -24,8 +25,8 @@ $http = new Server("0.0.0.0", 80); $http ->set([ 'open_http2_protocol' => true, - 'document_root' => __DIR__ . '/../public', - 'enable_static_handler' => true, + // 'document_root' => __DIR__.'/../public', + // 'enable_static_handler' => true, 'timeout' => 7, 'http_compression' => true, 'http_compression_level' => 6, @@ -55,12 +56,27 @@ $http->on('start', function (Server $http) { }); }); +Files::load(__DIR__ . '/../public'); + include __DIR__ . '/app.php'; $http->on('request', function (SwooleRequest $swooleRequest, SwooleResponse $swooleResponse) { $request = new Request($swooleRequest); $response = new Response($swooleResponse); + if(Files::isFileLoaded($request->getURI())) { + $time = (60 * 60 * 24 * 45); // 45 days cache + + $response + ->setContentType(Files::getFileMimeType($request->getURI())) + ->addHeader('Cache-Control', 'public, max-age='.$time) + ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + $time).' GMT') // 45 days cache + ->send(Files::getFileContents($request->getURI())) + ; + + return; + } + $app = new App('Asia/Tel_Aviv'); try { diff --git a/composer.json b/composer.json index c149cf03da..f0a53c2a60 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,7 @@ "appwrite/php-clamav": "1.0.*", - "utopia-php/framework": "0.8.0", + "utopia-php/framework": "0.8.1", "utopia-php/abuse": "0.2.*", "utopia-php/audit": "0.3.*", "utopia-php/cache": "0.2.*", diff --git a/composer.lock b/composer.lock index 3499778c88..4466bd124a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6faf79daa7c1931e3977c49baa44200b", + "content-hash": "12fa4cc8c24ef38a37424285d9be917a", "packages": [ { "name": "appwrite/php-clamav", @@ -1596,16 +1596,16 @@ }, { "name": "utopia-php/framework", - "version": "0.8.0", + "version": "0.8.1", "source": { "type": "git", "url": "https://github.com/utopia-php/framework.git", - "reference": "de93b6391ad93e46a5a6573527d0d82d93fb2c1a" + "reference": "79c4193e42120b3eefcda22a0254a6bfc257d6b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/framework/zipball/de93b6391ad93e46a5a6573527d0d82d93fb2c1a", - "reference": "de93b6391ad93e46a5a6573527d0d82d93fb2c1a", + "url": "https://api.github.com/repos/utopia-php/framework/zipball/79c4193e42120b3eefcda22a0254a6bfc257d6b6", + "reference": "79c4193e42120b3eefcda22a0254a6bfc257d6b6", "shasum": "" }, "require": { @@ -1636,7 +1636,7 @@ "php", "upf" ], - "time": "2020-07-04T22:01:06+00:00" + "time": "2020-07-06T11:37:03+00:00" }, { "name": "utopia-php/locale", diff --git a/src/Appwrite/Utopia/Files.php b/src/Appwrite/Utopia/Files.php index 9782196cba..e7cb3dc7bb 100644 --- a/src/Appwrite/Utopia/Files.php +++ b/src/Appwrite/Utopia/Files.php @@ -16,6 +16,62 @@ class Files */ static protected $count = 0; + /** + * @var array + */ + static protected $mimeTypes = []; + + /** + * @var array + */ + static protected $extensions = [ + 'css' => 'text/css', + 'js' => 'text/javascript', + 'svg' => 'image/svg+xml', + ]; + + /** + * Add MimeType + * + * @var string $mimeType + */ + public static function addMimeType(string $mimeType) + { + self::$mimeTypes[$mimeType] = true; + } + + /** + * Remove MimeType + * + * @var string $mimeType + */ + public static function removeMimeType(string $mimeType) + { + if(isset(self::$mimeTypes[$mimeType])) { + unset(self::$mimeTypes[$mimeType]); + } + } + + /** + * Get MimeType List + * + * @return array + */ + public static function getMimeTypes(): array + { + return self::$mimeTypes; + } + + /** + * Get Files Loaded Count + * + * @return int + */ + public static function getCount(): int + { + return self::$count; + } + /** * Load * @@ -34,12 +90,13 @@ class Files $handle = opendir($directory); while ($path = readdir($handle)) { + $extension = pathinfo($path, PATHINFO_EXTENSION); if (in_array($path, ['.', '..'])) { continue; } - if (in_array(pathinfo($path, PATHINFO_EXTENSION), ['php', 'phtml'])) { + if (in_array($extension, ['php', 'phtml'])) { continue; } @@ -54,7 +111,12 @@ class Files self::$count++; - self::$loaded[substr($directory.'/'.$path , strlen($root))] = file_get_contents($directory.'/'.$path); + self::$loaded[substr($directory.'/'.$path , strlen($root))] = [ + 'contents' => file_get_contents($directory.'/'.$path), + 'mimeType' => (array_key_exists($extension, self::$extensions)) + ? self::$extensions[$extension] + : mime_content_type($directory.'/'.$path) + ]; } closedir($handle); @@ -63,4 +125,46 @@ class Files echo '[Static Files] Loadded '.self::$count.' files'.PHP_EOL; } } + + /** + * Is File Loaded + * + * @var string $uri + */ + public static function isFileLoaded(string $uri): bool + { + if(!array_key_exists($uri, self::$loaded)) { + return false; + } + + return true; + } + + /** + * Get File Contants + * + * @var string $uri + */ + public static function getFileContents(string $uri): string + { + if(!array_key_exists($uri, self::$loaded)) { + throw new Exception('File not found or not loaded: '.$uri); + } + + return self::$loaded[$uri]['contents']; + } + + /** + * Get File MimeType + * + * @var string $uri + */ + public static function getFileMimeType(string $uri): string + { + if(!array_key_exists($uri, self::$loaded)) { + throw new Exception('File not found or not loaded: '.$uri); + } + + return self::$loaded[$uri]['mimeType']; + } } diff --git a/src/Appwrite/Utopia/Response.php b/src/Appwrite/Utopia/Response.php index f217be4f7a..4939fe3e02 100644 --- a/src/Appwrite/Utopia/Response.php +++ b/src/Appwrite/Utopia/Response.php @@ -226,7 +226,7 @@ class Response extends UtopiaResponse // Send content type header $this - ->addHeader('Content-Type', $this->contentType . '; charset=UTF-8') + ->addHeader('Content-Type', $this->contentType) ; // Set application headers diff --git a/tests/unit/Utopia/FilesTest.php b/tests/unit/Utopia/FilesTest.php new file mode 100644 index 0000000000..6f3fe9f002 --- /dev/null +++ b/tests/unit/Utopia/FilesTest.php @@ -0,0 +1,49 @@ +assertGreaterThan(100, Files::getCount()); + $this->assertLessThan(250, Files::getCount()); + + $this->assertEquals(false, Files::isFileLoaded('/index.php')); + $this->assertEquals(false, Files::isFileLoaded('/unknown.jpg')); + $this->assertEquals(true, Files::isFileLoaded('/scripts/app.js')); + $this->assertEquals(true, Files::isFileLoaded('/styles/default.less')); + $this->assertEquals(true, Files::isFileLoaded('/dist/scripts/app.js')); + $this->assertEquals(true, Files::isFileLoaded('/dist/styles/default-ltr.css')); + $this->assertEquals(true, Files::isFileLoaded('/dist/styles/default-rtl.css')); + + $this->assertEquals('application/vnd.ms-fontobject', Files::getFileMimeType('/fonts/poppins-v9-latin-100.eot')); + $this->assertEquals('image/svg+xml', Files::getFileMimeType('/fonts/poppins-v9-latin-100.svg')); + $this->assertEquals('font/sfnt', Files::getFileMimeType('/fonts/poppins-v9-latin-100.ttf')); + $this->assertEquals('application/octet-stream', Files::getFileMimeType('/fonts/poppins-v9-latin-100.woff')); + $this->assertEquals('application/octet-stream', Files::getFileMimeType('/fonts/poppins-v9-latin-100.woff2')); + $this->assertEquals('image/png', Files::getFileMimeType('/images/apple.png')); + $this->assertEquals('text/javascript', Files::getFileMimeType('/dist/scripts/app.js')); + $this->assertEquals('text/javascript', Files::getFileMimeType('/dist/scripts/app.js')); + $this->assertEquals('text/css', Files::getFileMimeType('/dist/styles/default-ltr.css')); + $this->assertEquals('text/css', Files::getFileMimeType('/dist/styles/default-rtl.css')); + + $this->assertNotEmpty(Files::getFileContents('/fonts/poppins-v9-latin-100.eot')); + $this->assertNotEmpty(Files::getFileContents('/fonts/poppins-v9-latin-100.svg')); + $this->assertNotEmpty(Files::getFileContents('/fonts/poppins-v9-latin-100.ttf')); + $this->assertNotEmpty(Files::getFileContents('/fonts/poppins-v9-latin-100.woff')); + $this->assertNotEmpty(Files::getFileMimeType('/fonts/poppins-v9-latin-100.woff2')); + $this->assertNotEmpty(Files::getFileContents('/images/apple.png')); + $this->assertNotEmpty(Files::getFileContents('/dist/scripts/app.js')); + $this->assertNotEmpty(Files::getFileContents('/dist/scripts/app.js')); + $this->assertNotEmpty(Files::getFileContents('/dist/styles/default-ltr.css')); + $this->assertNotEmpty(Files::getFileContents('/dist/styles/default-rtl.css')); + + } +} \ No newline at end of file