我如何为 Apache 编写 .htaccess 文件以附加 PHP(如果未提供)并使用编写良好的 404 页面

How can I write an .htaccess file for Apache to append PHP (if not supplied) AND use a well-written 404 page

在 Apache 中,我有一个工作的 .htaccess 文件,它将 .php 扩展名附加到请求的网站页面,例如:https://{{domain}}/sales -> serves来自 https://{{domain}}/sales.php 的内容,而对于访问者来说它看起来像 https://{{domain}}/sales

它运行完美。

但是,我无法解决如何同时使用来自服务器的精美 404.php 页面。

这是我当前的 .htaccess 文件内容:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ \.php [NC,L]

证据:如果我关闭我的 .htaccess 文件(重命名),根据我的 httpd.conf 设置,404 页面运行良好。所以,我几乎肯定是这个不成熟的 .htaccess 文件阻止我在找不到 sales.php 页面时提供精美的 404 页面。

What are the exact lines in httpd.conf:

DocumentRoot "/var/www/html/"
ErrorDocument 404 "/404.php"

此外,我已经尝试了每一个:(并在之后重新加载了 httpd)

ErrorDocument 404 "/var/www/html/{{virtualHostDir}}/404.php"
ErrorDocument 404 "/404.php"
ErrorDocument 404 "404.php"

我什至尝试将 ErrorDocument 直接添加到 virtualHost 设置中,但无济于事。


And what actually happens when you get a 404 and the .htaccess file is in place?

我得到一个没有 html 的页面,它只是说 "File not found."

DocumentRoot "/var/www/html/"
ErrorDocument 404 "/404.php"

看起来正确。如果 404 错误文档位于 /var/www/html/404.php,则没有明显的原因(根据给定的信息)为什么它没有按预期工作。它似乎不是 .htaccess 文件的内容 - 尽管您可以尝试其他方法(见下文)。

提供给 ErrorDocument 指令的路径应该是文档根目录相关的 URL 路径 - 以斜杠开头。 (为了触发对相应错误文档的内部子请求。)

I've even tried to add the ErrorDocument directly to the virtualHost settings

但是,如果您使用的是 VirtualHost 容器,那么这些设置实际上应该在各自的 vHost 中。 vHost 中的任何内容都会覆盖主服务器配置。

显然,如果您对服务器配置/虚拟主机进行了任何更改,则需要重新启动 Apache。

既然你正在使用 .htaccess,你也可以在 .htaccess 中设置 ErrorDocument - 这将反过来覆盖虚拟主机/服务器配置。

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ \.php [NC,L]

这没有什么特别的问题...您正在匹配一个不包含点的请求 URL-路径,并且假设它还没有映射到文件或目录,您正在附加一个 .php 扩展。

关于此的一些注释:

  • 无论文件 "with a .php extension" 是否实际存在,您都附加 .php 扩展名。这不一定是错误的,只是 404 然后在 /does-not-exist.php 而不是 /does-not-exist 上触发。您可以改为检查目标文件是否存在。这将避免检查请求是否已经映射到文件或目录。

  • 检查请求是否映射到文件的第一个条件可能是不必要的,除非你有没有文件扩展名的文件(我认为这不太可能)。

  • [^\.] - 不需要反斜杠转义正则表达式字符 class 中的文字点。 (虽然这样做没有坏处,除了可读性 IMO。)

  • \.php - 无需反斜杠转义 RewriteRule 替换 中的文字点。这个参数是一个 "ordinary" 字符串(不是正则表达式),点在这里没有特殊含义。 (尽管如此,除了可读性之外,这样做没有任何坏处。)

  • 此处不需要 RewriteRule 上的 NC 标志,因为您正在匹配 所有内容 除了正则表达式中的一个点,无论如何自然包括大写和小写字母。

  • 如果这就是您使用 mod_rewrite 的全部目的,那么您可以改用 MultiViews 来处理无扩展的 URL。这就是 MultiViews(mod_negotiation 的一部分)所做的。给定 /path/to/foo 的请求,如果 /path/to/foo.php 存在,mod_negotiation 将提供该文件。您需要删除现有的 mod_rewrite 指令(因为它们实际上会发生冲突并被忽略),然后在 .htaccess 文件的顶部启用 MultiViews:

    Options +MultiViews
    

或者,考虑到我在上面提出的要点,请尝试以下操作:

RewriteEngine On

RewriteCond %{DOCUMENT_ROOT}/.php -f
RewriteRule ^([^.]+)$ .php [L]

注意:我假设您的 .htaccess 文件位于文档根目录中,即。 /var/www/html/.htaccess?