我有一个网站,目前正在从一个旧的CMS迁移到一个新的(Laravel)。 只有一些网站的语言已经被转移到Laravel。 所以基本上,我的虚拟主机的根文件夹是这样的:
[D] staticContentDirectory1 [D] staticContentDirectory2 ... [D] oldCmsDirectory1 [D] oldCmsDirectory2 ... [D] oldCmsDirectoryN [D] public [F] index-of-the-old-cms-still-in-use.php
我有一个.htaccess文件,将旧CMS或静态内容目录中没有处理的所有内容redirect到Laravel,如下所示:
RewriteRule ^((?!staticContentDirectory1|staticContentDirectory2|public)(.*))$ public/$1 [L]
Laravel也有公开的.htaccess来处理它的东西。
到目前为止,一切工作都很完美,我们对结果非常满意(给定初始约束条件)。
我们发现了一个问题。 不知何故,谷歌设法发现/public存在并抓取它,导致与/public/里面,从那以后创build/public/public/ URLs(幸运的是,返回一个500错误,避免无限的URL)。
在修复CMS和robots.txt之前,我们试图通过将stream量从/public重写/redirect到/来解决这个问题。
很多事情都经过了尝试,发生了很多失败,几乎全部都是无限循环的redirect。
因为每个Apache模块似乎都是自己做的,混合RedirectMatch和RewriteRule失败了。 RewriteCond和RewriteRule是无限的redirect或完全忽略。
TL; DR:我现在正在寻求帮助:如何将RewriteRule /folder到/folder ,然后将所有stream量从该文件夹redirect到根目录。
为了避免redirect循环,你需要区分/public子目录的直接请求和内部重写到/public子目录的请求(这是你的指令在上面做的)。
有几种方法可以做到这一点。 一种方法是检查从客户端发送的包含初始请求头的THE_REQUEST服务器variables(例如, GET /public/whatever HTTP/1.1 ),并且在URL被重写时不会改变。
请尝试以下操作…通常,外部redirect应在内部重写之前进行,因此以下规则应该位于/public子目录(不是文档根目录中的.htaccess文件)的.htaccess文件顶部附近:
RewriteCond %{THE_REQUEST} ^[AZ]{3,9}\ /public RewriteRule (.*) /$1 [R=302,L]
对于任何启动/public/<whatever> 直接请求,然后redirect到/<whatever> 。 前面的RewriteCond指令确保只处理直接请求。
RewriteRule指令最初看起来可能有点奇怪(好像它可能redirect到自己),但是这是因为RewriteRule 模式匹配URLpath而不是 .htaccess文件所在的目录前缀 。 所以,给予/public/<whatever>的请求, $1反向引用只能捕获<whatever> 。 所以redirect到/<whatever> 。
请注意,这是目前临时(302)redirect。 只有在确定工作正常的情况下,才能将其更改为301 。 301s被浏览器强制caching,如果出现错误,可能会使testing出现问题。
混合
RedirectMatch和RewriteRule失败
由于指令属于不同的模块(mod_alias vs mod_rewrite),它们在请求期间的不同时间执行,不pipe它们在configuration文件中的顺序如何(mod_rewrite通常先运行)。 所以混合这些指令确实会导致冲突。 但是, RedirectMatch并没有给你这个实例所需的控件。