轉: Apache SSI詳解及應用

轉: Apache SSI詳解及應用

什麼是 SSI?

SSI(Server Side Includes),是嵌套在 HTML 網頁中的指示語句,由後臺服務器進行代碼的解釋計算。使用 SSI 能夠動態的建立一部分網頁內容而不須要編寫複雜的 JSP/ASP/PHP 等程序。SSI 是如此的小巧以致於不該算做一門語言,由於他遠沒有JSP/ASP/PHP 等程序那麼複雜,只有一些極其有限的語法規則。javascript

不少 HTTP Server 程序都支持 SSI,可能語法稍有不一樣,好比: IIS/Novell HTTP Server 等等,大同小異,本文要說明的是 Apache 2.0 的 SSI。閒話少說,我想告訴你們的是,這是一篇實踐經驗總結性的文章,後文中的示例解決方案都是來自實際的網站應用中。php

開啓SSI功能需先對apache配置文件(httpd.conf)進行設置 詳情請百度

<Directory "D:/myProject/web">
AddType text/html .ssi    #這裏能夠是 .shtml 或其餘 不必定要 .ssi, 設置.ssi後綴的也是text/html類型的文件
Options Includes
AddOutputFilterByType INCLUDES; DEFLATE text/html  #輸出處理器
</Directory>

測試SSI是否成功啓用 編輯文件html

//  test.ssi :
# echo指令輸出變量 DATE_LOCAL
<!--#echo var="DATE_LOCAL" -->
## 特別注意 <!--# 之間不能有任何空格,否則指令是無效的,被看成html註釋

由於不少IDE都有註釋代碼行的快捷鍵, 如 sublime text( ctrl + /) 可是會變成 <!-- #echo var="..." -->,因爲多了個空格,因此ssi指令被當成註釋了。 java

瀏覽器訪問 http://localhost/test.ssi 能看到打印當前時間 說明SSI已啓用web


關於SSI的更多參考資料

這些文檔也能夠在 Apache的安裝文件夾找到:
Apache Tutorial: Introduction to Server Side Includes
Apache mod_include正則表達式

SSI語法:

<!--#fn attribute=value attribute=value ... --> fn能夠理解成函數或者指令。 例子:express

#環境變量習慣大寫
http://<!--#echo var="SERVER_NAME" var="DOCUMENT_URI"-->  

#virtual的值能夠是相對路徑或絕對路徑 如 virtual="/ssi/footer.ssi" 
<!--#include virtual="ssi/footer.ssi" --> 

#file的值只能是相對路徑
<!--#include file="footer.ssi" --> 

#設置自定義變量
<!--#set var="protocol" value="http" -->

SSI 語句是直接嵌套在 HTML 頁面中的,能夠放置在任意的位置。因此 SSI 語句先後採用 HTML 註釋的寫法,這樣一旦服務器關閉了對 SSI 的支持,此時訪問頁面的話,也不會直接在網頁上顯示出沒必要要的代碼。apache

SSI不區分大小寫,環境變量用大寫是很好的習慣;
SSI中只有一種數據類型:字符串;
SSI中的轉義符是  ,字符串能夠用雙引號或單引號包裹 ,同JS瀏覽器

SSI 中的變量分爲自定義變量和環境變量**

自定義變量使用 set 命令來建立:<!--#set var="protocol" value="http" -->
環境變量是系統已經存在的一些默認的變量和變量值,能夠直接使用。 <!--#echo var=」DATE_LOCAL」 -->
DATE_LOCAL 就是一個環境變量,用來顯示當前本地時間。相似的環境變量還有不少,好比經常使用HTTP_HOST、SERVER_NAME、DOCUMENT_URI、DOCUMENT_NAME 等等。安全

# 查看全部環境變量
# 因爲無換行因此按ctrl+u,以網頁源代碼的方式查看更清晰點
<!--#printenv--> 

# ------- 應用示例: --------------
<body>
    <!--#include virtual="/bnn/ssi/header.ssi"-->
    <div id="Main">
        <div id="Content">
            <p>This is "<a href="http://<!--#echo var='SERVER_NAME' -->">Learning Apache SSI</a>" testing page!</p>
            <p>Hello SSI</p>
            <p>Today is: <!--#echo var="DATE_LOCAL" --></p>
        </div>
    </div>
    <!--#include virtual="ssi/footer.ssi"-->
    </body>

數據類型:SSI 中只有一種數據類型「字符串」。例如:

<!--#set var=」MyFirstVar」 value=」120」 -->
<!--#set var=」MySecondVar」 value=」20」 -->
# $MyFirstVar < $MySecondVar  //由於2個變量都是字符串值 因此執行的是字符串比較(比較每一個字符的ASCII碼大小)

SSI經常使用指令

SSI 的元素並很少,下面列出經常使用的元素和屬性,其它請查看官方參考。

echo :將變量值寫入 HTML 代碼中。

#能夠一次輸出多個變量值 
<!--#echo var="DATE_LOCAL"--> 
http://<!--#echo var=」SERVER_NAME」 var=」DOCUMENT_URI」 -->

include :在語句所在位置引入子頁面。

include 是 SSI 中最經常使用的命令,也是 SSI 主要功能的體現。

# virtual的值能夠是相對路徑或絕對路徑, 但注意路徑中不能包含主機名;
#路徑能夠是相對當前文件(SSI 語句所在的頁面)或者從「/」開始,相對網站根目錄的路徑;
<!--#include virtual="ssi/header.ssi"--> 
# 路徑後容許加參數
<!--#include virtual="/cgi-bin/ap/optin_cn.pl?btn=send&fax=yes" -->

SSI 是容許嵌套的;例如,假設有三個文件,file1 include file2,file2中 include file3。

set :建立變量或修改變量值

<!--#set var=」Protocol」 value=」http」 -->
# 若變量值帶引號,能夠這樣:
<!--#set var="MyVar1" value='"IBM"' -->  //value的值能夠是字符串常量或者變量 如:value="$MyVar2" 
<!--#set var="MyVar2" value="\"IBM\"" -->

SSI中的變量都帶$前綴 如:$Myvar,爲了更清晰的表達一個變量 一般用大括號把變量名包起來 ${MyVar} , 同php

<!--#set var="MyVar1" value="IBM" -->
<!--#set var="MyVar2" value="Services" -->
<!--#set var="MyVar3" value="${MyVar1}${MyVar2}" -->  //設置 MyVar3 = MyVar1+MyVar2
<!--#echo var="MyVar3" -->

<!--#set var="MyVar3" value="abc${MyVar1}_${MyVar1}def" --> // 修改MyVar3的值
<!--#echo var="MyVar3" -->

<!--#set var=」MyVar1」 value=」IBM」 -->
<!--#set var=」MyVar2」 value=」\$MyVar1」 --> // 變量值爲 "$IBM"

# 另外一個把變量寫在 SSI 語句中的例子:
<!--#include virtual="/servers/eserver/${cc}/ssi/nav_left.ssi" -->  // 這個比較有用。

fsize 和flastmod

顯示指定文件的大小(fsize)和指定文件的最後修改時間(flastmod)

virtual – 與元素 include 中的屬性相同,<!--#fsize virtual=」/cgi-bin/cmail.pl」 --> 結果返回的是這個 Perl 腳本文件的大小,而不是運行這段 Perl 腳本的結果。

SSI 配置元素

  • config指令
    配置一些 SSI 運行結果;錯誤信息、文件大小格式、時間格式。
    errmsg屬性 當 SSI 語句運行出錯時顯示的信息。 例如:<!--#config errmsg="出錯啦# " -->
    sizefmt 顯示以何種方式顯示文件大小。這個屬性有兩個值:bytes 和 abbrev。

    <!--#config sizefmt="bytes" -->  //按bytes大小顯示
      <!--#config sizefmt="abbrev" --> //按bytes、Kb或Mb動態顯示 視文件大小

    timefmt 顯示時間的格式。屬性值的參數同 C 標準庫中的strftime(3) 相同;

    <!--#config timefmt="%Y-%m-%d"-->
      <!--#config timefmt="%Y-%m-%d"-->
      <meta name="DC.DATE" scheme="iso8610" content="<!--#echo var=’LAST_MODIFIED’-->">

流控制元素

條件語句

SSI 中只有條件語句一種結構,並且結構很簡單。基本的控制元素:

<!--#if expr="test_condition"-->
    html or SSI statements
<!--#elif expr="test_condition"-->
    html or SSI statements
<!--#else-->
    html or SSI statements
<!--#endif-->
## if 語句能夠嵌套,你能夠在 if 塊中再加入一個 if 塊語句。

非空字符串爲真,空串爲假

<!--#if expr="IBM" -->  // 表示條件成立;
<!--#if expr="" -->  //空字符,返回 假,條件不成立。

判斷一個變量是否爲空字符串的一種寫法:<!--#if expr="$MyVar = ‘’" -->

比較運算符 = != < <= > >=

<!--#if expr="$DOCUMENT_URI = ‘/bnn/index.html’" -->
codes
<!--#endif -->

邏輯運算符 ! && || 同JS

運算符優先級 比較運算符優先級高於邏輯運算符 ; && 和 || 具備相同的優先級,可使用括號 () 進行分組。

<!--#if expr="$a = test1 && $b = test2" -->
<!--#if expr="($a = test1) && ($b = test2)" -->

任何不被識別爲變量或者操做符都被看成是一個字符串。字符串也可使用引號(單引號或者雙引號)括起來。不被引號括起來的字符串中不容許有空格或者 Tab,由於空格是被用來起到分隔的做用。若是一個字符串中包含空格,請使用引號括起來。

<!--#if expr="$a = test1 && $b = ‘test 2’" -->

正則表達式

Regular expression (正則表達式,縮寫 RE),是一種對字符串進行匹配查找的高效模式。幾乎每一種語言都支持 RE;Apache SSI 中的 RE 語法同 Perl(版本 5)語言中的相同,但並不完整的支持

<!--#if expr="$QUERY_STRING = /^sid=([a-zA-Z0-9]+)/" -->
    <!--#set var="session" value="$1" -->
<!--#endif -->

說明:此例表示從參數中提取子字符串。$QUERY_STRING 是環境變量,表示經過網頁 URL 傳遞過來的參數,例如:
http://www.IBM.com/index.html?sid=safsaf43513sadfz&cntry=cn 其中,問號後面的部分就是 $QUERY_STRING 的值。

若是等號右邊的比較部分是 / / 這種形式,則表示,這部分是正則表達式

/^sid=([a-zA-Z0-9]+)/ 括號表示分組,用圓括號分組的同時,程序自動會將圓括號內匹配的部分提取出來保存在 $1 這個變量中;這個 $1 是系統變量,用來保存正則表達式分組提取出來的各個部分值,一共有 9個,$1-$9。

SSI 與 JavaScript

SSI 與 JS 如何一塊兒使用呢?是這樣的,因爲服務器並不能識別 JS 代碼,因此能夠把 SSI 語句放到 JS 代碼行中,這樣取代一部分 JS 代碼的工做,將這部分工做放到服務器端運行。

<!--#if expr="$DOCUMENT_URI = /\/bnn\//" -->  //正則匹配 形如:/bnn/ 的路徑,而後設置變量 SSI變量在JS中輸出
    <!--#set var="LASLink" value="http://localhost/bnn/" -->
    <!--#set var="LASText" value="Learning Apache SSI" -->
<!--#endif -->

<script type="text/javascript">
//<![CDATA[
    document.write(‘<a class="fbox" href="<!--#echo var="LASLink" -->"><!--#echo var="LASText" --></a>’);
//]]>
</script>

SSI 與 日期

前幾天遇到這樣一個需求:一個 Promotion - 3月3日以前顯示默認的內容,3月3日以後顯示另一個內容。下面給出這段代碼,分享一下相似這種的要求該如何入手。

<!--#config timefmt="%Y-%m-%d"--> # 配置日期格式
<!--#if expr="$DATE_LOCAL = /(.+)-(.+)-(.+)/" --> # 流程控制語句實現邏輯 正則匹配當前本地日期 捕獲年月日
    <!--#if expr="($2 = '03') && ($3 != /0[1-3]/)" --> # 嵌套的if 正則跟字符串比較?
        3月3日以後
    <!--#else -->
        默認
    <!--#endif -->
<!--#endif -->

SSI與頁面佈局

頁面佈局中一些相對固定的模塊,能夠經過include的方式包含到頁面中。
一般狀況下,上面有 4個區域是不常常變更的:Header、Left Nav、Nav Trail 和 Footer。

<body>
<!--#include virtual="ssi/header.ssi"--> # 把頭部模塊包含進來
    <div id="Main">
        <div id="LeftNav"><!--#include virtual="ssi/nav_left.ssi"--></div> # 左側導航模塊包含進來
        <div id="RightNav"><!--#include virtual="ssi/nav_right.ssi"--></div> # ~右側導航模塊include進來
        <div id="Content">
            <div id="NavTrail"><!--#include virtual="ssi/nav_trail.ssi"--></div> # 麪包屑模塊include進來
        <p>Hello SSI</p>
        </div>
    </div>
    <!--#include virtual="ssi/footer.ssi"--> # 頁腳模塊include進來
</body>


<!--#set var="protocol" value="" --> # 設置變量protocol初始值 
<!--#if expr="$HTTPS != /ON/" --> # 若環境變量$HTTPS 開啓,則設置變量protocol的值
    <!--#set var="protocol" value="http://${SERVER_NAME}" -->
<!--#endif -->
<!--#set var="protocols" value="https://${SERVER_NAME}" --> # 設置變量 變量名比較長的話用大括號包起來比較清晰,易於解析。

# 根據請求的路徑 高亮顯示相應的欄目連接
<ul>
    <li class="TopLink">
        <a class="left-nav-overview" href="<!--#echo var='protocol' -->/ ">IBM</a>
    </li>
    <li class="PrimaryLink<!--#if expr='$DOCUMENT_URI = /\/systems\/cn\//' -->-Highlight<!--#endif -->">
        <a class="left-nav" href="<!--#echo var='protocol' -->/systems/cn/">Systems</a>
    </li>
    <li class="PrimaryLink<!--#if expr='$DOCUMENT_URI = /\/contact\/index.html/' -->-Highlight<!--#endif -->">
        <a class="left-nav" href="<!--#echo var='protocols' -->/contact/index.html">聯繫咱們</a>
    </li>
</ul>

Nav Trail 又叫作 Breadcrumb,中文裏咱們叫作「當前位置」。在頁面上,根據當前頁面所在不一樣,在這個地方會有提示訪問者當前所在的位置。若是在每一個頁面都存在這個提示的話,編輯起來會很麻煩。但如今可使用 SSI 解決這個問題,只要在每一個頁面的這個位置 include 一個 SSI 文件就能夠了,當前所在位置的工做交給 SSI 來完成。

<!--#set var="protocol" value="" --> # 設置變量protocol初始值
<!--#if expr="$HTTPS != /ON/" --> # 若url是 https:// 安全訪問模式
    <!--#set var="protocol" value="http://${SERVER_NAME}" --> # 設置變量 protocol的值
<!--#endif -->
<!--#set var="protocols" value="https://${SERVER_NAME}" --> 

# 設置一系列變量值 當前位置的連接和文本
<!--#set var="NavTrailLink1" value="" -->
<!--#set var="NavTrailLinkName1" value="" -->

<!--#set var="NavTrailLink2" value="" -->
<!--#set var="NavTrailLinkName2" value="" -->

<!--#set var="NavTrailLink3" value="" -->
<!--#set var="NavTrailLinkName3" value="" -->

#  設置值時是多重if嵌套
<!--#if expr="$DOCUMENT_URI = /\/bnn\// && $DOCUMENT_URI != /\/bnn\/index.html/" --> # 如果訪問/bnn/下非index.html頁面
    <!--#set var="NavTrailLink1" value="${protocol}/bnn/" --> # 設置一級文本和連接變量值
    <!--#set var="NavTrailLinkName1" value="BNN" -->

    <!--#if expr="$DOCUMENT_URI = /\/bnn\/books\// && $DOCUMENT_URI != /\/bnn\/books\/index.html/" --> # 如果訪問/bnn/books/下非index.html頁面
        <!--#set var="NavTrailLink2" value="${protocol}/bnn/books/" --> # 設置二級文本和連接變量值 如此類推
        <!--#set var="NavTrailLinkName2" value="圖書館" -->

    <!--#elif expr="$DOCUMENT_URI = /\/bnn\/food\// && $DOCUMENT_URI != /\/bnn\/food\/index.html/" -->
        <!--#set var="NavTrailLink2" value="${protocol}/bnn/food/" -->
        <!--#set var="NavTrailLinkName2" value="好吃的" -->

        <!--#if expr="$DOCUMENT_URI = /\/bnn\/food\/strawberry\// && $DOCUMENT_URI != /\/bnn\/food\/strawberry\/index.html/" -->
            <!--#set var="NavTrailLink3" value="${protocol}/bnn/food/strawberry/" -->
            <!--#set var="NavTrailLinkName3" value="草莓" -->
        <!--#endif -->

    <!--#endif -->
<!--#endif -->

# 輸出當前位置時也是多重if嵌套
<img alt="" class="display-img" height="6" src="//www.ibm.com/i/c.gif" width="1" />
<!--#if expr="$NavTrailLink1" -->
    <a class="bctl" href="<!--#echo var='NavTrailLink1' -->"><!--#echo var="NavTrailLinkName1" --></a><span class="bct">&nbsp;&gt;&nbsp;</span>
    <!--#if expr="$NavTrailLink2" -->
        <a class="bctl" href="<!--#echo var='NavTrailLink2' -->"><!--#echo var="NavTrailLinkName2" --></a><span class="bct">&nbsp;&gt;&nbsp;</span>
        <!--#if expr="$NavTrailLink3" -->
            <a class="bctl" href="<!--#echo var='NavTrailLink3' -->"><!--#echo var="NavTrailLinkName3" --></a><span class="bct">&nbsp;&gt;&nbsp;</span>
        <!--#endif -->
    <!--#endif -->
<!--#endif -->

SSI指令小結

語法: <!--#directive [parm=value] --> ,指令包括:

  • config:設置日期格式等,如:(<!--#config timefmt="%B %Y" -->)
  • echo:打印變量值 (<!--#echo var="VARIABLE_NAEM" -->)
  • exec:用來執行服務器端的命令
  • include:文件包含 (<!--#include virtual="file-name" -->)
  • flastmod:輸出指定文件最後修改時間(<!--#flastmod file="filename.shtml" -->)
  • fsize:輸出指定文件的大小(<!--#fzie file="filename.shtml" -->)
  • printenv:打印全部環境變量(<!--#printenv -->)
  • set:設置或修改變量 (<!--#set var="foo" value="Bar" -->)
  • if elif endif else:建立條件分支
相關文章
相關標籤/搜索