htaccess 中的 RewriteRule 失败,但它可能是我的主机
RewriteRule in htaccess fails, but it could be my host
我读到 Self Sabotage is Not asking for help 所以我来了。
所以,我有一个站点...它使用 WAMP 运行良好。它在我当前的主机上运行良好。但我需要切换到一个新主机,现在它失败了。我认为这是一个 .htaccess
问题,但现在我不确定。在我当前的主机上,我没有 .htaccess
文件,但效果很好。在我使用 WAMP 的本地主机服务器上,我拥有与在我的新主机上相同的东西,但我只是禁用了 .htaccess
文件,将其重命名为 BAD.htaccess
,该网站仍然运行良好。这就是为什么我认为这是一个服务器端问题,我需要一些帮助。在虚拟主机中的 WAMP 服务器上,我为该“域”禁用了 +FollowSymLinks
。在我现在的主机上,我没有简单的方法来做到这一点,所以这就是他们给我的任何东西,但它有效。
我目前在 Ionos,并已切换到使用 cPanel 的 GreenGeeks。到目前为止,我还没有找到要编辑以删除的 vhosts 文件 +FollowSymLinks
,如果这甚至是问题的话。
也许可以用 .htaccess
来完成,如果是的话,这就是我需要做的。首先是我目前的 .htaccess
:
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^poems$ poems.php [R]
#RewriteRule ^poems/$ poems.php
RewriteRule ^collections$ collections/ [R]
RewriteRule ^collections/$ collections.php
RewriteRule ^poem$ poem/ [R]
RewriteRule ^poem/$ poem.php
RewriteRule ^poem/([0-9]+)/([a-zA-Z])$ poem.php?num=&poem= [NC,L]
RewriteRule ^collection$ collection/ [R]
RewriteRule ^collection/$ collection.php
# RewriteRule ^poem/([0=9]+)$ indpoem.php?num= [NC,L]
通过前两个设置,我可以转到 example.com/poems
,它将重定向或重写为 example.com/poems.php
,但看起来仍然像 example.com/poems
。与 collections
相同。在新主机上,那些重写规则确实会重写它,但 URL 或 URI 显示 example.com/poems.php
,根据当前的 SEO 标准,我不希望这样。尽管如此,我还是可以接受。
但是,当我进入下一个级别时... example.com/poem/#/poem-name
它在我的新主机上失败了。我确实有一个名为 poem.php
的文件,它应该重写。在该文件中,我使用以下内容获取 #
和名称...
$URL = explode("/",$_SERVER['REQUEST_URI']);
所以我不必做 _GET
。
如您所见,我尝试执行 RewriteRule
将其从第一个更改为 example.com/poem?111&name
,但这看起来很愚蠢,因为在 WAMP 上我不需要做任何事情。我可以尝试再次将其重写为相同的 URL,但我有一种行不通的感觉。如果确实如此,它可能会是 poem.php/#/name/
我在使用 cPanel 时缺少关于服务器配置的任何想法。我什至尝试过
Options -FollowSymLinks
在我的 .htaccess
文件中没有成功。
如有任何帮助,我们将不胜感激。我的 WAMP 和新主机拥有所有最新版本的 Apache 和 PHP.
这里有一些问题...
为了使站点在 完全没有 .htaccess
文件的情况下工作(在您的 WAMP 开发服务器和当前主机上)然后 MultiViews
(mod_negotiation 的一部分)必须已启用。是MultiViews
将/foo
“重写”为/foo.php
。
如果 MultiViews
启用,那么您当前的 .htaccess
文件基本上被覆盖,因为 MultiViews
内容协商发生在您的 mod_rewrite 指令之前已处理,因此您的 RewriteRule
模式 无法匹配。
MultiViews
在 Apache 上默认是禁用的,它需要“显式”启用。不幸的是,某些共享主机确实在服务器配置中启用了此功能(如果您不希望这样做,这会导致比修复更多的问题。)
On the new host those rewrite rules do rewrite it but the URL or URI shows example.com/poems.php
.
RewriteRule ^poems$ poems.php [R]
- 因为 MultiViews 被禁用并且您的指令在外部“重定向”
/poems
到 /poems.php
。这里没有“重写”。 R
(redirect
) 标志触发外部重定向。
RewriteRule ^poem$ poem/ [R]
RewriteRule ^poem/$ poem.php
但是,对于 /poem
,您重定向到 /poem/
(附加尾部斜杠)但您省略了 L
标志,因此处理继续并且请求进一步重写为/poem.php
。但是因为你已经触发了 R
edirect,请求被“重定向”(不是重写)到 /poem.php
,再次暴露 .php
.
重定向应该几乎总是包含 L
标志。事实上,您的所有规则都应包含 L
标志以进行优化并防止意外冲突。
为什么要重定向以附加尾部斜线(好像这是首选的规范 URL)?您在问题文本中没有提及这一点,据我所知,只有一个示例在 URL 上包含一个尾部斜线?那么,什么是preferred/canonicalURL呢? URL 你链接到什么?顺便说一句,MultiViews
不会附加尾部斜杠 - 因此不需要此重定向,或者您的站点在没有 .htaccess
文件的 WAMP/当前主机上实际上“运行良好”。 (?)(就个人而言,我 不会 使用尾部斜杠。)
RewriteRule ^poem/([0-9]+)/([a-zA-Z])$ poem.php?num=&poem= [NC,L]
:
$URL = explode("/",$_SERVER['REQUEST_URI']);
您的 PHP 脚本解析请求的 URL-路径(即 $_SERVER['REQUEST_URI']
),它不引用查询字符串。但是,上面的 RewriteRule
指令正在重写查询字符串 - 这似乎完全是多余的(“愚蠢” - 正如你所建议的)。因为您没有在 PHP 脚本中使用查询字符串,所以在使用 MultiViews 时请求仍然“有效”。
根据您的 PHP 脚本,您只需将请求重写为 poem.php
,无需查询字符串。 (这就是 MultiViews 所做的。虽然,严格来说,MultiViews 将 /poem/123/name
重写为 /poem.php/123/name
- 将额外的 URL-path 作为 path-info到 poem.php
.)
此正则表达式仅匹配第三个(名称)路径段中的单个字母,因此它将无法匹配 /poem/123/name
形式的请求 URL,因此请求未重写为 poem.php
并且请求失败(我怀疑是 404)。
此正则表达式也不匹配结尾的斜杠。 (那么,尾部斜杠真的规范吗?)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
- 这些条件完全是多余的。
RewriteCond
指令仅适用于第一个 RewriteRule
指令。
Options -FollowSymLinks
- 您需要
FollowSymLinks
才能 mod_rewrite 工作。不要试图禁用它。 FollowSymLinks
实际上是 默认 Apache 设置,因此如果它已被禁用,您只需要在 .htaccess
中明确启用它(即 +FollowSymLinks
)在服务器配置中。
解决方案
就个人而言,我不会在规范的 URL 上使用尾部斜杠。 (这与您的大部分示例和规则中使用的正则表达式一致。)
所以,综合以上几点:
Options +FollowSymLinks -MultiViews
RewriteEngine on
# Canonical redirect to remove trailing slash (from non-directories)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ / [R,L]
# Internal rewrites to ".php"
RewriteRule ^poems$ poems.php [L]
RewriteRule ^collections$ collections.php [L]
RewriteRule ^poem(/\d+/[\w-]+)?$ poem.php [L]
RewriteRule ^collection$ collection.php [L]
另一方面,如果规范 URL 应该包含尾部斜线,则相应地更改它:
Options +FollowSymLinks -MultiViews
RewriteEngine on
# Canonical redirect to append trailing slash to "all" URLs
RewriteRule !/$ ${REQUEST_URI}/ [R,L]
# Internal rewrites to ".php"
RewriteRule ^poems/$ poems.php [L]
RewriteRule ^collections/$ collections.php [L]
RewriteRule ^poem/(\d+/[\w-]+/)?$ poem.php [L]
RewriteRule ^collection/$ collection.php [L]
如果您有很多这样的 URLs/pages,那么您可以使它完全“通用”,而不必明确命名每个 URL/file。 IE。 “诗”、“集”等
或者,您只需启用 MultiViews 并让 mod_negotiation 重写 URL。但是,您将无法在重写之前规范尾部斜杠或验证请求,并且 MultiViews 适用于 所有内容 ,而不仅仅是您的 .php
文件,因此可能会创建重复内容。如果您需要进行任何特定的重写,例如重写查询字符串,那么 MultiViews 很可能会发生冲突。
Options +MultiViews
我读到 Self Sabotage is Not asking for help 所以我来了。
所以,我有一个站点...它使用 WAMP 运行良好。它在我当前的主机上运行良好。但我需要切换到一个新主机,现在它失败了。我认为这是一个 .htaccess
问题,但现在我不确定。在我当前的主机上,我没有 .htaccess
文件,但效果很好。在我使用 WAMP 的本地主机服务器上,我拥有与在我的新主机上相同的东西,但我只是禁用了 .htaccess
文件,将其重命名为 BAD.htaccess
,该网站仍然运行良好。这就是为什么我认为这是一个服务器端问题,我需要一些帮助。在虚拟主机中的 WAMP 服务器上,我为该“域”禁用了 +FollowSymLinks
。在我现在的主机上,我没有简单的方法来做到这一点,所以这就是他们给我的任何东西,但它有效。
我目前在 Ionos,并已切换到使用 cPanel 的 GreenGeeks。到目前为止,我还没有找到要编辑以删除的 vhosts 文件 +FollowSymLinks
,如果这甚至是问题的话。
也许可以用 .htaccess
来完成,如果是的话,这就是我需要做的。首先是我目前的 .htaccess
:
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^poems$ poems.php [R]
#RewriteRule ^poems/$ poems.php
RewriteRule ^collections$ collections/ [R]
RewriteRule ^collections/$ collections.php
RewriteRule ^poem$ poem/ [R]
RewriteRule ^poem/$ poem.php
RewriteRule ^poem/([0-9]+)/([a-zA-Z])$ poem.php?num=&poem= [NC,L]
RewriteRule ^collection$ collection/ [R]
RewriteRule ^collection/$ collection.php
# RewriteRule ^poem/([0=9]+)$ indpoem.php?num= [NC,L]
通过前两个设置,我可以转到 example.com/poems
,它将重定向或重写为 example.com/poems.php
,但看起来仍然像 example.com/poems
。与 collections
相同。在新主机上,那些重写规则确实会重写它,但 URL 或 URI 显示 example.com/poems.php
,根据当前的 SEO 标准,我不希望这样。尽管如此,我还是可以接受。
但是,当我进入下一个级别时... example.com/poem/#/poem-name
它在我的新主机上失败了。我确实有一个名为 poem.php
的文件,它应该重写。在该文件中,我使用以下内容获取 #
和名称...
$URL = explode("/",$_SERVER['REQUEST_URI']);
所以我不必做 _GET
。
如您所见,我尝试执行 RewriteRule
将其从第一个更改为 example.com/poem?111&name
,但这看起来很愚蠢,因为在 WAMP 上我不需要做任何事情。我可以尝试再次将其重写为相同的 URL,但我有一种行不通的感觉。如果确实如此,它可能会是 poem.php/#/name/
我在使用 cPanel 时缺少关于服务器配置的任何想法。我什至尝试过
Options -FollowSymLinks
在我的 .htaccess
文件中没有成功。
如有任何帮助,我们将不胜感激。我的 WAMP 和新主机拥有所有最新版本的 Apache 和 PHP.
这里有一些问题...
为了使站点在 完全没有
.htaccess
文件的情况下工作(在您的 WAMP 开发服务器和当前主机上)然后MultiViews
(mod_negotiation 的一部分)必须已启用。是MultiViews
将/foo
“重写”为/foo.php
。如果
MultiViews
启用,那么您当前的.htaccess
文件基本上被覆盖,因为MultiViews
内容协商发生在您的 mod_rewrite 指令之前已处理,因此您的RewriteRule
模式 无法匹配。MultiViews
在 Apache 上默认是禁用的,它需要“显式”启用。不幸的是,某些共享主机确实在服务器配置中启用了此功能(如果您不希望这样做,这会导致比修复更多的问题。)
On the new host those rewrite rules do rewrite it but the URL or URI shows
example.com/poems.php
.RewriteRule ^poems$ poems.php [R]
- 因为 MultiViews 被禁用并且您的指令在外部“重定向”
/poems
到/poems.php
。这里没有“重写”。R
(redirect
) 标志触发外部重定向。
RewriteRule ^poem$ poem/ [R] RewriteRule ^poem/$ poem.php
但是,对于
/poem
,您重定向到/poem/
(附加尾部斜杠)但您省略了L
标志,因此处理继续并且请求进一步重写为/poem.php
。但是因为你已经触发了R
edirect,请求被“重定向”(不是重写)到/poem.php
,再次暴露.php
.重定向应该几乎总是包含
L
标志。事实上,您的所有规则都应包含L
标志以进行优化并防止意外冲突。为什么要重定向以附加尾部斜线(好像这是首选的规范 URL)?您在问题文本中没有提及这一点,据我所知,只有一个示例在 URL 上包含一个尾部斜线?那么,什么是preferred/canonicalURL呢? URL 你链接到什么?顺便说一句,
MultiViews
不会附加尾部斜杠 - 因此不需要此重定向,或者您的站点在没有.htaccess
文件的 WAMP/当前主机上实际上“运行良好”。 (?)(就个人而言,我 不会 使用尾部斜杠。)
RewriteRule ^poem/([0-9]+)/([a-zA-Z])$ poem.php?num=&poem= [NC,L] : $URL = explode("/",$_SERVER['REQUEST_URI']);
您的 PHP 脚本解析请求的 URL-路径(即
$_SERVER['REQUEST_URI']
),它不引用查询字符串。但是,上面的RewriteRule
指令正在重写查询字符串 - 这似乎完全是多余的(“愚蠢” - 正如你所建议的)。因为您没有在 PHP 脚本中使用查询字符串,所以在使用 MultiViews 时请求仍然“有效”。根据您的 PHP 脚本,您只需将请求重写为
poem.php
,无需查询字符串。 (这就是 MultiViews 所做的。虽然,严格来说,MultiViews 将/poem/123/name
重写为/poem.php/123/name
- 将额外的 URL-path 作为 path-info到poem.php
.)此正则表达式仅匹配第三个(名称)路径段中的单个字母,因此它将无法匹配
/poem/123/name
形式的请求 URL,因此请求未重写为poem.php
并且请求失败(我怀疑是 404)。此正则表达式也不匹配结尾的斜杠。 (那么,尾部斜杠真的规范吗?)
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f
- 这些条件完全是多余的。
RewriteCond
指令仅适用于第一个RewriteRule
指令。
Options -FollowSymLinks
- 您需要
FollowSymLinks
才能 mod_rewrite 工作。不要试图禁用它。FollowSymLinks
实际上是 默认 Apache 设置,因此如果它已被禁用,您只需要在.htaccess
中明确启用它(即+FollowSymLinks
)在服务器配置中。
解决方案
就个人而言,我不会在规范的 URL 上使用尾部斜杠。 (这与您的大部分示例和规则中使用的正则表达式一致。)
所以,综合以上几点:
Options +FollowSymLinks -MultiViews
RewriteEngine on
# Canonical redirect to remove trailing slash (from non-directories)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ / [R,L]
# Internal rewrites to ".php"
RewriteRule ^poems$ poems.php [L]
RewriteRule ^collections$ collections.php [L]
RewriteRule ^poem(/\d+/[\w-]+)?$ poem.php [L]
RewriteRule ^collection$ collection.php [L]
另一方面,如果规范 URL 应该包含尾部斜线,则相应地更改它:
Options +FollowSymLinks -MultiViews
RewriteEngine on
# Canonical redirect to append trailing slash to "all" URLs
RewriteRule !/$ ${REQUEST_URI}/ [R,L]
# Internal rewrites to ".php"
RewriteRule ^poems/$ poems.php [L]
RewriteRule ^collections/$ collections.php [L]
RewriteRule ^poem/(\d+/[\w-]+/)?$ poem.php [L]
RewriteRule ^collection/$ collection.php [L]
如果您有很多这样的 URLs/pages,那么您可以使它完全“通用”,而不必明确命名每个 URL/file。 IE。 “诗”、“集”等
或者,您只需启用 MultiViews 并让 mod_negotiation 重写 URL。但是,您将无法在重写之前规范尾部斜杠或验证请求,并且 MultiViews 适用于 所有内容 ,而不仅仅是您的 .php
文件,因此可能会创建重复内容。如果您需要进行任何特定的重写,例如重写查询字符串,那么 MultiViews 很可能会发生冲突。
Options +MultiViews