summaryrefslogtreecommitdiffstats
path: root/library/Icinga/Web/Controller/StaticController.php
diff options
context:
space:
mode:
Diffstat (limited to 'library/Icinga/Web/Controller/StaticController.php')
-rw-r--r--library/Icinga/Web/Controller/StaticController.php87
1 files changed, 87 insertions, 0 deletions
diff --git a/library/Icinga/Web/Controller/StaticController.php b/library/Icinga/Web/Controller/StaticController.php
new file mode 100644
index 0000000..f5ce163
--- /dev/null
+++ b/library/Icinga/Web/Controller/StaticController.php
@@ -0,0 +1,87 @@
+<?php
+/* Icinga Web 2 | (c) 2020 Icinga GmbH | GPLv2+ */
+
+namespace Icinga\Web\Controller;
+
+use Icinga\Application\Icinga;
+use Icinga\Web\Request;
+
+class StaticController
+{
+ /**
+ * Handle incoming request
+ *
+ * @param Request $request
+ *
+ * @returns void
+ */
+ public function handle(Request $request)
+ {
+ $app = Icinga::app();
+
+ // +4 because strlen('/lib') === 4
+ $assetPath = ltrim(substr($request->getRequestUri(), strlen($request->getBaseUrl()) + 4), '/');
+
+ $library = null;
+ foreach ($app->getLibraries() as $candidate) {
+ if (substr($assetPath, 0, strlen($candidate->getName())) === $candidate->getName()) {
+ $library = $candidate;
+ $assetPath = ltrim(substr($assetPath, strlen($candidate->getName())), '/');
+ break;
+ }
+ }
+
+ if ($library === null) {
+ $app->getResponse()
+ ->setHttpResponseCode(404);
+
+ return;
+ }
+
+ $assetRoot = $library->getStaticAssetPath();
+ if (empty($assetRoot)) {
+ $app->getResponse()
+ ->setHttpResponseCode(404);
+
+ return;
+ }
+
+ $filePath = $assetRoot . DIRECTORY_SEPARATOR . $assetPath;
+ $dirPath = realpath(dirname($filePath)); // dirname, because the file may be a link
+
+ if ($dirPath === false
+ || substr($dirPath, 0, strlen($assetRoot)) !== $assetRoot
+ || ! is_file($filePath)
+ ) {
+ $app->getResponse()
+ ->setHttpResponseCode(404);
+
+ return;
+ }
+
+ $fileStat = stat($filePath);
+ $eTag = sprintf(
+ '%x-%x-%x',
+ $fileStat['ino'],
+ $fileStat['size'],
+ (float) str_pad($fileStat['mtime'], 16, '0')
+ );
+
+ $app->getResponse()->setHeader(
+ 'Cache-Control',
+ 'public, max-age=1814400, stale-while-revalidate=604800',
+ true
+ );
+
+ if ($request->getServer('HTTP_IF_NONE_MATCH') === $eTag) {
+ $app->getResponse()
+ ->setHttpResponseCode(304);
+ } else {
+ $app->getResponse()
+ ->setHeader('ETag', $eTag)
+ ->setHeader('Content-Type', mime_content_type($filePath), true)
+ ->setHeader('Last-Modified', gmdate('D, d M Y H:i:s', $fileStat['mtime']) . ' GMT')
+ ->setBody(file_get_contents($filePath));
+ }
+ }
+}