使用 Apache,将流量重写到某个文件夹,但重定向来自该文件夹的所有流量

使用 Apache,将流量重写到某个文件夹,但重定向来自该文件夹的所有流量

我有一个网站,目前正在从旧 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 模块似乎都独立完成其工作,混合RedirectMatchRewriteRule失败,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不会为您提供此实例所需的控制。

相关内容