將 htaccess 重寫規則轉換為 Apache2 虛擬主機規則
我試圖
RewriteRule
通過結合.htaccess
我之前成功實施的一些規則來設置萬用字元子域,相信我可以對我的 Apache vhosts 文件使用相同的規則。本質上,
example.com
並www.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文件不變。