htaccess 中的 RewriteRule 失败,但它可能是我的主机

Posted

技术标签:

【中文标题】htaccess 中的 RewriteRule 失败,但它可能是我的主机【英文标题】:RewriteRule in htaccess fails, but it could be my host 【发布时间】:2021-07-05 00:34:28 【问题描述】:

我读到了Self Sabotage is Not asking for help,所以我在这里。

所以,我有一个网站...使用 WAMP 效果很好。它在我当前的主机上运行良好。但是我需要切换到新主机,现在它失败了。我认为这是.htaccess 问题,但现在我不确定。在我当前的主机上,我没有 .htaccess 文件,它工作得很好。在我使用 WAMP 的本地主机服务器上,我和我的新主机上的东西一样,但我只是禁用了 .htaccess 文件,将其重命名为 BAD.htaccess,并且该站点仍然运行良好。这就是为什么我认为这是一个服务器端问题,我需要一些帮助。在我的虚拟主机 WAMP 服务器上,我为该“域”禁用了 +FollowSymLinks。在我目前的主机上,我没有简单的方法来做到这一点,所以这只是他们给我的任何东西,但它有效。

我目前在 Ionos 工作,并已切换到使用 cPanel 的 GreenGeeks。到目前为止,我还没有找到要编辑以删除 +FollowSymLinks 的 vhosts 文件,如果这甚至是问题的话。

也许它可以通过.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=$1&poem=$2 [NC,L]

RewriteRule ^collection$ collection/ [R]
RewriteRule ^collection/$ collection.php

# RewriteRule ^poem/([0=9]+)$ indpoem.php?num=$1  [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。

【问题讨论】:

尝试禁用MultiViews。在这种情况下,这通常是罪魁祸首,在“假”网址和实际存在的文件之间存在部分重叠。 谢谢,我试过了。至少我认为我做到了。似乎覆盖这些东西的唯一方法是在.htaccess中。所以我上传了一个只有 Options -MultiViews 的文件,但它没有用。然后我上传了添加的原始文件。仍然没有运气。奇怪的是它可以在我的 WAMP 和其他没有 .htaccess 的服务器上运行。在我的 WAMP 上,我什至在 vhosts 文件中禁用了 FollowSymLInks,认为这导致了问题。感谢您的回复。 您的规范网址是否包含尾部斜杠?您正在重定向以在指令中附加斜杠,但您的大多数示例都省略了它? 【参考方案1】:

这里有几个问题...

为了使网站能够在完全没有.htaccess 文件(在您的WAMP 开发服务器和当前主机上)运行,那么必须启用MultiViews(mod_negotiation 的一部分)。将/foo“重写”为/foo.php的是MultiViews

如果MultiViews 已启用,那么您当前的.htaccess 文件基本上会被覆盖,因为MultiViews 内容协商发生在您的mod_rewrite 指令被处理之前,因此您的RewriteRule 模式 无法匹配.

MultiViews 在 Apache 上默认禁用,需要“显式”启用。不幸的是,一些共享主机确实在服务器配置中启用了此功能(这会导致比它修复的问题更多 - 如果您没有预料到的话。)

在新主机上,这些重写规则确实会重写它,但 URL 或 URI 显示 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。但是因为你已经触发了Redirect,所以请求被“重定向”(而不是重写)到/poem.php,再次暴露了.php

重定向应该几乎总是包含L 标志。事实上,您的所有规则都应该包含 L 标志以进行优化并防止意外冲突。

为什么要重定向以附加斜杠(好像这是首选的规范 URL)?您在问题文本中没有提到这一点,据我所知,您的示例中只有一个在 URL 上包含斜杠?那么,什么是首选/规范 URL?你链接到哪个网址?顺便说一句,MultiViews 不会附加斜杠 - 所以要么不需要这个重定向,要么你的网站在没有 .htaccess 文件的 WAMP / 当前主机上实际上不是“运行良好”。 (?)(就我个人而言,我不会使用斜杠。)

 RewriteRule ^poem/([0-9]+)/([a-zA-Z])$ poem.php?num=$1&poem=$2 [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-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 (.*)/$ /$1 [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]

如果您有许多这样的 URL/页面,那么您可以将其完全“通用”,而无需显式命名每个 URL/文件。 IE。 “诗”、“集”等


或者,您只需启用 MultiViews 并让 mod_negotiation 重写 URL。但是,您将无法在重写之前规范化尾部斜杠或验证请求,并且 MultiViews 适用于所有内容,而不仅仅是您的.php 文件,因此可能会创建重复的内容。如果您需要进行任何特定的重写,例如重写查询字符串,那么 MultiViews 可能会发生冲突。

Options +MultiViews

【讨论】:

哇,谢谢怀特先生。我认为这回答了我所有的问题。我尝试联系我的主机以查看是否存在一些服务器端问题,但他们不是很有帮助。在阅读了您非常详细的帖子后,一定是在服务器上禁用了 MultiViews。我确实尝试将其添加到 .htaccess 文件中,但没有删除所有重写。我会先试试。至于 /(slash) 重写,这是我过去所做的,它似乎有效,可能是因为我正在重写查询。 最初我并没有将其重写为一个查询,只是重定向到页面并让它与_SERVER一起工作,当我发布我的问题时,我一定没有删除该部分。我知道在我的 WAMP 上的虚拟主机中启用了 Multiviews,我猜我的旧主机启用了它,但新主机没有启用。因此,我将首先尝试该解决方案。到目前为止,我认为它不会影响我的网站,但也许当我添加更多内容时,它可能会因此我也会尝试您的其他解决方案。太感谢了。我花了几个小时在这里、youtube 和整个互联网上搜索,但找不到这么简洁的答案。

以上是关于htaccess 中的 RewriteRule 失败,但它可能是我的主机的主要内容,如果未能解决你的问题,请参考以下文章

我的 .htaccess 中的 RewriteRule 命令不起作用

htaccess 中的 Apache RewriteRule - 路由已损坏

htaccess 中的 RewriteRule 失败,但它可能是我的主机

转载 .htaccess文件RewriteRule语法规则

apache使用.htaccess文件中RewriteRule重定向后,URL中的加号无法解析

向 .htaccess 添加注释