我有一个网站,目前正在从旧 CMS 迁移到新 CMS(Laravel)。该网站只有部分语言已迁移到 Laravel。因此,基本上,我的 vhost 根文件夹有以下内容:
[D] staticContentDirectory1
[D] staticContentDirectory2
...
[D] oldCmsDirectory1
[D] oldCmsDirectory2
...
[D] oldCmsDirectoryN
[D] public
[F] index-of-the-old-cms-still-in-use.php
我有一个.htaccess
文件,它将旧 CMS 或静态内容目录未处理的所有内容重定向到 Laravel,如下所示:
RewriteRule ^((?!staticContentDirectory1|staticContentDirectory2|public)(.*))$ public/$1 [L]
还有一个.htaccess
来自 Laravel 的公共资源,用于处理其内容。
到目前为止,一切都运行良好,我们对结果非常满意(考虑到最初的限制)。
不过我们发现了一个问题。不知怎么的,Google 设法发现了/public
存在并对其进行了抓取,这导致 URL/public/
内部存在一个 URL,此后该 URL 已创建/public/public/
URL(幸运的是,它返回了 500 错误并避免了无限数量的 URL)。
在修复 CMS 之前,robots.txt
我们尝试通过重写/重定向流量来解决这个/public
问题/
。
我们尝试了很多方法,也发生了很多失败,几乎都是在无限循环的重定向中。
因为每个 Apache 模块似乎都独立完成其工作,混合RedirectMatch
并RewriteRule
失败,RewriteCond
并且RewriteRule
要么无限重定向,要么完全被忽略。
TL;DR:我现在正在寻求帮助:如何才能拥有一个 RewriteRule,/folder
并将所有流量从该文件夹重定向到根目录。
答案1
为了避免重定向循环,您需要区分对/public
子目录的直接请求和已内部重写到/public
子目录(这就是上面的指令所做的)。
有几种方法可以做到这一点。一种方法是检查THE_REQUEST
服务器变量,该变量包含从客户端发送的初始请求标头(例如GET /public/whatever HTTP/1.1
),并且在重写 URL 时不会发生变化。
.htaccess
尝试以下操作...作为一般规则,外部重定向应在内部重写之前进行,因此以下规则应位于子目录中文件顶部附近/public
(而不是.htaccess
文档根目录中的文件):
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /public
RewriteRule (.*) /$1 [R=302,L]
对于任意直接的/public/<whatever>
启动然后重定向到的请求/<whatever>
。上述RewriteCond
指令确保仅处理直接请求。
该RewriteRule
指令乍一看可能有点奇怪(好像它可能会重定向到自身),但这是因为RewriteRule
图案匹配 URL 路径减去目录前缀文件所在的位置.htaccess
。因此,给定对 的请求/public/<whatever>
,$1
反向引用仅捕获<whatever>
。因此重定向回/<whatever>
。
301
请注意,目前这是临时 (302) 重定向。只有当您确定它正常工作时才可将其更改为。301 会被浏览器严格缓存,因此如果出现错误,测试可能会出现问题。
混合
RedirectMatch
失败RewriteRule
由于指令属于不同的模块(mod_alias 与 mod_rewrite),因此它们在请求期间的执行时间不同,而不管它们在配置文件中的明显顺序如何(mod_rewrite 通常先运行)。因此混合这些指令确实会导致冲突。但是,RedirectMatch
不会为您提供此实例所需的控制。