2013-02-12 128 views
1

我的目標是從這些路徑將用戶重定向:重寫規則,以新的URL和內部重寫舊

/foo/index.php 
/foo/ 

/index 

而且具有/index負荷/foo/index.php原始內容。

這可能性在.htaccess

到目前爲止,我已經試過:

RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L] 
RewriteRule ^index$ /foo/index.php [QSA,L] 

但這進入一個無限循環的重定向。我想添加一個RewriteCond的URI會有所幫助,但是從docs

注:RewriteRule的格局相匹配後條件正在處理中。

顯然RewriteCond在我的使用情況下不會有太大用處。

通過Rewrite Flags docs看,該S標誌似乎正是我在尋找:

此標記強制重寫引擎跳過序列中的下一NUM規則,如果當前的規則相匹配。使用這個來僞造if-then-else結構:then-clause的最後一條規則變成skip = N,其中N是else子句中的規則數目。

所以我已經試過:

RewriteRule ^index$ /foo/index.php [QSA,L,S=1] 
RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L] 

雖然,因爲我有L標誌,該標誌S似乎有點多餘。儘管如此,我認爲這種邏輯似乎是正確的,儘管這仍然處於無限的重定向循環中。

現在我正在使用PHP的解決方法。首先,Apache在內部將新URL重寫爲舊的,然後在PHP中檢查$_SERVER['REQUEST_URI']是否與腳本開頭的新格式相匹配,否則將301重定向到新URL。

雖然,我想知道是否可以單獨使用.htaccess?或者如果任何人可以解釋如何/爲什麼我會通過上面的重寫規則獲得無限循環,我將不勝感激。

回答

1

麻煩的是,這些規則在.htaccess文件,爲docs說,這個文件每隔rewite循環之後重新解析,letst它可能會在不同的目錄已經適用於.htaccess。因此你的L標誌都是徒勞的。

我看了看周圍,如果你真的不能把你的重寫規則放在主要的apache配置中,我可以提供以下kludge:因爲服務器變量THE_REQUEST在重寫運行之間沒有更新,所以可以推斷出「瀏覽器顯示的網址」從那裏和防止改寫在這種情況下:

# external redirect to /index (unless browser already shows /index plus query params) 
RewriteCond %{THE_REQUEST} !^\w+\ /index(\?.*)?\ HTTP/1..$ 
RewriteRule ^foo/(index\.php)?$ /index [R=301,QSA,L] 

# internal redirect for /index 
RewriteRule ^index$ /foo/index.php [QSA,L] 

我認爲有也是不變的另一個變量,但現在我找不到它。也許是別人?

+0

+1,正如你所說的,唯一合乎邏輯的解釋是'L'實際上並沒有結束重寫,而是開始一個新的重寫循環?但是,如果我按照你所說的將這些放在主要配置文件上,它是否可以解決這個問題?現在去測試。 – 2013-02-12 23:28:34

+1

噢,是的,我應該先閱讀完整的'L'標誌文檔。我已經更新了你的正則表達式,以便始終在請求路徑名稱開頭匹配'/ index':'RewriteCond%{THE_REQUEST}!^ \ w + \/index(?:\?。*)?'現在它工作得很好, 謝謝。 – 2013-02-13 00:09:18

+0

是的,你的正則表達式看起來更好,我更新了我的答案 – 2013-02-13 08:08:26