]> granicus.if.org Git - apache/blob - docs/manual/howto/ssi.xml
b30c55b65ec4a0fdf275c76d480ef2f6b4458a4c
[apache] / docs / manual / howto / ssi.xml
1 <?xml version='1.0' encoding='UTF-8' ?>
2 <!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
3 <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
4 <manualpage metafile="ssi.xml.meta">
5 <relativepath href=".."/>
6 <parentdocument href="./">How-To / Tutorials</parentdocument>
7
8 <title>Apache Tutorial: Introduction to Server Side Includes</title>
9
10 <summary>
11 <p>Server-side includes provide a means to add dynamic content to
12 existing HTML documents.</p>
13 </summary>
14
15 <section id="related"><title>Introduction</title>
16  <related>
17     <modulelist>
18     <module>mod_include</module>
19     <module>mod_cgi</module>
20     <module>mod_expires</module>
21     </modulelist>
22
23     <directivelist>
24     <directive module="core">Options</directive>
25     <directive module="mod_include">XBitHack</directive>
26     <directive module="mod_mime">AddType</directive>
27     <directive module="core">SetOutputFilter</directive>
28     <directive module="mod_setenvif">BrowserMatchNoCase</directive>
29     </directivelist>
30 </related>
31
32     <p>This article deals with Server Side Includes, usually called
33     simply SSI. In this article, I'll talk about configuring your
34     server to permit SSI, and introduce some basic SSI techniques
35     for adding dynamic content to your existing HTML pages.</p>
36
37     <p>In the latter part of the article, we'll talk about some of
38     the somewhat more advanced things that can be done with SSI,
39     such as conditional statements in your SSI directives.</p>
40
41 </section>
42
43 <section id="what"><title>What are SSI?</title>
44
45     <p>SSI (Server Side Includes) are directives that are placed in
46     HTML pages, and evaluated on the server while the pages are
47     being served. They let you add dynamically generated content to
48     an existing HTML page, without having to serve the entire page
49     via a CGI program, or other dynamic technology.</p>
50
51     <p>The decision of when to use SSI, and when to have your page
52     entirely generated by some program, is usually a matter of how
53     much of the page is static, and how much needs to be
54     recalculated every time the page is served. SSI is a great way
55     to add small pieces of information, such as the current time.
56     But if a majority of your page is being generated at the time
57     that it is served, you need to look for some other
58     solution.</p>
59 </section>
60
61 <section id="configuring">
62 <title>Configuring your server to permit SSI</title>
63
64     <p>To permit SSI on your server, you must have the following
65     directive either in your <code>httpd.conf</code> file, or in a
66     <code>.htaccess</code> file:</p>
67 <example>
68         Options +Includes
69 </example>
70
71     <p>This tells Apache that you want to permit files to be parsed
72     for SSI directives.  Note that most configurations contain
73     multiple <directive module="core">Options</directive> directives
74     that can override each other.  You will probably need to apply the
75     <code>Options</code> to the specific directory where you want SSI
76     enabled in order to assure that it gets evaluated last.</p>
77
78     <p>Not just any file is parsed for SSI directives. You have to
79     tell Apache which files should be parsed. There are two ways to
80     do this. You can tell Apache to parse any file with a
81     particular file extension, such as <code>.shtml</code>, with
82     the following directives:</p>
83 <example>
84         AddType text/html .shtml<br />
85         AddOutputFilter INCLUDES .shtml
86 </example>
87
88     <p>One disadvantage to this approach is that if you wanted to
89     add SSI directives to an existing page, you would have to
90     change the name of that page, and all links to that page, in
91     order to give it a <code>.shtml</code> extension, so that those
92     directives would be executed.</p>
93
94     <p>The other method is to use the <directive 
95     module="mod_include">XBitHack</directive> directive:</p>
96 <example>
97         XBitHack on
98 </example>
99
100     <p><directive module="mod_include">XBitHack</directive>
101     tells Apache to parse files for SSI
102     directives if they have the execute bit set. So, to add SSI
103     directives to an existing page, rather than having to change
104     the file name, you would just need to make the file executable
105     using <code>chmod</code>.</p>
106 <example>
107         chmod +x pagename.html
108 </example>
109
110     <p>A brief comment about what not to do. You'll occasionally
111     see people recommending that you just tell Apache to parse all
112     <code>.html</code> files for SSI, so that you don't have to
113     mess with <code>.shtml</code> file names. These folks have
114     perhaps not heard about <directive 
115     module="mod_include">XBitHack</directive>. The thing to
116     keep in mind is that, by doing this, you're requiring that
117     Apache read through every single file that it sends out to
118     clients, even if they don't contain any SSI directives. This
119     can slow things down quite a bit, and is not a good idea.</p>
120
121     <p>Of course, on Windows, there is no such thing as an execute
122     bit to set, so that limits your options a little.</p>
123
124     <p>In its default configuration, Apache does not send the last
125     modified date or content length HTTP headers on SSI pages,
126     because these values are difficult to calculate for dynamic
127     content. This can prevent your document from being cached, and
128     result in slower perceived client performance. There are two
129     ways to solve this:</p>
130
131     <ol>
132       <li>Use the <code>XBitHack Full</code> configuration. This
133       tells Apache to determine the last modified date by looking
134       only at the date of the originally requested file, ignoring
135       the modification date of any included files.</li>
136
137       <li>Use the directives provided by 
138       <module>mod_expires</module> to set an explicit expiration
139       time on your files, thereby letting browsers and proxies
140       know that it is acceptable to cache them.</li>
141     </ol>
142 </section>
143
144 <section id="basic"><title>Basic SSI directives</title>
145
146     <p>SSI directives have the following syntax:</p>
147 <example>
148         &lt;!--#element attribute=value attribute=value ... --&gt;
149 </example>
150
151     <p>It is formatted like an HTML comment, so if you don't have
152     SSI correctly enabled, the browser will ignore it, but it will
153     still be visible in the HTML source. If you have SSI correctly
154     configured, the directive will be replaced with its
155     results.</p>
156
157     <p>The element can be one of a number of things, and we'll talk
158     some more about most of these in the next installment of this
159     series. For now, here are some examples of what you can do with
160     SSI</p>
161
162 <section id="todaysdate"><title>Today's date</title>
163
164 <example>
165         &lt;!--#echo var="DATE_LOCAL" --&gt;
166 </example>
167
168     <p>The <code>echo</code> element just spits out the value of a
169     variable. There are a number of standard variables, which
170     include the whole set of environment variables that are
171     available to CGI programs. Also, you can define your own
172     variables with the <code>set</code> element.</p>
173
174     <p>If you don't like the format in which the date gets printed,
175     you can use the <code>config</code> element, with a
176     <code>timefmt</code> attribute, to modify that formatting.</p>
177
178 <example>
179         &lt;!--#config timefmt="%A %B %d, %Y" --&gt;<br />
180         Today is &lt;!--#echo var="DATE_LOCAL" --&gt;
181 </example>
182 </section>
183
184 <section id="lastmodified"><title>Modification date of the file</title>
185
186 <example>
187         This document last modified &lt;!--#flastmod file="index.html" --&gt;
188 </example>
189
190     <p>This element is also subject to <code>timefmt</code> format
191     configurations.</p>
192 </section>
193
194 <section id="cgi"><title>Including the results of a CGI program</title>
195
196     <p>This is one of the more common uses of SSI - to output the
197     results of a CGI program, such as everybody's favorite, a ``hit
198     counter.''</p>
199
200 <example>
201         &lt;!--#include virtual="/cgi-bin/counter.pl" --&gt;
202 </example>
203
204 </section>
205 </section>
206
207 <section id="additionalexamples">
208 <title>Additional examples</title>
209
210     <p>Following are some specific examples of things you can do in
211     your HTML documents with SSI.</p>
212
213 <section id="docmodified"><title>When was this document
214 modified?</title>
215
216     <p>Earlier, we mentioned that you could use SSI to inform the
217     user when the document was most recently modified. However, the
218     actual method for doing that was left somewhat in question. The
219     following code, placed in your HTML document, will put such a
220     time stamp on your page. Of course, you will have to have SSI
221     correctly enabled, as discussed above.</p>
222 <example>
223         &lt;!--#config timefmt="%A %B %d, %Y" --&gt;<br />
224         This file last modified &lt;!--#flastmod file="ssi.shtml" --&gt;
225 </example>
226
227     <p>Of course, you will need to replace the
228     <code>ssi.shtml</code> with the actual name of the file that
229     you're referring to. This can be inconvenient if you're just
230     looking for a generic piece of code that you can paste into any
231     file, so you probably want to use the
232     <code>LAST_MODIFIED</code> variable instead:</p>
233 <example>
234         &lt;!--#config timefmt="%D" --&gt;<br />
235         This file last modified &lt;!--#echo var="LAST_MODIFIED" --&gt;
236 </example>
237
238     <p>For more details on the <code>timefmt</code> format, go to
239     your favorite search site and look for <code>strftime</code>. The
240     syntax is the same.</p>
241 </section>
242
243 <section id="standard-footer">
244 <title>Including a standard footer</title>
245
246     <p>If you are managing any site that is more than a few pages,
247     you may find that making changes to all those pages can be a
248     real pain, particularly if you are trying to maintain some kind
249     of standard look across all those pages.</p>
250
251     <p>Using an include file for a header and/or a footer can
252     reduce the burden of these updates. You just have to make one
253     footer file, and then include it into each page with the
254     <code>include</code> SSI command. The <code>include</code>
255     element can determine what file to include with either the
256     <code>file</code> attribute, or the <code>virtual</code>
257     attribute. The <code>file</code> attribute is a file path,
258     <em>relative to the current directory</em>. That means that it
259     cannot be an absolute file path (starting with /), nor can it
260     contain ../ as part of that path. The <code>virtual</code>
261     attribute is probably more useful, and should specify a URL
262     relative to the document being served. It can start with a /,
263     but must be on the same server as the file being served.</p>
264 <example>
265         &lt;!--#include virtual="/footer.html" --&gt;
266 </example>
267
268     <p>I'll frequently combine the last two things, putting a
269     <code>LAST_MODIFIED</code> directive inside a footer file to be
270     included. SSI directives can be contained in the included file,
271     and includes can be nested - that is, the included file can
272     include another file, and so on.</p>
273 </section>
274
275 </section>
276
277 <section id="config">
278 <title>What else can I config?</title>
279
280     <p>In addition to being able to <code>config</code> the time
281     format, you can also <code>config</code> two other things.</p>
282
283     <p>Usually, when something goes wrong with your SSI directive,
284     you get the message</p>
285 <example>
286         [an error occurred while processing this directive]
287 </example>
288
289     <p>If you want to change that message to something else, you
290     can do so with the <code>errmsg</code> attribute to the
291     <code>config</code> element:</p>
292 <example>
293         &lt;!--#config errmsg="[It appears that you don't know how to use SSI]" --&gt;
294 </example>
295
296     <p>Hopefully, end users will never see this message, because
297     you will have resolved all the problems with your SSI
298     directives before your site goes live. (Right?)</p>
299
300     <p>And you can <code>config</code> the format in which file
301     sizes are returned with the <code>sizefmt</code> attribute. You
302     can specify <code>bytes</code> for a full count in bytes, or
303     <code>abbrev</code> for an abbreviated number in Kb or Mb, as
304     appropriate.</p>
305     </section>
306
307 <section id="exec">
308     <title>Executing commands</title>
309
310     <p>I expect that I'll have an article some time in the coming
311     months about using SSI with small CGI programs. For now, here's
312     something else that you can do with the <code>exec</code>
313     element. You can actually have SSI execute a command using the
314     shell (<code>/bin/sh</code>, to be precise - or the DOS shell,
315     if you're on Win32). The following, for example, will give you
316     a directory listing.</p>
317 <example>
318         &lt;pre&gt;<br />
319         &lt;!--#exec cmd="ls" --&gt;<br />
320         &lt;/pre&gt;
321 </example>
322
323     <p>or, on Windows</p>
324 <example>
325         &lt;pre&gt;<br />
326         &lt;!--#exec cmd="dir" --&gt;<br />
327         &lt;/pre&gt;
328 </example>
329
330     <p>You might notice some strange formatting with this directive
331     on Windows, because the output from <code>dir</code> contains
332     the string ``&lt;<code>dir</code>&gt;'' in it, which confuses
333     browsers.</p>
334
335     <p>Note that this feature is exceedingly dangerous, as it will
336     execute whatever code happens to be embedded in the
337     <code>exec</code> tag. If you have any situation where users
338     can edit content on your web pages, such as with a
339     ``guestbook'', for example, make sure that you have this
340     feature disabled. You can allow SSI, but not the
341     <code>exec</code> feature, with the <code>IncludesNOEXEC</code>
342     argument to the <code>Options</code> directive.</p>
343     </section>
344
345 <section id="advanced">
346 <title>Advanced SSI techniques</title>
347
348     <p>In addition to spitting out content, Apache SSI gives you
349     the option of setting variables, and using those variables in
350     comparisons and conditionals.</p>
351
352 <section id="caveat"><title>Caveat</title>
353
354     <p>Most of the features discussed in this article are only
355     available to you if you are running Apache 1.2 or later. Of
356     course, if you are not running Apache 1.2 or later, you need to
357     upgrade immediately, if not sooner. Go on. Do it now. We'll
358     wait.</p>
359 </section>
360
361 <section id="variables"><title>Setting variables</title>
362
363     <p>Using the <code>set</code> directive, you can set variables
364     for later use. We'll need this later in the discussion, so
365     we'll talk about it here. The syntax of this is as follows:</p>
366 <example>
367         &lt;!--#set var="name" value="Rich" --&gt;
368 </example>
369
370     <p>In addition to merely setting values literally like that,
371     you can use any other variable, including, for example,
372     environment variables, or some of the variables we discussed in
373     the last article (like <code>LAST_MODIFIED</code>, for example)
374     to give values to your variables. You will specify that
375     something is a variable, rather than a literal string, by using
376     the dollar sign ($) before the name of the variable.</p>
377 <example>
378         &lt;!--#set var="modified" value="$LAST_MODIFIED" --&gt;
379 </example>
380
381     <p>To put a literal dollar sign into the value of your
382     variable, you need to escape the dollar sign with a
383     backslash.</p>
384 <example>
385         &lt;!--#set var="cost" value="\$100" --&gt;
386 </example>
387
388     <p>Finally, if you want to put a variable in the midst of a
389     longer string, and there's a chance that the name of the
390     variable will run up against some other characters, and thus be
391     confused with those characters, you can place the name of the
392     variable in braces, to remove this confusion. (It's hard to
393     come up with a really good example of this, but hopefully
394     you'll get the point.)</p>
395 <example>
396         &lt;!--#set var="date" value="${DATE_LOCAL}_${DATE_GMT}" --&gt;
397 </example>
398 </section>
399
400 <section id="conditional">
401 <title>Conditional expressions</title>
402
403     <p>Now that we have variables, and are able to set and compare
404     their values, we can use them to express conditionals. This
405     lets SSI be a tiny programming language of sorts.
406     <module>mod_include</module> provides an <code>if</code>,
407     <code>elif</code>, <code>else</code>, <code>endif</code>
408     structure for building conditional statements. This allows you
409     to effectively generate multiple logical pages out of one
410     actual page.</p>
411
412     <p>The structure of this conditional construct is:</p>
413 <example>
414     &lt;!--#if expr="test_condition" --&gt;<br />
415     &lt;!--#elif expr="test_condition" --&gt;<br />
416     &lt;!--#else --&gt;<br />
417     &lt;!--#endif --&gt;
418 </example>
419
420     <p>A <em>test_condition</em> can be any sort of logical
421     comparison - either comparing values to one another, or testing
422     the ``truth'' of a particular value. (A given string is true if
423     it is nonempty.) For a full list of the comparison operators
424     available to you, see the <module>mod_include</module>
425     documentation. Here are some examples of how one might use this
426     construct.</p>
427
428     <p>In your configuration file, you could put the following
429     line:</p>
430 <example>
431         BrowserMatchNoCase macintosh Mac<br />
432         BrowserMatchNoCase MSIE InternetExplorer
433 </example>
434
435     <p>This will set environment variables ``Mac'' and
436     ``InternetExplorer'' to true, if the client is running Internet
437     Explorer on a Macintosh.</p>
438
439     <p>Then, in your SSI-enabled document, you might do the
440     following:</p>
441 <example>
442         &lt;!--#if expr="${Mac} &amp;&amp; ${InternetExplorer}" --&gt;<br />
443         Apologetic text goes here<br />
444         &lt;!--#else --&gt;<br />
445         Cool JavaScript code goes here<br />
446         &lt;!--#endif --&gt;
447 </example>
448
449     <p>Not that I have anything against IE on Macs - I just
450     struggled for a few hours last week trying to get some
451     JavaScript working on IE on a Mac, when it was working
452     everywhere else. The above was the interim workaround.</p>
453
454     <p>Any other variable (either ones that you define, or normal
455     environment variables) can be used in conditional statements.
456     With Apache's ability to set environment variables with the
457     <code>SetEnvIf</code> directives, and other related directives,
458     this functionality can let you do some pretty involved dynamic
459     stuff without ever resorting to CGI.</p>
460 </section>
461 </section>
462
463 <section id="conclusion"><title>Conclusion</title>
464
465     <p>SSI is certainly not a replacement for CGI, or other
466     technologies used for generating dynamic web pages. But it is a
467     great way to add small amounts of dynamic content to pages,
468     without doing a lot of extra work.</p>
469 </section>
470
471 </manualpage>