提供静态文件而不对所有文件类型 header 信息进行硬编码

Serve static files without hard coding all file types header information

我目前正在我的项目中制作一个路由器,我发现了一个问题。我正在使用 .htaccess 文件将所有路由重定向到我的 router.php 文件。这会产生一个问题,我的所有 css/images/js 文件也被重定向到我的 .htaccess 文件。这是我的 .htacess 文件的代码:

RewriteEngine on
Options +Multiviews
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)/?$ .php

RewriteRule ^(.*)$ router.php [NC,L,QSA]

我曾尝试通过手动检测它是否是可识别的静态文件类型之一并手动 returning 内容来解决此问题。在我的路由器 class 中,我检查了给定的文件类型是否是可识别的静态文件类型。如果它是一个静态文件类型,我会渲染它,如果不是,我会把它交给 handle 函数,它基本上检查路由是否被识别并且 returns 对函数的调用。

       if ($isStatic["check"]) {
            $this->render->returnStaticFiles($data["uri"], $isStatic["type"], $isStatic["ext"] ?? "");
        } else {
            $this->handle($data["uri"]);
        }

然而,这个问题是我需要手动将静态文件类型添加到数组并使用函数设置正确的 headers 否则它只会被识别为 text/html 这不适用于 css 或图像。 Css 将不会被解析,图像将只是 return 作为二进制文本作为乱码。这就是我目前实现渲染的方式 class:

<?php

namespace app\Router;

use JetBrains\PhpStorm\ArrayShape;

class Render
{
    public array $static_file_types = ["js", "css", "html", "json"];
    public array $image_types = ["png", "jpg", "jpeg"];

    public function __construct(
        public string $root_dir = "",
        public string $home = "http://localhost/"
    ){}

    public function throwError(int $statusCode = 500) :string
    {
        $err_dir = $this->root_dir . "errors\";
        $file_contents = file_get_contents($err_dir . "$statusCode.php") ?? false;
        if (!$file_contents) {
            return str_replace(
                ["{code}", "{home}"],
                [$statusCode, $this->home],
                file_get_contents($err_dir . "err_template.php")
            );
        }
        return str_replace("{home}", $this->home, $file_contents);
    }
    public function returnStaticFiles(string $uri, string $type, string $ext) : void
    {
        if ($type == "cnt") {
            $this->setHeader($ext);
            include_once $this->root_dir . $uri;
        } elseif ($type == "img") {
            $this->handleImage($this->root_dir . urldecode($uri), $ext);
        } else {
            echo "This file is not supported sorry";
            exit();
        }
    }
    private function handleImage(string $path_to_image, string $type) : void
    {
        if (file_exists($path_to_image)) {
            $image = fopen($path_to_image, "r");
            header("Content-Type: image/$type");
            header("Content-Length: " . filesize($path_to_image));
            fpassthru($image);
        } else {
            echo "This image does not exist sorry";
        }
    }
    #[ArrayShape(["check" => "bool", "type" => "string", "ext" => "string"])]
    public function checkIsStatic($uri) : array
    {
        $_uri = explode(".", $uri);
        $ext = end($_uri);

        if (in_array($ext, $this->static_file_types)) {
            return ["check" => true, "type" => "cnt", "ext" => $ext];
        } elseif (in_array($ext, $this->image_types)) {
            return ["check" => true, "type" => "img", "ext" => $ext];
        } else {
            return ["check" => false, "type" => ""];
        }
    }
    private function setHeader($ext): void
    {
        switch ($ext) {
            case "css":
                header("Content-Type: text/css"); break;
            case "js":
                header("Content-Type: text/javascript"); break;
            case "json":
                header("Content-Type: application/json"); break;
            default:
                header("Content-Type: text/html"); break;
        }
    }
}

这工作得很好,但有什么办法解决这个问题吗?我可能需要提供 PDF 内容或其他文件类型(如音频或视频),我认为这不是最佳解决方案。我尝试搜索它,但我认为我找不到任何东西。

感谢任何帮助。

事实证明这是一个简单的解决方案。我只是将重定向的所有内容更改为 router.php 到另一行 RewriteRule !.(js|css|ico|gif|jpg|png)$ router.php [L]

这会检查文件是否不是 js 或 css 等,然后它会重定向到 router.php 文件,否则它通常会提供该文件。我认为我的问题不够清楚,其他人无法理解,所以我希望这个答案能解决问题。

对这个 link 的大喊大叫,这让一切都变得正确:rewrite rule in .htaccess: what does it do