ssi.xml revision dc643bc37eec0af989b9623deaa81fb9499b6c8e
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<?xml version='1.0' encoding='UTF-8' ?>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<!DOCTYPE manualpage SYSTEM "/style/manualpage.dtd">
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<?xml-stylesheet type="text/xsl" href="/style/manual.en.xsl"?>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<manualpage>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<relativepath href=".."/>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<title>Apache Tutorial: Introduction to Server Side Includes</title>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<summary>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<p>Server-side includes provide a means to add dynamic content to
0853e1e2522c1ac17f697221758bcbd4781a7ff9ndexisting HTML documents.</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd</summary>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<section id="related"><title>Introduction</title>
27e52281f1522522b170cafc76b08b58aa70ccaand <related>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <modulelist>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <module>mod_include</module>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <module>mod_cgi</module>
4b5981e276e93df97c34e4da05ca5cf8bbd937dand <module>mod_expires</module>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd </modulelist>
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd <directivelist>
ecc5150d35c0dc5ee5119c2717e6660fa331abbftakashi <directive module="core">Options</directive>
bc9d4698fce0238d2f6f2682e99423ebb1149976rbowen <directive module="mod_include">XBitHack</directive>
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd <directive module="mod_mime">AddType</directive>
63f06dce77bb2d9b1c5aa5deeb47a1069987fd1end <directive module="core">SetOutputFilter</directive>
ecc5150d35c0dc5ee5119c2717e6660fa331abbftakashi <directive module="mod_setenvif">BrowserMatchNoCase</directive>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd </directivelist>
48c64aeceef385e19025b384bd719b2a9789592dnd</related>
48c64aeceef385e19025b384bd719b2a9789592dnd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <p>This article deals with Server Side Includes, usually called
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd simply SSI. In this article, I'll talk about configuring your
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd server to permit SSI, and introduce some basic SSI techniques
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd for adding dynamic content to your existing HTML pages.</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <p>In the latter part of the article, we'll talk about some of
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd the somewhat more advanced things that can be done with SSI,
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd such as conditional statements in your SSI directives.</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd</section>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<section id="what"><title>What are SSI?</title>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <p>SSI (Server Side Includes) are directives that are placed in
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd HTML pages, and evaluated on the server while the pages are
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd being served. They let you add dynamically generated content to
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd an existing HTML page, without having to serve the entire page
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd via a CGI program, or other dynamic technology.</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <p>The decision of when to use SSI, and when to have your page
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd entirely generated by some program, is usually a matter of how
80eed96ee3d8cfa0b66d9fb1cfe63fd83254d38bnilgun much of the page is static, and how much needs to be
80eed96ee3d8cfa0b66d9fb1cfe63fd83254d38bnilgun recalculated every time the page is served. SSI is a great way
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd to add small pieces of information, such as the current time.
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd But if a majority of your page is being generated at the time
316f02e3836836c82e19019ff23f90a7ebc65289nilgun that it is served, you need to look for some other
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd solution.</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd</section>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<section id="configuring">
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<title>Configuring your server to permit SSI</title>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <p>To permit SSI on your server, you must have the following
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd directive either in your <code>httpd.conf</code> file, or in a
08cf4a15275e4cb65a424b3a1db5410bfb51085cjim <code>.htaccess</code> file:</p>
22d5d84393d960a2027f472036f3fee15d7dbce9nd<example>
22d5d84393d960a2027f472036f3fee15d7dbce9nd Options +Includes
22d5d84393d960a2027f472036f3fee15d7dbce9nd</example>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
a78048ccbdb6256da15e6b0e7e95355e480c2301nd <p>This tells Apache that you want to permit files to be parsed
a78048ccbdb6256da15e6b0e7e95355e480c2301nd for SSI directives. Note that most configurations contain
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd multiple <directive module="core">Options</directive> directives
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd that can override each other. You will probably need to apply the
a78048ccbdb6256da15e6b0e7e95355e480c2301nd <code>Options</code> to the specific directory where you want SSI
623eebe956d9c2d6d073ed3eae855b56030b40e9noodl enabled in order to assure that it gets evaluated last.</p>
a78048ccbdb6256da15e6b0e7e95355e480c2301nd
a78048ccbdb6256da15e6b0e7e95355e480c2301nd <p>Not just any file is parsed for SSI directives. You have to
ffb88a4885747797937e30a5ac8b1606da3cb4adnd tell Apache which files should be parsed. There are two ways to
909ce17e2bd0faef7b1c294f2307f009793fd493nd do this. You can tell Apache to parse any file with a
a78048ccbdb6256da15e6b0e7e95355e480c2301nd particular file extension, such as <code>.shtml</code>, with
a78048ccbdb6256da15e6b0e7e95355e480c2301nd the following directives:</p>
42af92a661a06b3cebc88d585aad75064a309d51nd<example>
42af92a661a06b3cebc88d585aad75064a309d51nd AddType text/html .shtml<br />
ffb88a4885747797937e30a5ac8b1606da3cb4adnd AddOutputFilter INCLUDES .shtml
6fe26506780e73be2a412d758af77fafdf03291and</example>
a78048ccbdb6256da15e6b0e7e95355e480c2301nd
a78048ccbdb6256da15e6b0e7e95355e480c2301nd <p>One disadvantage to this approach is that if you wanted to
9649d29bb7801e0698e6a845e1a8a61534df58b3noodl add SSI directives to an existing page, you would have to
9649d29bb7801e0698e6a845e1a8a61534df58b3noodl change the name of that page, and all links to that page, in
a78048ccbdb6256da15e6b0e7e95355e480c2301nd order to give it a <code>.shtml</code> extension, so that those
a78048ccbdb6256da15e6b0e7e95355e480c2301nd directives would be executed.</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <p>The other method is to use the <directive
08cf4a15275e4cb65a424b3a1db5410bfb51085cjim module="mod_includes">XBitHack</directive> directive:</p>
6aadbc6fd703e73d1d419e9f06b84a4338c898f1maczniak<example>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd XBitHack on
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd</example>
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd <p><directive module="mod_includes">XBitHack</directive>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd tells Apache to parse files for SSI
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd directives if they have the execute bit set. So, to add SSI
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd directives to an existing page, rather than having to change
05ede5110427cb9dc071cc671d5aaba5d3b88c79nd the file name, you would just need to make the file executable
e8b603fa9ccf7b17b11b42df6d8916fd97c2331dnd using <code>chmod</code>.</p>
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd<example>
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd chmod +x pagename.html
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd</example>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
611049e38bfbaeb173d2d7fab2e44a48753436a1nd <p>A brief comment about what not to do. You'll occasionally
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd see people recommending that you just tell Apache to parse all
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd <code>.html</code> files for SSI, so that you don't have to
8574d86b9ec3be36b7f54ed0547a0ee5d60dbd6bnd mess with <code>.shtml</code> file names. These folks have
a78048ccbdb6256da15e6b0e7e95355e480c2301nd perhaps not heard about <directive
6aadbc6fd703e73d1d419e9f06b84a4338c898f1maczniak module="mod_includes">XBitHack</directive>. The thing to
6aadbc6fd703e73d1d419e9f06b84a4338c898f1maczniak keep in mind is that, by doing this, you're requiring that
a78048ccbdb6256da15e6b0e7e95355e480c2301nd Apache read through every single file that it sends out to
a78048ccbdb6256da15e6b0e7e95355e480c2301nd clients, even if they don't contain any SSI directives. This
a78048ccbdb6256da15e6b0e7e95355e480c2301nd can slow things down quite a bit, and is not a good idea.</p>
03a4ff9ac4c9b8009249010e7c53bb86ff05915and
f21bea4c0f58e17aa1d9a0fac2c219852f89944amaczniak <p>Of course, on Windows, there is no such thing as an execute
d0828c8a321dc5e9ea60550f052294669c08cf93jim bit to set, so that limits your options a little.</p>
d0828c8a321dc5e9ea60550f052294669c08cf93jim
f21bea4c0f58e17aa1d9a0fac2c219852f89944amaczniak <p>In its default configuration, Apache does not send the last
4b5981e276e93df97c34e4da05ca5cf8bbd937dand modified date or content length HTTP headers on SSI pages,
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd because these values are difficult to calculate for dynamic
f21bea4c0f58e17aa1d9a0fac2c219852f89944amaczniak content. This can prevent your document from being cached, and
6aadbc6fd703e73d1d419e9f06b84a4338c898f1maczniak result in slower perceived client performance. There are two
2704de98885368683621b01c8f8f4e4b01557611takashi ways to solve this:</p>
2704de98885368683621b01c8f8f4e4b01557611takashi
2704de98885368683621b01c8f8f4e4b01557611takashi <ol>
d0828c8a321dc5e9ea60550f052294669c08cf93jim <li>Use the <code>XBitHack Full</code> configuration. This
2704de98885368683621b01c8f8f4e4b01557611takashi tells Apache to determine the last modified date by looking
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd only at the date of the originally requested file, ignoring
6aadbc6fd703e73d1d419e9f06b84a4338c898f1maczniak the modification date of any included files.</li>
d2b809e5d72658bff23819d8b77f20e4939af541nd
a78048ccbdb6256da15e6b0e7e95355e480c2301nd <li>Use the directives provided by
cd6c8de3bedcc401ee230159b0439fa20f44488etakashi <module>mod_expires</module> to set an explicit expiration
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd time on your files, thereby letting browsers and proxies
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd know that it is acceptable to cache them.</li>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd </ol>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd</section>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<section id="basic"><title>Basic SSI directives</title>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
1de1266f0ea387d6373be8415745dfd2ab876341jim <p>SSI directives have the following syntax:</p>
27d778df0b517e1578f907d2e51eb961cd8ee5fbjim<example>
27d778df0b517e1578f907d2e51eb961cd8ee5fbjim &lt;!--#element attribute=value attribute=value ... --&gt;
a43bfa789f4e52dde53ae8e53fa0427b5c1cf977nd</example>
a43bfa789f4e52dde53ae8e53fa0427b5c1cf977nd
28c9d384aa958b321280b4ac886941dcad25396bnd <p>It is formatted like an HTML comment, so if you don't have
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd SSI correctly enabled, the browser will ignore it, but it will
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd still be visible in the HTML source. If you have SSI correctly
1d980e5489836e977ba59b419e27b0ec875c4bd3takashi configured, the directive will be replaced with its
e5ce3ac0e9b720c0fa23782e29168a0810697fdetakashi results.</p>
604c89126c27104f659d7a51b0113e3bd435faf8fielding
50cb7e2b30597f481fee57bac945190f06ebcc58jorton <p>The element can be one of a number of things, and we'll talk
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd some more about most of these in the next installment of this
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd series. For now, here are some examples of what you can do with
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd SSI</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0a69d9bb491d9810892a9949c01403a1de3c7ac2nd<section id="todaysdate"><title>Today's date</title>
6d20aeba2c4aa0938bc6e0659d13adc7670ff421poirier
6d20aeba2c4aa0938bc6e0659d13adc7670ff421poirier<example>
5f4e50966b2b9b58436a1651cbe588d1b595657ewrowe &lt;!--#echo var="DATE_LOCAL" --&gt;
5f4e50966b2b9b58436a1651cbe588d1b595657ewrowe</example>
5f4e50966b2b9b58436a1651cbe588d1b595657ewrowe
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun <p>The <code>echo</code> element just spits out the value of a
11495c9f0bd33e51a25b4d532beadfbcf9b944a3nilgun variable. There are a number of standard variables, which
5f4e50966b2b9b58436a1651cbe588d1b595657ewrowe include the whole set of environment variables that are
ecc5150d35c0dc5ee5119c2717e6660fa331abbftakashi available to CGI programs. Also, you can define your own
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd variables with the <code>set</code> element.</p>
50cb7e2b30597f481fee57bac945190f06ebcc58jorton
79b024b81f6bb3c44dce77a7552191daf8b522d2jim <p>If you don't like the format in which the date gets printed,
f772e8f448c223e5ea306f1bf92d97d968f972d5jim you can use the <code>config</code> element, with a
f772e8f448c223e5ea306f1bf92d97d968f972d5jim <code>timefmt</code> attribute, to modify that formatting.</p>
fac8c35bfb158112226ab43ddf84d59daca5dc30nd
f772e8f448c223e5ea306f1bf92d97d968f972d5jim<example>
1de1266f0ea387d6373be8415745dfd2ab876341jim &lt;!--#config timefmt="%A %B %d, %Y" --&gt;<br />
1de1266f0ea387d6373be8415745dfd2ab876341jim Today is &lt;!--#echo var="DATE_LOCAL" --&gt;
a78048ccbdb6256da15e6b0e7e95355e480c2301nd</example>
a78048ccbdb6256da15e6b0e7e95355e480c2301nd</section>
a78048ccbdb6256da15e6b0e7e95355e480c2301nd
a78048ccbdb6256da15e6b0e7e95355e480c2301nd<section id="lastmodified"><title>Modification date of the file</title>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<example>
a78048ccbdb6256da15e6b0e7e95355e480c2301nd This document last modified &lt;!--#flastmod file="index.html" --&gt;
898711b68797304101de0882fa576c8908acfae6nd</example>
a78048ccbdb6256da15e6b0e7e95355e480c2301nd
a78048ccbdb6256da15e6b0e7e95355e480c2301nd <p>This element is also subject to <code>timefmt</code> format
a78048ccbdb6256da15e6b0e7e95355e480c2301nd configurations.</p>
50cb7e2b30597f481fee57bac945190f06ebcc58jorton</section>
a78048ccbdb6256da15e6b0e7e95355e480c2301nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<section id="cgi"><title>Including the results of a CGI program</title>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <p>This is one of the more common uses of SSI - to output the
8e31885fc494b603e0650113dde9e29d1b1d2602maczniak results of a CGI program, such as everybody's favorite, a ``hit
03c25fb6f628ac81f2ecb637d1e7502dcee783f3nd counter.''</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd<example>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd &lt;!--#include virtual="/cgi-bin/counter.pl" --&gt;
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd</example>
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd
ecc5150d35c0dc5ee5119c2717e6660fa331abbftakashi</section>
bc9d4698fce0238d2f6f2682e99423ebb1149976rbowen</section>
ad74a0524a06bfe11b7de9e3b4ce7233ab3bd3f7nd
63f06dce77bb2d9b1c5aa5deeb47a1069987fd1end<section id="additionalexamples">
ecc5150d35c0dc5ee5119c2717e6660fa331abbftakashi<title>Additional examples</title>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd
50039065d571fe01fd458a3f031c995a1fd53c22rbowen <p>Following are some specific examples of things you can do in
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd your HTML documents with SSI.</p>
0853e1e2522c1ac17f697221758bcbd4781a7ff9nd <hr />
<section id="docmodified"><title>When was this document
modified?</title>
<p>Earlier, we mentioned that you could use SSI to inform the
user when the document was most recently modified. However, the
actual method for doing that was left somewhat in question. The
following code, placed in your HTML document, will put such a
time stamp on your page. Of course, you will have to have SSI
correctly enabled, as discussed above.</p>
<example>
&lt;!--#config timefmt="%A %B %d, %Y" --&gt;<br />
This file last modified &lt;!--#flastmod file="ssi.shtml" --&gt;
</example>
<p>Of course, you will need to replace the
<code>ssi.shtml</code> with the actual name of the file that
you're referring to. This can be inconvenient if you're just
looking for a generic piece of code that you can paste into any
file, so you probably want to use the
<code>LAST_MODIFIED</code> variable instead:</p>
<example>
&lt;!--#config timefmt="%D" --&gt;<br />
This file last modified &lt;!--#echo var="LAST_MODIFIED" --&gt;
</example>
<p>For more details on the <code>timefmt</code> format, go to
your favorite search site and look for <code>strftime</code>. The
syntax is the same.</p>
</section>
<section id="footer">
<title>Including a standard footer</title>
<p>If you are managing any site that is more than a few pages,
you may find that making changes to all those pages can be a
real pain, particularly if you are trying to maintain some kind
of standard look across all those pages.</p>
<p>Using an include file for a header and/or a footer can
reduce the burden of these updates. You just have to make one
footer file, and then include it into each page with the
<code>include</code> SSI command. The <code>include</code>
element can determine what file to include with either the
<code>file</code> attribute, or the <code>virtual</code>
attribute. The <code>file</code> attribute is a file path,
<em>relative to the current directory</em>. That means that it
cannot be an absolute file path (starting with /), nor can it
contain ../ as part of that path. The <code>virtual</code>
attribute is probably more useful, and should specify a URL
relative to the document being served. It can start with a /,
but must be on the same server as the file being served.</p>
<example>
&lt;!--#include virtual="/footer.html" --&gt;
</example>
<p>I'll frequently combine the last two things, putting a
<code>LAST_MODIFIED</code> directive inside a footer file to be
included. SSI directives can be contained in the included file,
and includes can be nested - that is, the included file can
include another file, and so on.</p>
</section>
</section>
<section id="config">
<title>What else can I config?</title>
<p>In addition to being able to <code>config</code> the time
format, you can also <code>config</code> two other things.</p>
<p>Usually, when something goes wrong with your SSI directive,
you get the message</p>
<example>
[an error occurred while processing this directive]
</example>
<p>If you want to change that message to something else, you
can do so with the <code>errmsg</code> attribute to the
<code>config</code> element:</p>
<example>
&lt;!--#config errmsg="[It appears that you don't know how to use SSI]" --&gt;
</example>
<p>Hopefully, end users will never see this message, because
you will have resolved all the problems with your SSI
directives before your site goes live. (Right?)</p>
<p>And you can <code>config</code> the format in which file
sizes are returned with the <code>sizefmt</code> attribute. You
can specify <code>bytes</code> for a full count in bytes, or
<code>abbrev</code> for an abbreviated number in Kb or Mb, as
appropriate.</p>
</section>
<section id="exec">
<title>Executing commands</title>
<p>I expect that I'll have an article some time in the coming
months about using SSI with small CGI programs. For now, here's
something else that you can do with the <code>exec</code>
element. You can actually have SSI execute a command using the
shell (<code>/bin/sh</code>, to be precise - or the DOS shell,
if you're on Win32). The following, for example, will give you
a directory listing.</p>
<example>
&lt;pre&gt;<br />
&lt;!--#exec cmd="ls" --&gt;<br />
&lt;/pre&gt;
</example>
<p>or, on Windows</p>
<example>
&lt;pre&gt;<br />
&lt;!--#exec cmd="dir" --&gt;<br />
&lt;/pre&gt;
</example>
<p>You might notice some strange formatting with this directive
on Windows, because the output from <code>dir</code> contains
the string ``&lt;<code>dir</code>&gt;'' in it, which confuses
browsers.</p>
<p>Note that this feature is exceedingly dangerous, as it will
execute whatever code happens to be embedded in the
<code>exec</code> tag. If you have any situation where users
can edit content on your web pages, such as with a
``guestbook'', for example, make sure that you have this
feature disabled. You can allow SSI, but not the
<code>exec</code> feature, with the <code>IncludesNOEXEC</code>
argument to the <code>Options</code> directive.</p>
</section>
<section id="advanced">
<title>Advanced SSI techniques</title>
<p>In addition to spitting out content, Apache SSI gives you
the option of setting variables, and using those variables in
comparisons and conditionals.</p>
<section id="caveat"><title>Caveat</title>
<p>Most of the features discussed in this article are only
available to you if you are running Apache 1.2 or later. Of
course, if you are not running Apache 1.2 or later, you need to
upgrade immediately, if not sooner. Go on. Do it now. We'll
wait.</p>
</section>
<section id="variables"><title>Setting variables</title>
<p>Using the <code>set</code> directive, you can set variables
for later use. We'll need this later in the discussion, so
we'll talk about it here. The syntax of this is as follows:</p>
<example>
&lt;!--#set var="name" value="Rich" --&gt;
</example>
<p>In addition to merely setting values literally like that,
you can use any other variable, including, for example,
environment variables, or some of the variables we discussed in
the last article (like <code>LAST_MODIFIED</code>, for example)
to give values to your variables. You will specify that
something is a variable, rather than a literal string, by using
the dollar sign ($) before the name of the variable.</p>
<example>
&lt;!--#set var="modified" value="$LAST_MODIFIED" --&gt;
</example>
<p>To put a literal dollar sign into the value of your
variable, you need to escape the dollar sign with a
backslash.</p>
<example>
&lt;!--#set var="cost" value="\$100" --&gt;
</example>
<p>Finally, if you want to put a variable in the midst of a
longer string, and there's a chance that the name of the
variable will run up against some other characters, and thus be
confused with those characters, you can place the name of the
variable in braces, to remove this confusion. (It's hard to
come up with a really good example of this, but hopefully
you'll get the point.)</p>
<example>
&lt;!--#set var="date" value="${DATE_LOCAL}_${DATE_GMT}" --&gt;
</example>
</section>
<section id="conditional">
<title>Conditional expressions</title>
<p>Now that we have variables, and are able to set and compare
their values, we can use them to express conditionals. This
lets SSI be a tiny programming language of sorts.
<code>mod_include</code> provides an <code>if</code>,
<code>elif</code>, <code>else</code>, <code>endif</code>
structure for building conditional statements. This allows you
to effectively generate multiple logical pages out of one
actual page.</p>
<p>The structure of this conditional construct is:</p>
<example>
&lt;!--#if expr="test_condition" --&gt;<br />
&lt;!--#elif expr="test_condition" --&gt;<br />
&lt;!--#else --&gt;<br />
&lt;!--#endif --&gt;
</example>
<p>A <em>test_condition</em> can be any sort of logical
comparison - either comparing values to one another, or testing
the ``truth'' of a particular value. (A given string is true if
it is nonempty.) For a full list of the comparison operators
available to you, see the <code>mod_include</code>
documentation. Here are some examples of how one might use this
construct.</p>
<p>In your configuration file, you could put the following
line:</p>
<example>
BrowserMatchNoCase macintosh Mac<br />
BrowserMatchNoCase MSIE InternetExplorer
</example>
<p>This will set environment variables ``Mac'' and
``InternetExplorer'' to true, if the client is running Internet
Explorer on a Macintosh.</p>
<p>Then, in your SSI-enabled document, you might do the
following:</p>
<example>
&lt;!--#if expr="${Mac} &amp;&amp; ${InternetExplorer}" --&gt;<br />
Apologetic text goes here<br />
&lt;!--#else --&gt;<br />
Cool JavaScript code goes here<br />
&lt;!--#endif --&gt;
</example>
<p>Not that I have anything against IE on Macs - I just
struggled for a few hours last week trying to get some
JavaScript working on IE on a Mac, when it was working
everywhere else. The above was the interim workaround.</p>
<p>Any other variable (either ones that you define, or normal
environment variables) can be used in conditional statements.
With Apache's ability to set environment variables with the
<code>SetEnvIf</code> directives, and other related directives,
this functionality can let you do some pretty involved dynamic
stuff without ever resorting to CGI.</p>
</section>
</section>
<section id="conclusion"><title>Conclusion</title>
<p>SSI is certainly not a replacement for CGI, or other
technologies used for generating dynamic web pages. But it is a
great way to add small amounts of dynamic content to pages,
without doing a lot of extra work.</p>
</section>
</manualpage>