2012-03-12 131 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] 
相關問題