# 服务器端包含入门
服务器端包含提供了一种对现有HTML文档增加动态内容的方法。
## 简介
相关模块
* `mod_include`
* `mod_cgi`
* `mod_expires`
相关指令
* `Options`
* `XBitHack`
* `AddType`
* `SetOutputFilter`
* `BrowserMatchNoCase`
本文针对服务器端包含(SSI)讨论如何配置服务器以允许SSI ,并介绍一些对现有HTML页面增加动态内容的基本SSI技术。
本文后部将讨论用SSI做一些稍微高级的事情,比如SSI指令中的条件语句。
## 什么是SSI ?
SSI是嵌入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头,因为这些值对动态页面来说难以确定。这样会阻止页面被缓冲,导致客户端性能有明显的下降。有两种解决方法:
1. 设置 `XBitHack Full` ,告诉Apache在判断最后修改日期时,只查看被请求文件本身的日期,而忽略其中包含的其它文件的修改日期。
2. 使用`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`格式的细节,可以到[google](http://www.google.com/)查找`strftime` ,其语法是相同的。
### 包含一个标准页脚
当你管理一个拥有许多页面的站点,你会发现对所有页面同时做改动是很痛苦的,尤其是在试图对所有页面维持某种标准视觉效果的时候。
使用包含一个页眉/页脚的方法,可以减轻修改的负担。你只要制作一个页脚文件,并用`include`命令包含到每个页面即可。`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`属性设置返回的文件大小的格式,或者是以`bytes`为单位,或者是以Kb或Mb为单位的`简写(abbrev)`。
## 执行命令
我期望未来几个月内能再写一篇小型的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还有设置变量的操作,并且还可以将这些变量用在比较和条件表达式中。
### 警告
本文中讨论的大多数功能仅在Apache1.2及更新版本中有效。如果你运行的不是Apache1.2及更新版本,请立刻或者尽快升级,现在就动手,我们会等你弄好了再继续往下讲。
### 设置变量
使用`set`指令可以设置变量以备后用,其语法是:
```
<!--#set var="name" value="Rich" -->
```
除了设置字面变量以外,还可以设置其他任何变量,比如[环境变量](#calibre_link-232)和此前提到过的一些变量(如`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或者其他动态页面技术,但它是在页面中插入众多小型的动态片段的优秀方法,而无须大量额外的操作。
- Apache HTTP Server Version 2.2 文档 [最后更新:2006年3月21日]
- 版本说明
- 从1.3升级到2.0
- 从2.0升级到2.2
- Apache 2.2 新特性概述
- Apache 2.0 新特性概述
- The Apache License, Version 2.0
- 参考手册
- 编译与安装
- 启动Apache
- 停止和重启
- 配置文件
- 配置段(容器)
- 缓冲指南
- 服务器全局配置
- 日志文件
- 从URL到文件系统的映射
- 安全方面的提示
- 动态共享对象(DSO)支持
- 内容协商
- 自定义错误响应
- 地址和端口的绑定(Binding)
- 多路处理模块
- Apache的环境变量
- Apache处理器的使用
- 过滤器(Filter)
- suEXEC支持
- 性能方面的提示
- URL重写指南
- Apache虚拟主机文档
- 基于主机名的虚拟主机
- 基于IP地址的虚拟主机
- 大批量虚拟主机的动态配置
- 虚拟主机示例
- 深入研究虚拟主机的匹配
- 文件描述符限制
- 关于DNS和Apache
- 常见问题
- 经常问到的问题
- Apache的SSL/TLS加密
- SSL/TLS高强度加密:绪论
- SSL/TLS高强度加密:兼容性
- SSL/TLS高强度加密:如何...?
- SSL/TLS Strong Encryption: FAQ
- 如何.../指南
- 认证、授权、访问控制
- CGI动态页面
- 服务器端包含入门
- .htaccess文件
- 用户网站目录
- 针对特定平台的说明
- 在Microsoft Windows中使用Apache
- 在Microsoft Windows上编译Apache
- Using Apache With Novell NetWare
- Running a High-Performance Web Server on HPUX
- The Apache EBCDIC Port
- 服务器和支持程序
- httpd - Apache超文本传输协议服务器
- ab - Apache HTTP服务器性能测试工具
- apachectl - Apache HTTP服务器控制接口
- apxs - Apache 扩展工具
- configure - 配置源代码树
- dbmmanage - 管理DBM格式的用户认证文件
- htcacheclean - 清理磁盘缓冲区
- htdbm - 操作DBM密码数据库
- htdigest - 管理用于摘要认证的用户文件
- httxt2dbm - 生成RewriteMap指令使用的dbm文件
- htpasswd - 管理用于基本认证的用户文件
- logresolve - 解析Apache日志中的IP地址为主机名
- rotatelogs - 滚动Apache日志的管道日志程序
- suexec - 在执行外部程序之前切换用户
- 其他程序
- 杂项文档
- 与Apache相关的标准
- Apache模块
- 描述模块的术语
- 描述指令的术语
- Apache核心(Core)特性
- Apache MPM 公共指令
- Apache MPM beos
- Apache MPM event
- Apache MPM netware
- Apache MPM os2
- Apache MPM prefork
- Apache MPM winnt
- Apache MPM worker
- Apache模块 mod_actions
- Apache模块 mod_alias
- Apache模块 mod_asis
- Apache模块 mod_auth_basic
- Apache模块 mod_auth_digest
- Apache模块 mod_authn_alias
- Apache模块 mod_authn_anon
- Apache模块 mod_authn_dbd
- Apache模块 mod_authn_dbm
- Apache模块 mod_authn_default
- Apache模块 mod_authn_file
- Apache模块 mod_authnz_ldap
- Apache模块 mod_authz_dbm
- Apache模块 mod_authz_default
- Apache模块 mod_authz_groupfile
- Apache模块 mod_authz_host
- Apache模块 mod_authz_owner
- Apache模块 mod_authz_user
- Apache模块 mod_autoindex
- Apache模块 mod_cache
- Apache模块 mod_cern_meta
- Apache模块 mod_cgi
- Apache模块 mod_cgid
- Apache模块 mod_charset_lite
- Apache模块 mod_dav
- Apache模块 mod_dav_fs
- Apache模块 mod_dav_lock
- Apache模块 mod_dbd
- Apache模块 mod_deflate
- Apache模块 mod_dir
- Apache模块 mod_disk_cache
- Apache模块 mod_dumpio
- Apache模块 mod_echo
- Apache模块 mod_env
- Apache模块 mod_example
- Apache模块 mod_expires
- Apache模块 mod_ext_filter
- Apache模块 mod_file_cache
- Apache模块 mod_filter
- Apache模块 mod_headers
- Apache模块 mod_ident
- Apache模块 mod_imagemap
- Apache模块 mod_include
- Apache模块 mod_info
- Apache模块 mod_isapi
- Apache模块 mod_ldap
- Apache模块 mod_log_config
- Apache模块 mod_log_forensic
- Apache模块 mod_logio
- Apache模块 mod_mem_cache
- Apache模块 mod_mime
- Apache模块 mod_mime_magic
- Apache模块 mod_negotiation
- Apache模块 mod_nw_ssl
- Apache模块 mod_proxy
- Apache模块 mod_proxy_ajp
- Apache模块 mod_proxy_balancer
- Apache模块 mod_proxy_connect
- Apache模块 mod_proxy_ftp
- Apache模块 mod_proxy_http
- Apache模块 mod_rewrite
- Apache模块 mod_setenvif
- Apache模块 mod_so
- Apache模块 mod_speling
- Apache模块 mod_ssl
- Apache模块 mod_status
- Apache模块 mod_suexec
- Apache模块 mod_unique_id
- Apache模块 mod_userdir
- Apache模块 mod_usertrack
- Apache模块 mod_version
- Apache模块 mod_vhost_alias
- Developer Documentation for Apache 2.0
- Apache 1.3 API notes
- Debugging Memory Allocation in APR
- Documenting Apache 2.0
- Apache 2.0 Hook Functions
- Converting Modules from Apache 1.3 to Apache 2.0
- Request Processing in Apache 2.0
- How filters work in Apache 2.0
- Apache 2.0 Thread Safety Issues
- 词汇和索引
- 词汇表
- 指令索引
- 指令速查
- 模块索引
- 站点导航