Apache-2.4

將 htaccess 重寫規則轉換為 Apache2 虛擬主機規則

  • March 24, 2017

我試圖RewriteRule通過結合.htaccess我之前成功實施的一些規則來設置萬用字元子域,相信我可以對我的 Apache vhosts 文件使用相同的規則。

本質上,example.comwww.example.com轉到根路徑並尋找index.php. 根級別的所有其他(動態)子域請求,例如abc.example.com重寫(對瀏覽器不可見)到example.com/process.php?p=abc.

其次,任何來自基本/根級別之外的子域的文件請求都需要重寫,以便從沒有子域的標準域的根路徑中獲取。所以abc.example.com/css/style.css需要來自example.com/css/style.css

這是我這樣做的嘗試。我收到一個 Apache 錯誤:

您無權訪問此伺服器上的 /index.php。

對於任何子域嘗試,除了 www ,它按預期工作,以及 standard example.com,它仍然可以正常工作。

<VirtualHost *:80>

       ServerAdmin webmaster@example.com
       ServerName example.com
       ServerAlias www.example.com
       DocumentRoot /var/www/example.com/public_html

       ErrorLog ${APACHE_LOG_DIR}/error.log
       CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

<VirtualHost *:80>
       ServerAdmin webmaster@example.com
       ServerName other.example.com
       ServerAlias *.example.com
       DocumentRoot /var/www/example.com/public_html/

       <Directory /var/www/example.com/public_html/>
       Options FollowSymLinks
       AllowOverride all
       Require all granted

       RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
               RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC]
               RewriteRule ^$ /process.php?p=%2 [QSA,NC]
               RewriteCond %{REQUEST_FILENAME} !^$ [NC]
               RewriteRule ^(.*) http://www.example.com/$1 [P]
       </Directory>
</VirtualHost>

我以此為基礎成功地將不同域的根目錄重定向到example.com使用該.htaccess文件,該文件包含process.php所有其他請求並將其發送到example.com.

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

# Check the request isn't an existing file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^$ http://www.example.com/process.php [P]
RewriteCond %{REQUEST_FILENAME} !^$ [NC]
RewriteRule ^(.*) http://www.example.com/$1 [P]

而且在這個.htaccess測試之外,我成功地將子域作為變數重定向process.php,儘管它沒有擷取其他文件請求,例如上面的 css 範例:

Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC]
RewriteRule ^$ /process.php?p=%2 [QSA,NC]

更新 1

使用以下內容代替我的第二個虛擬主機條目,我已經(似乎)取得了一些成功。如果我使用子域,process.php則正在輸出頁面。雖然模式匹配似乎在這方面起作用,但我實際process.php接收的是一個空變數,而不是預期的子域作為字元串(對於:)process.php?p=%2

<VirtualHost *:80>
       ServerAdmin webmaster@example.com
       ServerName other.example.com
       ServerAlias *.example.com
       DocumentRoot /var/www/example.com/public_html

       <Directory /var/www/example.com/public_html>
       Options FollowSymLinks
       AllowOverride all
       Require all granted
       RewriteEngine on
       RewriteBase /

       RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
       RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC]
       RewriteCond %{REQUEST_URI} ^/$
       RewriteRule ^$ /process.php?p=%2 [NC,QSA]
       </Directory>
</VirtualHost>

更新 2

我以迂迴的方式解決了這個問題,但我不確定這是否是最優雅的方式。

使用上面的更新 1程式碼,我看到任何查詢字元串仍在附加,但在我的頁面%2中沒有被接收。我可能錯誤地認為,儘管根據我的程式碼說明,url 沒有向瀏覽器顯示 url 中的變數,但內部 url 仍然傳遞了它們。儘管如此,我意識到仍然可以使用in將子域確定為字元串,並將其用作頁面上的變數,其方式與我最初的想法類似。GET``process.php``p=abc``process.php``$_SERVER['HTTP_X_FORWARDED_HOST']``PHP

RewriteCond %{HTTP_HOST} !^www\.example\.com$ [NC]
RewriteCond %{HTTP_HOST} ^(www\.)?([^\.]+)\.example\.com$ [NC]
RewriteCond %{REQUEST_URI} ^/$
RewriteRule ^$ /process.php?p=%2 [NC,QSA]

%2設置反向引用,因為這是對最後匹配的CondPattern (RewriteCond模式) 的第二個擷取組的反向引用。最後匹配的 CondPattern^/$沒有任何擷取的組,因此%2始終為空。

無論如何,第三RewriteCond條指令看起來是多餘的。RewriteRule模式已經對此進行了檢查^$(在每個目錄的上下文中,目錄前綴已被刪除 - 所以這是正確的)。

第一個RewriteCond指令看起來也是多餘的。任何請求www.example.com都將被第一個 VirtualHost 擷取,因此此 VirtualHost 中的主機名無論如何都不會www.example.com,因此該指令始終評估為 true。

我會將其重寫為:

RewriteCond %{HTTP_HOST} ^(?:www\.)?([^.]+)\.example\.com$ [NC]
RewriteRule ^$ process.php?p=%1 [QSA]

我已經使第一非擷取即。(?:www\.)-?:使其無法擷取。所以,我們只得到%1實際的子域。此外,無需轉義字元類中的點(以匹配文字點)。這裡的NC旗幟RewriteRule是多餘的。

由於您在指令中指定了 URL 路徑,因此我還刪除了RewriteRule 替換RewriteBase的斜杠前綴。

這只會重寫abc.example.com/,即。對文件根的請求。

其次,任何來自基本/根級別之外的子域的文件請求都需要重寫,以便從沒有子域的標準域的根路徑中獲取。所以abc.example.com/css/style.css需要從example.com/css/style.css.

既然abc.example.com/example.com/指向文件系統上的同一個地方,我看不到你需要在這裡做任何事情嗎?example.com/css/style.css應該指向同一個文件abc.example.com/css/style.css

文件根目錄中的其他文件呢?例如。abc.example.com/file. 目前這只是通過CSS文件不變。

引用自:https://serverfault.com/questions/840115