php - htaccess 中的 RewriteRule 失败,但它可能是我的主机
问题描述
我读到自我破坏不是寻求帮助,所以我在这里。
所以,我有一个网站……使用 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=$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
其从 first 更改为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 上默认禁用,需要“显式”启用。不幸的是,一些共享主机确实在服务器配置中启用了此功能(这会导致比它修复的问题更多的问题 - 如果您没有预料到的话。)
在新主机上,这些重写规则确实会重写它,但 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
. 但是因为您已经触发了R
edirect,所以请求被“重定向”(而不是重写)到/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 作为路径信息传递给poem.php
.)此正则表达式仅匹配第三个(名称)路径段中的单个字母,因此它将无法匹配表单的请求 URL
/poem/123/name
,因此不会重写poem.php
请求并且请求失败(我怀疑是 404)。此正则表达式也不匹配尾部斜杠。(那么,斜杠真的是规范的吗?)
RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f
- 这些条件在您放置它们的地方完全是多余的。
RewriteCond
指令仅适用于RewriteRule
随后的第一个指令。
Options -FollowSymLinks
- 您需要
FollowSymLinks
mod_rewrite 才能工作。不要试图禁用它。FollowSymLinks
实际上是默认的Apache 设置,因此您只需要在服务器配置中禁用它时显式启用它(即。+FollowSymLinks
) 。.htaccess
解决方案
就个人而言,我不会在规范 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
推荐阅读
- swift - SwiftUI - 如何使用异步操作更改同步值
- c++ - C++ 固定容量关联容器
- kubernetes - 如何在 Kubernetes 中对 Pod 进行排队?
- javascript - “完全重新加载”Vue/Nuxt 组件
- html - 在 CSS 边框上放置 SVG 图标
- python-3.x - 如何改善美丽的汤 webscrape 循环?
- sql - Oracle SQL - 有条件的连接
- api - GET 端点是否会根据请求触发底层 API(使用 Postman 或 JMeter)
- apache-spark - 如何在pyspark中按列值而不是按行测试/训练拆分
- javascript - 如何连接两个字符串并在 Next.js 中的 React JSX 中搜索它们?以及如何使文件(MDX JS)内容可搜索?