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。但是因为你已经触发了 Redirect,请求被“重定向”(不是重写)到 /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-infopoem.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