2012-03-12 256 views
0

我知道这是一个非常高度讨论的主题,但我无法弄清楚我使用我的搜索技巧做错了什么。htaccess的子域名无法按预期方式工作

用下面的文件夹结构既是domain.local的根和board.domain.local

/ 
app/ 
bin/ 
board/ 
    index.php 
src/ 
vendor/ 
web/ 
    index.php 

这的.htaccess在/文件夹

<IfModule mod_rewrite.c> 
    RewriteEngine On 
    RewriteCond %{HTTP_HOST} ^board.domain.local$ 
    RewriteRule ^(.*)$ board/$1 [QSA,L] 
    RewriteCond %{HTTP_HOST} ^domain.local$ 
    RewriteRule ^(.*)$ web/$1 [QSA,L] 
</IfModule> 

访问board.domain.local当我得到一个内部服务器错误。访问domain.local完美工作,并将查询重定向到web/

为什么第一次重写不起作用?

回答

3

您正在按目录上下文进行相对路径重写,而不使用RewriteBase。为什么一个人可以工作,但另一个人不工作是因为其他地方的一些补偿因素,这在boardweb之间是不一致的。内部服务器错误可能是一个循环。检查你的错误日志。

RewriteEngine On 
RewriteBase/ # need this sucker 
RewriteCond %{HTTP_HOST} ^board.domain.local$ 
RewriteRule ^(.*)$ board/$1 [QSA,L] 
RewriteCond %{HTTP_HOST} ^domain.local$ 
RewriteRule ^(.*)$ web/$1 [QSA,L] 

在每个目录上下文中,重写是在文件系统路径上完成的,而不是在URL上完成的。重写仅在目录之后的路径部分完成,该目录被剥离。如果您进行相对重写,则目录部分将在后面放回。然后,发生一个愚蠢的事情:重写被视为一个URL! RewriteBase指定用于重写的前缀(而不是天真地恢复路径前缀)以使其成为有效的URL。 RewriteBase说,“虽然我们正在处理目录/var/www/docroot它实际上代表了URL空间/,所以当从重写中重新生成URL时,它们应该在该空间中,而不是在/var/www/docroot这不是URL”。

问问自己:什么是DocRoot?那么当DocRoot由于缺少RewriteBase而被错误地作为前缀时,URL-s会从相对重写中出来?通过你的配置跟踪这些伪造的URL-s的处理,你一定会发现一个人进入无限循环而另一个没有进入的原因。

+0

我会对此做一个稍微不同的解释:重写总是在URI上下文中完成,但是被修改为FS路径。如果您没有指定正确的RewriteBase来帮助引擎将URI映射到当前目录,那么引擎可能(并且经常)会错误地映射此映射。但除了一般问题陈述中的+1之外。这通常不是很好理解。 – TerryE 2012-03-12 23:21:12

+0

[@Kaz。我是否会生气或者我刚刚对你的一个不存在的评论?]是的,我同意路径名被删除,然后重新应用,就像你从重写日志中看到的级别大于5的IIRC。但是这是一个伪URI,当它出错时,我有很多实例。所以(i)如你所说总是指定一个基地,并且(ii)在规则之后总是使用[L] - 我刚刚看到太多的情况,如果你不立即强制内部重定向。 – TerryE 2012-03-12 23:50:44

+0

+1 Kaz很好的答案 – 2012-03-13 09:29:38

0

尝试增加一些条件,以保持重写引擎从循环(你的URI最终将成为/板/板/板/板/板/板/板/主板/等)

RewriteEngine On 

RewriteCond %{HTTP_HOST} ^board.domain.local$ 
RewriteCond %{REQUEST_URI} !^/board 
RewriteRule ^(.*)$ board/$1 [QSA,L] 

RewriteCond %{HTTP_HOST} ^domain.local$ 
RewriteCond %{REQUEST_URI} !^/web 
RewriteRule ^(.*)$ web/$1 [QSA,L] 
+0

但如果循环,为什么'web'改写工作?如果它变成了'web/web/web/web/...',那么它不应该也不工作吗? – 2012-03-12 19:33:11

+0

我不知道为什么这样,当我测试你的规则在我的干净的Apache安装在htaccess文件,都循环。您可以尝试打开'RewriteLog'并在您的服务器配置中设置'RewriteLogLevel 5'来查看发生了什么。 – 2012-03-12 20:18:13

0

这是对Kaz的评论的补充,因为我同意他们,但它不符合评论字符限制。如果处理了一个.htaccess文件(在每个目录上下文中),如果发生了一个或多个重写更改了URI,则会发生内部重定向。 .htaccess扫描将重新启动,并对规则进行评估。

默认情况下,只使用一组重写规则:这是RewriteEngine On路径中最低.htaccess中的那些规则。因此,在第二阶段请求domain.local的情况下,如果DOCROOT/web/.htaccess请求,那么对于domain.local的请求,将执行此代替DOCROOT/.htaccess

另一个方面是循环问题,我看到你已经解决了每个规则的第二个rewritecond。然而,这可能会失败,您可以启用MultiViews等选项(另一个怪异的Apache botch会对重写规则造成严重破坏),因为这样会将查询拆分开来,并执行子查询,从而可以阻止此类反递归条件。

因此,我总是将MultiViews和DirectoryIndex与搜索列表关联起来。

您还可以将[NS]标志添加到所有规则中,因为在子查询中都不适用。我还设置环境变量END = true以强制退出,当我想要做到这一点,在我的规则上使用这个塞子:

RewriteCond %{IS_SUBREQ}%{ENV:END} true 
RewriteRule^     - [L] 
相关问题