php - 如何为 Apache 编写 .htaccess 文件以附加 PHP(如果未提供)并使用编写良好的 404 页面
问题描述
在 Apache 中,我有一个有效的 .htaccess 文件,它将 .php 扩展名附加到请求的网站页面,例如: https://{{domain}}/sales -> 提供来自 https://{{ 的内容domain}}/sales.php 而对访问者来说,它看起来像 https://{{domain}}/sales
它工作完美。
但是,我无法解决如何也使用服务器上花哨的 404.php 页面。
这是我当前的 .htaccess 文件内容:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^\.]+)$ $1\.php [NC,L]
证据:如果我关闭我的 .htaccess 文件(重命名它),根据我的 httpd.conf 设置,404 页面运行良好。因此,我几乎可以肯定,当找不到 sales.php 页面时,正是这个不成熟的 .htaccess 文件阻止了我提供精美的 404 页面。
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 设置中,但无济于事。
当你得到一个 404 并且 .htaccess 文件就位时,实际上会发生什么?
我得到一个没有 html 的页面,它只是说“找不到文件”。
解决方案
DocumentRoot "/var/www/html/" ErrorDocument 404 "/404.php"
这看起来是正确的。如果 404 错误文档位于,/var/www/html/404.php
那么没有明显的原因(根据给定的信息)为什么它不能按预期工作。它似乎不是.htaccess
文件的内容 - 尽管您可以尝试另一种方法(见下文)。
提供给ErrorDocument
指令的路径应该是相对于文档根目录的 URL 路径 - 以斜杠开头。(为了触发对相应错误文档的内部子请求。)
我什至尝试将 ErrorDocument 直接添加到 virtualHost 设置中
但是,如果您使用的是 VirtualHost 容器,那么这些设置实际上应该在各自的 vHost(s) 中。vHost 中的任何内容都将覆盖主服务器配置。
显然,如果您对服务器配置/虚拟主机进行任何更改,那么您将需要重新启动 Apache。
由于您.htaccess
无论如何都在使用,您还可以设置ErrorDocument
in .htaccess
- 这将反过来覆盖虚拟主机/服务器配置。
RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^([^\.]+)$ $1\.php [NC,L]
这没有什么特别的问题......您正在匹配一个不包含点的请求的 URL 路径,并且如果它尚未映射到文件或目录,则您正在附加.php
扩展名。
关于此的一些注释:
.php
无论“带有.php
扩展名”的文件是否实际存在,您都可以附加扩展名。这不一定是错误的,只是 404 然后被触发/does-not-exist.php
而不是/does-not-exist
. 您可以改为检查目标文件是否存在。这将避免必须检查请求是否尚未映射到文件或目录。检查请求未映射到文件的第一个条件可能是不必要的,除非您有没有文件扩展名的文件(我认为这不太可能)。
[^\.]
- 无需反斜杠转义正则表达式字符类中的文字点。(虽然这样做没有害处,除了可读性IMO。)$1\.php
RewriteRule
-替换中的文字点无需反斜杠转义。这个参数是一个“普通”字符串(不是正则表达式),点在这里没有特殊含义。(尽管如此,这样做并没有什么坏处,除了可读性。)此处不需要该
NC
标志,因为您要匹配除正则表达式中的点以外的所有内容,无论如何它自然包括大写和小写字母。RewriteRule
如果这就是您使用 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}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]
注意:我假设您的.htaccess
文件位于文档根目录中,即。/var/www/html/.htaccess
?
推荐阅读
- robotframework - 在机器人框架中重新测试时如何标记通过测试
- amp-html - 如何将当前时间添加到 amp-video api (1.0v)?
- javascript - Vue JS 根据传递的 props 数据在挂载上获取数据总是返回 false
- tensorflow - 带有 tf.cond 的 TensorFlow 自定义激活函数
- java - JNA 的行为与我的 C# 对应物不同,为什么?
- css - 要并排放置的表单域
- c#-4.0 - 仅更改一个 Console.WriteLine 的颜色
- javascript - 通过单击按钮在 html 页面上显示名称。该按钮是使用数据库中的数据生成的
- shopify - 如何为我的 Shopify 产品动态设置 SEO 标题和描述
- javascript - 在每个间隔后都有一个循环来改变卡片的样式