节选自《Apache源代码解析-基于Apache0.6.5》第七章。
7.1概述
现在的Apache本身除了提供静态页面服务之外,还可以通过加载第三方扩展模块方式支持php、jsp等脚本语言,提供动态页面效果。您也许不知道,其实即便不使用这些脚本语言,Apache也支持在您的页面里面加入动态内容。
所谓的动态,就是在不同条件下显示不同的内容,比如当前时间的显示就属于动态内容显示。Apache0.6.5对动态内容支持包括两部分,一部分是本章描述的SSI,另一部分是将要在下一章描述的cgi脚本。
SSI全称是Server Side Include,即服务器端包含。SSI允许在静态文件中显示一些系统变量甚至执行shell命令或cgi脚本。
服务器包含部分的功能在http_include.c中实现。
7.2 背景知识
7.2.1字符实体
如果您做过页面或者对HTML比较熟悉,一定对字符实体这个概念不陌生。
我们在做页面的时候,有时候会遇到这样的情况:我想在某个位置加入几个连续的空格,如果我在源代码里面输入空格,不论输入多少个,在页面显示的时候都是显示一个空格,因为HTML会自动截去多余的空格。不管你加多少空格,都被看做一个空格。
这时候我们一般的做法是用 来代替空格,也许您觉得 不够专业,明眼人一看就知道是空格,那好,我们还有一个替代方 案,使用 来代替空格。在源代码中连续输入几个 序列或 序列,用浏览器打开,是不是显示出几个 空格呢?
这个 或 就是HTML字符实体(HTML Character Entities)。
一个字符实体分成三部分:第一部分是一个&符号;第二部分是实体(Entity)名字或者是#加上实体(Entity)编号;第三部分是一个分号。
用实体名字的好处是比较好理解,一看 ,大概就猜出是none-break space的意思,但是其劣势在于并不是所有的浏览器都支持最新的Entity名字。而实体(Entity)编号,各种浏览器都能处理。
注意:Entity是区分大小写的。
最常用的字符实体
显示结果 | 说明 | Entity Name | Entity Number |
| 显示一个空格 | |   |
< | 小于 | < | < |
> | 大于 | > | > |
& | &符号 | & | & |
其他常用的字符实体
更多HTMLver4的字符实体定义参看:http://www.w3.org/TR/html4/sgml/entities.html
7.2.2环境变量
做Java开发的人一定对环境变量这个概念不陌生,相信每个Java程序员在成功输出Hello World之前都对环境变量进行了一些或艰苦或顺利的设置。
其实每个程序运行的时候都使用了环境变量,只是你没有察觉而已。
我们知道,如果想在Linux下执行一个可执行文件,一般需要给出这个可执行文件的绝对或相对位置,比如我们启动Apache的时候,就需要类似下面这样的方式:
[devel@RIZI src]$ pwd
/home/devel/apache_0.6.5/src
[devel@RIZI src]$ httpd
[devel@RIZI src]$
如果我们在/home/devel/apache_0.6.5/src目录外的任何位置执行下面的指令,是不能启动Apache的:
[devel@RIZI ~]$ pwd
/home/devel
[devel@RIZI ~]$ httpd
-bash: httpd: command not found
[devel@RIZI ~]$
这时因为系统“没找到”httpd这个可执行文件。那么系统都会在哪里“找”呢?答案是系统变量PATH中。
Bash(或任何您当前在使用的shell)根据您输入的命令在PATH系统变量指定的位置找对应的可执行文件,如果找到了,就根据您的输入参数执行这个程序,如果没找到,就会给出“命令没找到”提示。
系统常用命令都在PATH系统变量指定的目录中,这也是我们可以在任何目录执行系统命令如ls的原因。
我们可以通过env命令来查看当前登录用户的系统变量:
[devel@RIZI ~]$ env
SHELL=/bin/bash
HISTSIZE=1000
…… ……
PATH=/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/devel/bin
…… ……
OLDPWD=/home/devel/apache_0.6.5
[devel@RIZI ~]$
而ls命令的位置一般在/bin目录下:
[devel@RIZI ~]$ which ls
/bin/ls
[devel@RIZI ~]$
Apache维护一个自定义的环境变量数据结构供SSI使用。
7.3配置Apache支持SSI
如果您要使用SSI,需要修改两个配置文件:srm.conf和access.conf
7.3.1 配置方法
1.在srm.conf中找到这样的行:
#AddType text/x-server-parsed-html .shtml
如果没有,增加这样一行,并去掉前面的注释(#)。
AddType的含义请参看
2.在access.conf中找到您要使用SSI的目录,如您的站点根目录
<Directory /home/devel/apache-0.6.5//htdocs>
Options Indexes FollowSymLinks
</Directory>
在Opetion后面增加Includes选项。
7.3.2 配置指令解析
1.AddType 指令
语法:AddType
MIME-type extension [
extension ] ...
功能:
在给定的文件扩展名与特定的内容类型间建立映射
示例:
AddType text/x-server-parsed-html .shtml
上例说明,.shtml为扩展名的文件是text/x-server-parsed-html类型的文件
2.Option 指令
语法:Options
可选项 [
可选项 ] ...
功能:配置在特定目录使用哪些特性
示例:Options Indexes FollowSymLinks
上例说明,可以在指定的目录下列表文件,可以使用符号链接。具体参数及含义如下:
Indexes:如果服务器收到了一个映射到该目录的URL请求,而目录下又没有DirectoryIndex(如index.html),那么服务器返回一个格式化目录列表。
Includes:允许服务器端包含
IncludesNOEXEC:允许服务器端包含,但禁用#exec命令和#exec CGI
FollowSymLinks:服务器会在此目录中使用符号连接
SymLinksIfOwnerMatch:符号连接仅当与它的目的文件或目录具有相同的用户ID时才使用。简单理解就是符号链接的所有者和它指向的文件或目录是同一个人
execCGI:允许执行CGI脚本
MultiViews:这是一个被诟病的功能。允许你访问页面时不需要文件的扩展名。比如,你有一个叫"uation.txt"的文件,在启用 MultiViews的站点,你可以用"example.com/uation"来访问到这个文件,该指令在我们要讲解的版本中不予支持
None:都不允许
All:除MultiViews之外的所有特性
7.4 SSI命令解说
SSI命令是嵌入在正常的HTML源代码中的。
SSI在使用时遵循以下格式:
<!--#directive parameter="value"-->
其中,directive是向服务器发送的指令名称,parameter是指令的操作对象,而value则是用户希望得到的指令处理结果。
所有的SSI命令都是以"<!--#"开始,其中"<!-"和"#"之间不能有任何空格,否则服务器会把SSI命令当称普通的文件注释处理, 不会显示出任何结果,也不会产生错误提示。此外,SSI命令中的"="两边不能有空格,右边的值必须包含在双引号内,后面可以跟空格,最后是结束标 签"-->"。
Apache0.6.5支持6种类型的SSI命令,如下所示:
Config errmsg, timefmt, sizefmt
include virtual, file
echo var
fsize file
flastmod file
exec cmd, cgi
下面我们根据实例,一一解说。
7.4.1 config命令
Config命令主要用于修改SSI的默认设置。主要有一个内容设置和两个格式设置:
1. errmsg
内容设置,设置错误信息的内容,在里面你可以加上自己的邮件地址之类的个人自定义信息。如:
<!--#config errmsg="Error! Please email webmaster@mydomain.com -->
2. timefmt
格式设置,可以重新设置SSI输出时间的格式,需要在显示某个时间前面设置,如:
<!--#config timefmt="%A, %B %d, %Y"-->
<!--#echo var="LAST_MODIFIED" -->
显示结果为:
Thursday, March 26, 2009
具体的时间格式参看附录。
3. sizefmt
格式设置,可以定义文件的大小以什么为单位显示。是以字节、千字节还是兆字节为单位表示。如果以字节为单位,参数值为"bytes";对于千字节和兆字节可以使用缩写形式。同样,sizefmt参数必须放在fsize命令的前面才能使用。
<!--#config sizefmt="bytes" -->
<!--#fsize file="index.html" -->
7.4.2 include命令
有时候我们在所有的页面里面会引用一些内容,比如会有几个固定链接,如“版权信息 | 关于我们 | 友情链接”等。如果我们在每个页面里面都直接插入这样的信息,一旦有相关信息的变动,如关于我们页面的地址从/include/aboutus.html 改到了/res/aboutus.html,我们就需要修改每个页面。这样的工作是繁杂且容易出错的。这时候我们可以使用include指令来解决这个问 题。这个命令也许是SSI里面最有价值且使用频率最高的命令了
Include命令可以有两个不同的参数:
1.Virtual :给出到服务器端某个文档的虚拟路径。例如:
<!--#include virtual="/res/readme.html" -->
2.File :给出到当前目录的相对路径,其中不能使用"../",也不能使用绝对路径。例如:
<!--#include file="readme.html" -->
这就要求每一个目录中都包含一个readme.html文件。
7.4.3 echo命令
Echo命令可以显示以下各环境变量:
1.DOCUMENT_NAME
显示当前文档的名称。
<!--#echo var="DOCUMENT_NAME" -->
显示结果为:hello.shtml
2.DOCUMENT_URL
显示当前文档的虚拟路径。例如:
<!--#echo var="DOCUMENT_URI" -->
显示结果为:/hello.shtml
3.DATE_LOCAL
显示服务器设定时区的日期和时间。
<!--#echo var="DATE_LOCAL" -->
显示结果为:Thursday, 26-Mar-09 16:59:31 CST
4.DATE_GMT
功能与DATE_LOCAL一样,只不过返回的是以格林尼治标准时间为基准的日期
<!--#echo var="DATE_GMT" -->
显示结果为:Thursday, 26-Mar-09 08:59:31 GMT
5.LAST_MODIFIED
显示当前文档的最后更新时间。
<!--#echo var="LAST_MODIFIED" -->
显示结果为:Thursday, 26-Mar-09 16:57:27 CST
6.CGI环境变量
PATH:服务器PATH信息
SERVER_SOFTWARE:服务器软件版本信息
SERVER_NAME:服务器名
SERVER_PORT:服务端口号
REMOTE_HOST:客户端名称
REMOTE_ADDR:客户端地址
DOCUMENT_ROOT:站点根目录
SERVER_ADMIN:站点管理员邮件地址
REMOTE_USER:远程用户
AUTH_TYPE:认证类型
REDIRECT_QUERY_STRING:重定向参数信息
REDIRECT_URL:重定向URL
最后两项和重定向有关,REMOTE_USER和AUTH_TYPE跟认证有关。这四项只有在特定情况下才能有值。
7.4.4 fsize命令
显示指定文件的大小。如:
<!--#fsize file="hello.zip" -->
输出为:1K
可以结合config命令的sizefmt参数定制输出格式,如:
<!--#config sizefmt="bytes" -->
<!--#fsize file="hello.zip" -->
输出为:2
说明这个文件只有2字节。
7.4.5 flastmod命令
显示指定文件的最后修改日期。
<!--#flastmod file="hello.zip" -->
输出为:Friday, 20-Mar-09 16:33:12 CST
7.4.6 exec命令
exec命令可以执行CGI脚本或者shell命令。使用方法如下:
cmd:使用/bin/sh执行指定的字串。如果服务器配置Option时使用了IncludesNOEXEC选项,则该命令将被屏蔽。
cgi:可以用来执行CGI脚本。例如,下面这个例子中使用服务端cgi-bin目录下的date脚本程序显示当前时间:
<!--#exec cgi="/cgi-bin/date" -->
7.4.7 一个简单的实例
本小节我们提供一个简单的,使用SSI功能的HTML页面,来检测Apache对SSI的支持。该HTML文件的源代码如下:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SSI测试</title>
</head>
<body>
<!--#config timefmt="%A, %B %d, %Y" -->
当前本地时间是:<!--#echo var="DATE_LOCAL" -->
<br/>
本文件大小是:<!--#fsize file="ssi.shtml" -->
</body>
</html>
您可以在http://www.oldapache.org/example/chapter7/ssi.rar 下载该代码。下载后解压缩,将解压缩后得到的ssi.shtml文件放到您的htdocs目录,按照7.3节中的说明配置Apache,重新启动Apache使新配置生效。从浏览器中访问页面http://www.yourdomain.com/ssi.shtml ,在我的浏览器中得到的结果如下图所示:
7.5 代码注释
限于篇幅,注释代码部分请参看本书官网。
节选自《Apache源代码解析-基于Apache0.6.5》第七章。