Apache HTTP 服务器版本 2.4
相关模块 | 相关指令 |
---|---|
本文介绍服务器端包含,通常简称为 SSI。在这篇文章中,我将讨论如何配置您的服务器以允许 SSI,并介绍一些基本 SSI 技术,用于向您现有的 HTML 页面添加动态内容。
在本文的后面部分,我们将讨论一些使用 SSI 可以完成的更高级的事情,例如 SSI 指令中的条件语句。
SSI(服务器端包含)是放置在 HTML 页面中的指令,并在服务器提供页面时进行评估。它们允许您向现有的 HTML 页面添加动态生成的内容,而无需通过 CGI 程序或其他动态技术提供整个页面。
例如,您可以在现有的 HTML 页面中放置一个指令,例如
<!--#echo var="DATE_LOCAL" -->
当页面被提供时,此片段将被评估并替换为其值
星期二,2013 年 1 月 15 日 19:28:54 EST
何时使用 SSI 以及何时让您的页面完全由某个程序生成,通常取决于页面中静态内容的多少以及每次提供页面时需要重新计算的内容的多少。SSI 是添加少量信息(例如上面显示的当前时间)的好方法。但是,如果您的页面大部分内容是在提供时生成的,则需要寻找其他解决方案。
要在您的服务器上允许 SSI,您必须在您的 httpd.conf
文件或 .htaccess
文件中包含以下指令
Options +Includes
这告诉 Apache 您希望允许解析文件以查找 SSI 指令。请注意,大多数配置包含多个 Options
指令,这些指令可以相互覆盖。您可能需要将 Options
应用于您希望启用 SSI 的特定目录,以确保它最后被评估。
并非所有文件都解析 SSI 指令。您必须告诉 Apache 哪些文件应该被解析。有两种方法可以做到这一点。您可以告诉 Apache 解析具有特定文件扩展名(例如 .shtml
)的任何文件,使用以下指令
AddType text/html .shtml AddOutputFilter INCLUDES .shtml
这种方法的一个缺点是,如果您想向现有页面添加 SSI 指令,则必须更改该页面的名称以及指向该页面的所有链接,以使其具有 .shtml
扩展名,以便执行这些指令。
另一种方法是使用 XBitHack
指令
XBitHack on
XBitHack
告诉 Apache 如果文件具有可执行位,则解析文件以查找 SSI 指令。因此,要向现有页面添加 SSI 指令,而不是必须更改文件名,您只需要使用 chmod
使文件可执行即可。
chmod +x pagename.html
关于不应该做什么的简短说明。您偶尔会看到人们建议您只告诉 Apache 解析所有 .html
文件以查找 SSI,这样您就不必处理 .shtml
文件名。这些人可能没有听说过 XBitHack
。要记住的是,通过这样做,您要求 Apache 读取它发送给客户端的每个文件,即使它们不包含任何 SSI 指令。这可能会使速度变慢,这不是一个好主意。
当然,在 Windows 上,没有可执行位可以设置,因此这会限制您的选择。
在默认配置中,Apache 不会在 SSI 页面上发送最后修改日期或内容长度 HTTP 标头,因为这些值对于动态内容来说很难计算。这会阻止您的文档被缓存,并导致感知到的客户端性能下降。有两种方法可以解决这个问题
XBitHack Full
配置。这告诉 Apache 通过仅查看最初请求的文件的日期来确定最后修改日期,而忽略任何包含文件的修改日期。mod_expires
提供的指令为您的文件设置明确的过期时间,从而让浏览器和代理知道可以缓存它们。SSI 指令具有以下语法
<!--#function attribute=value attribute=value ... -->
它的格式类似于 HTML 注释,因此如果您没有正确启用 SSI,浏览器会忽略它,但它仍然会在 HTML 源代码中可见。如果您正确配置了 SSI,则指令将被替换为其结果。
函数可以是多种东西之一,我们将在本系列的下一期中详细讨论其中大部分。现在,以下是一些您可以使用 SSI 完成的操作示例
<!--#echo var="DATE_LOCAL" -->
echo
函数只是输出变量的值。有许多标准变量,包括可用于 CGI 程序的整个环境变量集。此外,您还可以使用 set
函数定义自己的变量。
如果您不喜欢日期打印的格式,可以使用 config
函数,并使用 timefmt
属性来修改该格式。
<!--#config timefmt="%A %B %d, %Y" -->
今天是 <!--#echo var="DATE_LOCAL" -->
本文档最后修改于 <!--#flastmod file="index.html" -->
此函数也受 timefmt
格式配置的影响。
这是 SSI 的最常见用途之一 - 输出 CGI 程序的结果,例如大家最喜欢的“点击计数器”。
<!--#include virtual="/cgi-bin/counter.pl" -->
以下是您可以在 HTML 文档中使用 SSI 完成的一些特定示例。
之前,我们提到您可以使用 SSI 来告知用户文档最近一次修改的时间。但是,执行此操作的实际方法尚不清楚。以下代码放置在您的 HTML 文档中,将在您的页面上放置这样的时间戳。当然,您必须正确启用 SSI,如上所述。
<!--#config timefmt="%A %B %d, %Y" -->
此文件最后修改于 <!--#flastmod file="ssi.shtml" -->
当然,您需要将 ssi.shtml
替换为您引用的文件的实际名称。如果您只是在寻找可以粘贴到任何文件的通用代码,这可能很麻烦,因此您可能希望使用 LAST_MODIFIED
变量代替
<!--#config timefmt="%D" -->
此文件最后修改于 <!--#echo var="LAST_MODIFIED" -->
有关 timefmt
格式的更多详细信息,请访问您最喜欢的搜索网站并查找 strftime
。语法相同。
如果您管理的任何网站都超过几个页面,您可能会发现更改所有这些页面非常痛苦,尤其是如果您试图在所有这些页面上保持某种标准外观。
使用包含文件来创建页眉和/或页脚可以减少这些更新的负担。您只需创建一个页脚文件,然后使用 include
SSI 命令将其包含到每个页面中。include
函数可以使用 file
属性或 virtual
属性来确定要包含的文件。file
属性是文件路径,相对于当前目录。这意味着它不能是绝对文件路径(以 / 开头),也不能包含 ../ 作为该路径的一部分。virtual
属性可能更有用,并且应该指定相对于正在提供服务的文档的 URL。它可以以 / 开头,但必须与正在提供服务的文档位于同一服务器上。
<!--#include virtual="/footer.html" -->
我经常将最后两件事结合起来,将 LAST_MODIFIED
指令放在要包含的页脚文件中。SSI 指令可以包含在包含文件中,并且包含可以嵌套 - 也就是说,包含文件可以包含另一个文件,依此类推。
除了能够 config
时间格式之外,您还可以 config
其他两件事。
通常,当您的 SSI 指令出现问题时,您会收到以下消息
[处理此指令时发生错误]
如果您想将此消息更改为其他内容,可以使用 config
函数的 errmsg
属性
<!--#config errmsg="[您似乎不知道如何使用 SSI]" -->
希望最终用户永远不会看到此消息,因为您将在网站上线之前解决所有 SSI 指令问题。(对吧?)
您可以使用 sizefmt
属性配置返回文件大小的格式。您可以指定 bytes
以获取以字节为单位的完整计数,或指定 abbrev
以获取以 Kb 或 Mb 为单位的简写数字,具体取决于情况。
以下是您可以使用 exec
函数执行的另一项操作。您实际上可以使用 SSI 通过 shell(确切地说,是 /bin/sh
- 或者如果您使用的是 Win32,则使用 DOS shell)执行命令。例如,以下命令将为您提供目录列表。
<pre>
<!--#exec cmd="ls" -->
</pre>
或者,在 Windows 上
<pre>
<!--#exec cmd="dir" -->
</pre>
您可能会注意到在 Windows 上使用此指令时,格式有些奇怪,因为 dir
的输出包含字符串 ``<dir
>'',这会使浏览器感到困惑。
请注意,此功能极其危险,因为它将执行嵌入在 exec
标签中的任何代码。如果您有任何用户可以编辑网页内容的情况,例如使用“留言板”,请确保您已禁用此功能。您可以允许 SSI,但不允许 exec
功能,方法是使用 Options
指令的 IncludesNOEXEC
参数。
除了输出内容外,Apache SSI 还允许您设置变量,并在比较和条件语句中使用这些变量。
使用 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
文档。
例如,如果您希望根据一天中的时间自定义网页上的文本,您可以使用以下配方,将其放置在 HTML 页面中
早上好 <!--#if expr="%{TIME_HOUR} <12" -->
早上好!
<!--#else -->
下午好!
<!--#endif -->
任何其他变量(无论是您定义的变量还是普通环境变量)都可以在条件语句中使用。有关表达式求值引擎的更多信息,请参阅 Apache HTTP Server 中的表达式。
借助 Apache 使用 SetEnvIf
指令和其他相关指令设置环境变量的功能,此功能可以让您在服务器端执行各种动态内容,而无需使用完整的 Web 应用程序。
SSI 当然不能替代 CGI 或其他用于生成动态网页的技术。但它是一种在页面中添加少量动态内容的好方法,无需做太多额外工作。