Apache服務器端包含文件入門
2024-08-27 18:22:40
供稿:網友
服務器端包含提供了一種對現有HTML文檔增加動態內容的方法。
概要
相關模塊 相關指令
mod_include
mod_cgi
mod_expires
Options
XBitHack
AddType
SetOutputFilter
BrowserMatchNoCase
本文針對服務器端包含(Server Side Includes),通常簡稱為SSI,討論如何配置服務器以允許SSI,并介紹一些對現有HTML頁面增加動態內容的基本SSI技術。
本文后部將討論用SSI做一些應該算比較高級的事情,比如SSI指令中的條件語句。
什么是SSI?
SSI (Server Side Includes)是HTML頁面中的指令,在頁面被提供時由服務器進行運算,以對現有HTML頁面增加動態生成的內容,而無須通過CGI程序提供其整個頁面,或者使用其他動態技術。
對什么時候用SSI,而什么時候用某些程序生成整個頁面的權衡,取決于頁面中有多少內容是靜態,有多少內容需要在每次頁面被提供時重新計算。SSI是一種增加小段信息的好方法,諸如當前時間。如果你的頁面大部分是在被提供時生成的,那就要另找方案了。
配置服務器以允許SSI
要使服務器允許SSI,必須在httpd.conf文件或.htaccess文件中有如下配置:
Options +Includes
告訴服務器以允許解析文件中的SSI指令。注意,在多數配置中,多個Options指令會互相覆蓋,所以,可能必須對需要SSI的特定目錄使用Options,以確保位于最后并起作用。
并不是所有文件中的SSI指令都會被解析,所以,必須告訴Apache應該解析哪些文件。有兩種方法,使Apache解析帶有特定文件后綴的任何文件,比如.shtml, 配置如下:
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
這種方法的缺點之一是,為了使文件名有.shtml后綴從而執行其中的指令,可能需要改變加入SSI指令的現有的文件,以及所有指向此頁面的連接。
另一種方法是,使用XBitHack指令:
XBitHack on
XBitHack告訴Apache解析有執行權限的文件中的SSI指令。如此,只要用chmod使文件變成可執行的,就可以對現有的頁面增加SSI指令。
chmod +x pagename.html
這里簡要說明一點:偶然會有人向你推薦,無須用帶.shtml的文件名,使Apache解析所有.html文件的SSI就可以了。那些人可能沒聽說過XBitHack。要知道,這樣做會使Apache在發送文件到客戶端之前通讀此文件,即使其中并沒有任何SSI指令,從而對速度有不小影響,所以這并不是好辦法。
當然,在Windows上,沒有對應的執行權限可以設置,但還是應該謹慎選擇。
按缺省配置,Apache不會為SSI頁面發送最后修改日期或者內容長度的HTTP頭,因為這些值對動態頁面來說難以計算。這樣會阻止頁面被緩沖,導致客戶端性能有能夠感覺到的下降。有兩種解決方法:
使用XBitHack Full配置。它告訴Apache判斷最后修改日期時,只查看被請求的文件本身的日期,而忽略其中包含的任何文件的修改日期。
使用mod_expires提供的指令為文件設置一個明確的過期時間,并告訴瀏覽器和代理這個文件可以被緩沖。
基本SSI指令
SSI指令有如下語法:
<!--#element attribute=value attribute=value ... -->
其格式很象HTML的注釋,因此如果沒有正確配置SSI,它會被瀏覽器忽略,但在HTML代碼中仍然可見。而如果正確配置了SSI,則此指令會被其結果替代。
其中的元素可以有許多,我們會在下一個版本的文檔中討論其中的大多數,而在這里,僅舉幾個SSI的例子。
今天的日期
<!--#echo var="DATE_LOCAL" -->
echo元素僅僅是反饋一個變量的值。標準變量有許多,其中包含對CGI程序有效的所有的環境變量。另外,你也可以用set元素定義你的專用變量。
如果你不喜歡日期的這種打印格式,可以用config元素的timefmt屬性,改變其格式。
<!--#config timefmt="%A %B %d, %Y" -->
Today is <!--#echo var="DATE_LOCAL" -->
文件的修改日期
This document last modified <!--#flastmod file="index.html" -->
這個元素也是使用timefmt的格式配置。
包含一個CGI程序的輸出
這是SSI的很常見的一個用途-包含一個CGI程序的輸出,比如人人喜歡的``點擊計數器''。
<!--#include virtual="/cgi-bin/counter.pl" -->
附加的例子
以下是一些對HTML文檔使用SSI的特殊例子。
文檔是什么時候被修改的?
此前,我們提到過可以用SSI通知用戶文檔是什么時候被修改的,但是其具體實施方法卻基本上是個問題。以下代碼,放在HTML文檔中,會在頁面中產生一個時間戳,當然,首先,你必須按上述方法使SSI有效。
<!--#config timefmt="%A %B %d, %Y" -->
This file last modified <!--#flastmod file="ssi.shtml" -->
不用說,你應該用你實際引用的文件名來替換ssi.shtml,所以,如果你想簡單地在任何文件中粘貼一段通用代碼以達到這個目的,這個方法就并不方便,如此,就會用到LAST_MODIFIED變量:
<!--#config timefmt="%D" -->
This file last modified <!--#echo var="LAST_MODIFIED" -->
有關timefmt格式的細節,可以到搜索站點查找strftime,其語法是相同的。
包含一個標準注腳
如果你管理一個擁有許多頁面的站點,你會發現對所有頁面做改動是很痛苦的,尤其是在試圖對所有頁面維持某種標準觀感的時候。
使用包含一個頁眉和/或注腳的方法,可以減輕修改的負擔。你只要制作一個注腳文件,并用includeSSI命令包含到每個頁面,即可。include元素能按file屬性或者virtual屬性判斷應該包含的文件。file屬性是一個相對于當前目錄的文件路徑,即不能是一個絕對文件路徑(以/開頭)。virtual屬性可能更有用,它是一個相對于被提供文檔的URL,可以以/開頭,但必須與被提供文檔在同一個服務器。
<!--#include virtual="/footer.html" -->
SSI指令和注腳文件相結合使用是很有用的,比如在注腳文件中使用LAST_MODIFIED指令。SSI指令可以出現在包含文件中,而include可以嵌套,即一個包含文件可以包含另一個。
其他的設置
config除了能設置時間格式,還有兩種用途。
當SSI指令發生錯誤時,會產生如下消息:
[an error occurred while processing this directive]
為了改變消息的形式,可以使用config元素的errmsg屬性:
<!--#config errmsg="[It appears that you don't know how to use SSI]" -->
當然,最終用戶永遠也不會看到這個消息,因為在網站投入運行之前你已經把這些問題都解決了(是嗎?)。
還可以使用config的sizefmt屬性設置返回的文件大小的格式,或者是以字節為單位,或者是以Kb或Mb為單位的簡寫。
執行命令
我期望未來幾個月內能再寫一篇小型CGI程序使用SSI的文章,而這里,僅介紹exec的使用。SSI確實可以利用shell(/bin/sh,精確地說,還可以是Win32中的DOS shell)來執行命令。下例產生一個目錄列表:
<pre>
<!--#exec cmd="ls" -->
</pre>
在Windows中:
<pre>
<!--#exec cmd="dir" -->
</pre>
你可能會發現,在Windows中這個指令的結果有些奇怪,dir的輸出中包含有字串``<dir>'',它會使瀏覽器產生混淆。
注意,這個功能是極度危險的,因為它會執行任何包含在exec標記中的命令。如果用戶有可能修改你的網頁內容,比如“留言本”,那么你一定要關閉這個功能。在Options指令中加上IncludesNOEXEC參數,以關閉exec功能,同時又保留SSI。
高級SSI技術
除了分離內容,Apache SSI還可以設置用以比較和條件表達式的變量。
警告
本文中討論的大多數功能僅在Apache 1.2及更新版本中有效。如果你運行的不是Apache 1.2及更新版本,請立刻或者盡快升級,現在就動手,我們會等你弄好了再繼續往下講。
設置變量
使用set指令可以設置變量以備后用,其語法是:
<!--#set var="name" value="Rich" -->
除了設置文字變量以外,還可以設置其他任何變量,比如環境變量和此前提到過的一些變量(如LAST_MODIFIED),作為你的專用變量。在變量名前面綴以$,表示它是一個變量,而不是一個文字性字串。
<!--#set var="modified" value="$LAST_MODIFIED" -->
在文字性字串中使用$,必須使用轉義符號
<!--#set var="cost" value="$100" -->
最后,如果要在較長的字符串中使用變量,可以用花括號把變量名括起來,以免變量名與其他字符之間沖突而產生混淆(要對這種情況舉例說明有點難度,但還是希望你能領會)。
<!--#set var="date" value="${DATE_LOCAL}_${DATE_GMT}" -->
條件表達式
有了變量,就可以設置和比較它們的值以表示條件,SSI也因此成為一種簡潔的編程語言。mod_include提供了if, elif, else和endif等結構以構造條件語句,從而對一個實在的頁面高效地生成多個邏輯的頁面。
條件的結構如下:
<!--#if expr="test_condition" -->
<!--#elif expr="test_condition" -->
<!--#else -->
<!--#endif -->
test_condition可以是任何邏輯比較 - 可以是一個值和另一個值比較,也可以是測試一個特定的值是否為“真”(一個給定的字串如果非空則為真)。完整的比較操作符列表,見mod_include。以下是可能會用到的一些例子。
在配置文件中,可以這樣設置:
BrowserMatchNoCase macintosh Mac
BrowserMatchNoCase MSIE InternetExplorer
如果客戶端在Macintosh上運行Internet Explorer,則上例設置環境變量``Mac'' 和``InternetExplorer''為真。
然后,在允許SSI的文檔中,可以這樣設置:
<!--#if expr="${Mac} && ${InternetExplorer}" -->
Apologetic text goes here
<!--#else -->
Cool javascript code goes here
<!--#endif -->
我一點也不反對在Mac上運行IE - 只是上個星期我花了好幾個小時試圖在Mac上的IE中使用javascript,而它在其他地方都能正常運作,以上只是一個臨時的妥協方案。
任何其他變量(或者是你定義的,或者是標準的環境變量)都可以用于條件語句。利用Apache的SetEnvIf以及其他相關指令設置環境變量,此功能可以很好地實現動態頁面而無須借助于CGI。
總結
SSI固然不能替代CGI或者其他動態頁面技術,但它是在頁面中插入眾多小型的動態片段的優秀方法,而無須大量額外的操作。