
我的虛擬主機中有以下內容用於 SSL 連線(我的非 ssl 虛擬主機看起來相同,但沒有用於重定向的第一個規則集)。
DocumentRoot /var/www/example.com/public/
<Directory "/var/www/example.com/public/">
#only mod_rewrite configuration is shown here
RewriteEngine on
RewriteBase /
RewriteCond $1 !=signup
RewriteCond $1 !=login
RewriteCond $1 !=welcome
RewriteCond $1 !=thankyou
RewriteRule ^(.*)$ http://example.com/$1 [L,R,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteRule ^(.+)$ index.php?q=$1 [L,QSA]
</Directory>
我的目的是讓任何不匹配的頁面請求(signup|login|welcome|thankyou)重定向到非ssl虛擬主機而不進行進一步處理,否則不重定向,而是在SSL虛擬主機內處理請求。
第一個 RewriteRule 集負責重新導向,而第二個 RewriteRule 集負責正常頁面處理。
如果沒有第一個規則集,所有請求都會在 SSL 虛擬主機下正確載入。
使用第一個規則集,重定向可以正常工作,但與列出的資源不符。例如。請求
https://example.com/about
重定向到
http://example.com/about
但是當請求註冊、登入、歡迎和感謝頁面時,就會出現問題。這些請求也會被重新導向到非 ssl 站點,但方式會被破壞。請求
https://example.com/signup
重定向到
http://example.com/index.php?q=signup
看起來第一個規則集不符(如預期的那樣),然後在處理第二個規則集之後,再次應用第一個規則集(不是預期的)。
我無法將這種意外行為與任何記錄的功能相匹配。
有任何想法嗎?
編輯
我在文件中發現了一些模糊的引用,當規則匹配發生在「目錄上下文」中時,apache 重新運行規則,但是,該引用是關於 .htaccess 的。我的重寫發生在 <VirtualHost> 標記內的 <Directory> 標記內。我目前正在測試將重寫移到 <Directory> 上下文之外 - 這似乎確實會改變行為,但我尚未使其按照我的需要工作。
編輯2
該問題肯定是由於當規則處理存在於目錄上下文中時 apache 重新啟動重寫處理所引起的。我已將規則處理移至 <Directory> 標記之外。但是,現在 RewriteCond 行不起作用...例如。
RewriteCond %{REQUEST_FILENAME} -f
因為 apache 尚未將請求的資源解析為使用 DocumentRoot 的檔案對映。真是一團糟。
因此,我然後手動將在 DocumentRoot 中指定的值新增到 RewriteCond 中。然而,這似乎是一個糟糕的駭客。例如。
RewriteCond /var/www/example.com/public%{REQUEST_FILENAME} -f
因此,現在我正在尋找一種方法來防止 apache 在目錄上下文中重新啟動重寫過程,或者是第二好的方法,一種在 <VirtualHost> 層級指定必要的 RewriteConds 的更好方法。
答案1
我建議將以下內容新增到您的配置中,這將為您提供 mod_rewrite 正在執行的操作及其原因的詳細日誌。這可能有助於弄清楚為什麼你有這樣的行為:
RewriteLog /tmp/rewrite.log RewriteLogLevel 9
完成分析後,請確保刪除這些行,因為它們確實會影響效能。
答案2
我已經確定了以下解決方案,將重寫放在任何 <Directory ...> 部分之外。這允許我將任何不應該是 SSL 的請求重定向到非 SSL 站點,同時允許透過 SSL 提供任何靜態內容(圖像、css、js 等)。
<VirtualHost ...>
...
RewriteEngine on
RewriteCond $1 !=signup
RewriteCond $1 !=login
RewriteCond $1 !=welcome
RewriteCond $1 !=thankyou
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^/(.*)$ http://example.com/$1 [R=303,QSA,L]
RewriteCond %{REQUEST_URI} !=/favicon.ico
RewriteCond %{REQUEST_URI} !=/robots.txt
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^/(.+)$ /index.php?q=$1 [QSA,L]
...
</VirtualHost>