Amazon-Web-Services

Apache(httpd)VirtualHost RewriteCond 變數不起作用

  • August 1, 2015

我正在嘗試創建一個動態虛擬主機條目,目的是將所有流量重定向到*.mydomain.com 到 /var/www/html/* 這部分有效,但我還有一個重寫條件來檢查目錄是否存在(如果不存在)然後我想將所有流量重定向到根目錄/var/www/html/index.php。

這部分不起作用,因為在我的測試過程中,我注意到沒有一個 Rewrite 變數正在工作,它們是空白的,我無法弄清楚為什麼這是我的虛擬主機配置

# get the server name from the Host: header
UseCanonicalName Off

# this log format can be split per-virtual-host based on the first field
# LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

<VirtualHost *:80>
   ServerName mydomain.com
   ServerAlias www.mydomain.com
   VirtualDocumentRoot /var/www/html
</VirtualHost>

<VirtualHost *:80>
   ServerName vhosts.mydomain.com
   ServerAlias *
   VirtualDocumentRoot /var/www/html/%1

   RewriteEngine on
   LogLevel warn rewrite:trace4

   # If the request is not for a valid directory
   RewriteCond /var/www/html/%1 !-d
   RewriteCond %{REQUEST_FILENAME} !-d
   # If the request is not for a valid file
   RewriteCond %{REQUEST_FILENAME} !-f
   # If the request is not for a valid link
   RewriteCond %{REQUEST_FILENAME} !-l

   RewriteRule .* /var/www/html/index.php

</VirtualHost>

您會注意到我在測試和查看我的日誌文件時可以使用該變數的多種用途

[Wed Jul 29 16:56:56.015818 2015] [rewrite:trace2] [pid 23898] mod_rewrite.c(475): [client xx.xx.xx.xx:4863] xx.xx.xx.xx - - [fake.mydomain.com/sid#7f5c89bcf570][rid#7f5c89ed5000/initial] init rewrite engine with requested uri /
[Wed Jul 29 16:56:56.016050 2015] [rewrite:trace3] [pid 23898] mod_rewrite.c(475): [client xx.xx.xx.xx:4863] xx.xx.xx.xx - - [fake.mydomain.com/sid#7f5c89bcf570][rid#7f5c89ed5000/initial] applying pattern '.*' to uri '/'
[Wed Jul 29 16:56:56.018361 2015] [rewrite:trace4] [pid 23898] mod_rewrite.c(475): [client xx.xx.xx.xx:4863] xx.xx.xx.xx - - [fake.mydomain.com/sid#7f5c89bcf570][rid#7f5c89ed5000/initial] RewriteCond: input='/var/www/html/' pattern='!-d' => not-matched
[Wed Jul 29 16:56:56.018411 2015] [rewrite:trace1] [pid 23898] mod_rewrite.c(475): [client xx.xx.xx.xx:4863] xx.xx.xx.xx - - [fake.mydomain.com/sid#7f5c89bcf570][rid#7f5c89ed5000/initial] pass through /

即使 %1 通過虛擬目錄就好了,它在 mod 重寫規則中不起作用。變數的所有其他用途產生相同的結果,任何幫助將不勝感激。

不確定它是否有所作為,但這是在 AWS on Amazon Linux 建構中執行的。

%1 不是整個 Apache 配置的一種全域變數。

VirtualDocumentRoot中,它對應於“主機”名稱的第一部分,在RewriteCondor中,它表示對前面RewriteRule的擷取組的反向引用。有關RewriteCond,請參閱 Apache 文件 RewriteCond

扔掉那部分:

RewriteCond /var/www/html/%1 !-d

您對 %1 的使用是錯誤的,您之前沒有任何 RewriteCond,因此 %1 是空字元串。所以基本上你有一個條件說“如果/var/www/html/不是一個目錄,做……”

但顯然/var/www/html是一個目錄,這就是為什麼你的日誌行說

RewriteCond: input='/var/www/html/' pattern='!-d' => not-matched

UPADTE作為您評論的跟進:

要理解的是,Apache 由許多不同的部分組成,它們是模組。每個模組都有自己的語法。這使得整體非常強大,但可能會令人困惑,就像您的問題一樣。每個模組都可以用一個變數定義語法,該變數%1表示每個模組中的其他內容。

可能是我現在更好地理解了你想要做什麼:

  1. 檢查請求是否有與其子域對應的目錄,如果沒有,發送到/var/www/html/nosubdomain.php
  2. 否則檢查請求是否對應於文件/目錄/連結,如果不是,發送到/var/www/html/nofile.php

第 1 步:獲取子域

要獲取子域,您可以使用 mod_rewrite 的能力來定義和設置環境變數(這裡%1是 RewriteCond 中擷取的結果):

# Setting environment variable SUBDOMAIN = (subdomain).example.com

RewriteCond %{HTTP_HOST} ^([^\.]*)\.example\.com$
RewriteRule . - [E=SUBDOMAIN:%1]

第 2 步:現在您可以在 rewrite rules/cond 中使用 SUBDOMAIN 變數並檢查與子域對應的目錄是否存在。如果不是,則重定向到定義的頁面

# Test if subdomain directory exists, if not, redirect to a 
# standard page (/var/www/html/nosubdomain.php).

RewriteCond /var/www/html/%{ENV:SUBDOMAIN} !-d
RewriteRule .* /var/www/html/nosubdomain.php [L]

第 3 步:檢查請求的文件是否存在,如果不存在,則發送標準頁面 ( /var/www/html/nofile.php)。為此,最好依靠 Apache 檢查自身並使用 ErrorDocument。我們需要別名,因為您希望文件nofile.php位於 VirtualDocumentRoot ( /var/www/html/subdomain/)之外

Alias /nofile.php /var/www/html/nofile.php
ErrorDocument 404 /nofile.php

在你的指令之後將所有這些步驟放在一起RewriteEngine On應該會給你帶來一個工作設置,當然你必須適應你的確切案例。我已經測試了這個設置,它可以按我的意願工作,但是在 Apache 2.2 上。

如果您不在其他地方使用 SUBDOMAIN,您也可以將步驟 1 和 2 組合在一起:

RewriteCond %{HTTP_HOST} ^([^\.]*)\.example\.com$
RewriteCond /var/www/html/%1 !-d
RewriteRule .* /var/www/html/nosubdomain.php [L]

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