如何防止 apache 在「目錄上下文」中重新啟動重寫處理

如何防止 apache 在「目錄上下文」中重新啟動重寫處理

我的虛擬主機中有以下內容用於 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>

相關內容