Apache httpd 教程:服务器端包含的简介

服务器端包括提供一种将动态内容添加到现有 HTML 文档的方法。

Introduction

Related Modules Related Directives
mod_include
mod_cgi
mod_expires
Options
XBitHack
AddType
SetOutputFilter
BrowserMatchNoCase

本文介绍了通常称为 SSI 的服务器端包含。在本文中,我将讨论如何配置服务器以允许 SSI,并介绍一些基本的 SSI 技术,以便将动态内容添加到现有的 HTML 页面中。

在本文的后半部分,我们将讨论 SSI 可以完成的一些更高级的操作,例如 SSI 指令中的条件语句。

什么是 SSI?

SSI(服务器端包含)是放置在 HTML 页面中的指令,并在服务页面时在服务器上对其进行评估。它们使您可以将动态生成的内容添加到现有的 HTML 页面,而不必通过 CGI 程序或其他动态技术来提供整个页面。

例如,您可以将指令放置到现有的 HTML 页面中,例如:

<!--#echo var="DATE_LOCAL" -->

并且,当该页面被投放时,该片段将被评估并替换为其值:

Tuesday, 15-Jan-2013 19:28:54 EST

什么时候使用 SSI,什么时候完全由某个程序生成页面的决定,通常取决于多少页面是静态的,以及每次服务该页面时需要重新计算多少。 SSI 是添加少量信息(例如当前时间)的好方法-如上所示。但是,如果大部分页面是在投放时生成的,则需要寻找其他解决方案。

配置服务器以允许 SSI

要在服务器上允许 SSI,必须在httpd.conf文件或.htaccess文件中具有以下指令:

Options +Includes

这告诉 Apache 您想允许对文件进行 SSI 指令解析。请注意,大多数配置包含多个可以相互覆盖的Options指令。您可能需要将Options应用于要启用 SSI 的特定目录,以确保它最后被评估。

不仅为 SSI 指令解析任何文件。您必须告诉 Apache 应该解析哪些文件。有两种方法可以做到这一点。您可以使用以下指令告诉 Apache 解析具有特定文件 extensions 的任何文件,例如.shtml

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

这种方法的一个缺点是,如果要向现有页面添加 SSI 指令,则必须更改该页面的名称以及该页面的所有链接,以便为其提供.shtmlextensions,以便这些指令将被执行。

另一种方法是使用XBitHack指令:

XBitHack on

XBitHack告诉 Apache 解析文件中的 SSI 指令(如果它们设置了执行位)。因此,要将 SSI 指令添加到现有页面中,而不必更改文件名,只需使用chmod使文件可执行。

chmod +x pagename.html

关于不做什么的简短 Comment。有时您会看到有人建议您只告诉 Apache 解析 SSI 的所有.html文件,这样就不必弄乱.shtml文件名。这些人也许还没有听说过XBitHack。要记住的事情是,这样做,您需要 Apache 读取它发送给 Client 端的每个文件,即使它们不包含任何 SSI 指令。这会使事情变慢很多,不是一个好主意。

当然,在 Windows 上,不需要设置执行位,因此对您的选项有一些限制。

在其默认配置中,Apache 不会在 SSI 页面上发送上次修改日期或内容长度的 HTTP Headers,因为很难为动态内容计算这些值。这样可以防止文档被缓存,并导致 Client 端性能下降。有两种解决方法:

基本 SSI 指令

SSI 指令具有以下语法:

<!--#function attribute=value attribute=value ... -->

它的格式类似于 HTML Comments,因此,如果未正确启用 SSI,浏览器将忽略它,但在 HTML 源代码中仍然可见。如果正确配置了 SSI,则该指令将被其结果替换。

函数可以是很多事情之一,在本系列的下一部分中,我们将进一步讨论其中的大多数。现在,这里有一些您可以使用 SSI 进行操作的示例

Today's date

<!--#echo var="DATE_LOCAL" -->

echo函数只是吐出一个变量的值。有许多标准变量,包括 CGI 程序可用的整套环境变量。另外,您可以使用set函数定义自己的变量。

如果您不喜欢打印日期的格式,则可以使用带有timefmt属性的config函数来修改该格式。

<!--#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" -->

Additional examples

以下是一些可以使用 SSI 在 HTML 文档中执行的操作的特定示例。

该文档何时修改?

之前,我们提到您可以使用 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。语法是一样的。

包含标准页脚

如果您要 Management 的页面超过几个页面,则可能会发现对所有这些页面进行更改可能会非常麻烦,尤其是当您试图在所有这些页面上保持某种标准外观时。

将包含文件用于页眉和/或页脚可以减少这些更新的负担。您只需要制作一个页脚文件,然后使用include SSI 命令将其包含在每一页中即可。 include函数可以确定要包含file属性还是virtual属性的文件。 file属性是相对于当前目录的文件路径。这意味着它不能是绝对文件路径(以/开头),也不能包含../作为该路径的一部分。 virtual属性可能更有用,并且应指定相对于所服务文档的 URL。它可以以/开头,但必须与所提供的文件位于同一服务器上。

<!--#include virtual="/footer.html" -->

我经常结合最后两件事,将LAST_MODIFIED指令放在要包含的页脚文件中。 SSI 指令可以包含在包含的文件中,并且 includes 可以嵌套-也就是说,包含的文件可以包含另一个文件,依此类推。

我还能配置什么?

除了能够config时间格式,您还可以config另外两件事。

通常,当您的 SSI 指令出现问题时,您会收到以下消息:

[an error occurred while processing this directive]

如果您想将该消息更改为其他内容,可以使用config函数的errmsg属性进行更改:

<!--#config errmsg="[It appears that you don't know how to use SSI]" -->

希望最终用户永远不会看到此消息,因为您将在站点上线之前解决 SSI 指令的所有问题。 (对?)

而且,您可以config通过sizefmt属性返回文件大小的格式。您可以指定bytes以字节为单位的完整计数,或abbrev以 Kb 或 Mb 表示的缩写数字。

Executing commands

您可以使用exec函数执行其他操作。实际上,您可以让 SSI 使用 shell(确切地说是/bin/sh-或 DOS shell,如果您使用的是 Win32)执行命令。例如,以下内容将为您提供目录列表。

<pre> <!--#exec cmd="ls" --> </pre>

或者,在 Windows 上

<pre> <!--#exec cmd="dir" --> </pre>

您可能会在 Windows 上注意到此指令的某些奇怪格式,因为dir的输出中包含字符串``<dir>'',这会使浏览器感到困惑。

请注意,此功能极其危险,因为它将执行恰好嵌入在exec标签中的任何代码。如果您遇到用户可以编辑网页内容的任何情况,例如使用``留言簿'',请确保禁用此功能。您可以通过Options指令的IncludesNOEXEC参数来允许 SSI,但不允许exec功能。

先进的 SSI 技术

除了吐出内容外,Apache SSI 还为您提供了设置变量的选项,并可以在比较和条件条件中使用这些变量。

Setting variables

使用set指令,可以设置变量以备后用。在稍后的讨论中我们将需要它,因此我们将在这里讨论。其语法如下:

<!--#set var="name" value="Rich" -->

除了像这样从字面上设置值之外,您还可以使用任何其他变量,包括environment variables或上面讨论的变量(例如LAST_MODIFIED)为变量提供值。通过在变量名称前使用美元符号($),可以指定某物是变量,而不是 Literals 字符串。

<!--#set var="modified" value="$LAST_MODIFIED" -->

要将字面的美元符号放入变量的值,您需要使用反斜杠对美元符号进行转义。

<!--#set var="cost" value="\$100" -->

最后,如果您想将变量放在更长的字符串中间,并且变量名有可能与其他字符冲突,从而与这些字符混淆,则可以将变量名花括号中的变量,以消除这种混乱。 (很难给出一个很好的例子,但希望您能明白这一点.)

<!--#set var="date" value="${DATE_LOCAL}_${DATE_GMT}" -->

Conditional expressions

现在我们有了变量,并且能够设置和比较它们的值,我们可以使用它们来表达条件。这使 SSI 成为一种微小的编程语言。 mod_include提供了一个ifelifelseendif结构来构建条件语句。这使您可以有效地从一个实际页面中生成多个逻辑页面。

此条件构造的结构为:

<!--#if expr="test_condition" --> <!--#elif expr="test_condition" --> <!--#else --> <!--#endif -->

例如,如果您希望基于一天中的时间自定义网页上的文本,则可以使用以下食谱,将其放在 HTML 页面中:

Good <!--#if expr="%{TIME_HOUR} <12" --> morning! <!--#else --> afternoon! <!--#endif -->

任何其他变量(您定义的变量或常规环境变量)都可以在条件语句中使用。有关表达式评估引擎的更多信息,请参见Apache HTTP Server 中的表达式

Apache 具有使用SetEnvIf指令和其他相关指令设置环境变量的功能,该功能可以让您在服务器端执行多种动态内容,而无需使用完整的 Web 应用程序。

Conclusion

SSI 当然不能替代 CGI 或用于生成动态网页的其他技术。但这是在页面上添加少量动态内容的好方法,而无需执行大量额外工作。

首页