| <?xml version='1.0' encoding='UTF-8' ?> |
| <!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd"> |
| <?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?> |
| <!-- $LastChangedRevision$ --> |
| |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| <manualpage metafile="ssi.xml.meta"> |
| <parentdocument href="./">How-To / Tutorials</parentdocument> |
| |
| <title>Apache httpd Tutorial: Introduction to Server Side Includes</title> |
| |
| <summary> |
| <p>Server-side includes provide a means to add dynamic content to |
| existing HTML documents.</p> |
| </summary> |
| |
| <section id="related"><title>Introduction</title> |
| <related> |
| <modulelist> |
| <module>mod_include</module> |
| <module>mod_cgi</module> |
| <module>mod_expires</module> |
| </modulelist> |
| |
| <directivelist> |
| <directive module="core">Options</directive> |
| <directive module="mod_include">XBitHack</directive> |
| <directive module="mod_mime">AddType</directive> |
| <directive module="core">SetOutputFilter</directive> |
| <directive module="mod_setenvif">BrowserMatchNoCase</directive> |
| </directivelist> |
| </related> |
| |
| <p>This article deals with Server Side Includes, usually called |
| simply SSI. In this article, I'll talk about configuring your |
| server to permit SSI, and introduce some basic SSI techniques |
| for adding dynamic content to your existing HTML pages.</p> |
| |
| <p>In the latter part of the article, we'll talk about some of |
| the somewhat more advanced things that can be done with SSI, |
| such as conditional statements in your SSI directives.</p> |
| |
| </section> |
| |
| <section id="what"><title>What are SSI?</title> |
| |
| <p>SSI (Server Side Includes) are directives that are placed in |
| HTML pages, and evaluated on the server while the pages are |
| being served. They let you add dynamically generated content to |
| an existing HTML page, without having to serve the entire page |
| via a CGI program, or other dynamic technology.</p> |
| |
| <p>For example, you might place a directive into an existing HTML |
| page, such as:</p> |
| |
| <example> |
| <!--#echo var="DATE_LOCAL" --> |
| </example> |
| |
| <p>And, when the page is served, this fragment will be evaluated and replaced with its value:</p> |
| |
| <example> |
| Tuesday, 15-Jan-2013 19:28:54 EST |
| </example> |
| |
| <p>The decision of when to use SSI, and when to have your page |
| entirely generated by some program, is usually a matter of how |
| much of the page is static, and how much needs to be |
| recalculated every time the page is served. SSI is a great way |
| to add small pieces of information, such as the current time - shown |
| above. But if a majority of your page is being generated at the time |
| that it is served, you need to look for some other solution.</p> |
| </section> |
| |
| <section id="configuring"> |
| <title>Configuring your server to permit SSI</title> |
| |
| <p>To permit SSI on your server, you must have the following |
| directive either in your <code>httpd.conf</code> file, or in a |
| <code>.htaccess</code> file:</p> |
| <highlight language="config"> |
| Options +Includes |
| </highlight> |
| |
| <p>This tells Apache that you want to permit files to be parsed |
| for SSI directives. Note that most configurations contain |
| multiple <directive module="core">Options</directive> directives |
| that can override each other. You will probably need to apply the |
| <code>Options</code> to the specific directory where you want SSI |
| enabled in order to assure that it gets evaluated last.</p> |
| |
| <p>Not just any file is parsed for SSI directives. You have to |
| tell Apache which files should be parsed. There are two ways to |
| do this. You can tell Apache to parse any file with a |
| particular file extension, such as <code>.shtml</code>, with |
| the following directives:</p> |
| <highlight language="config"> |
| AddType text/html .shtml |
| AddOutputFilter INCLUDES .shtml |
| </highlight> |
| |
| <p>One disadvantage to this approach is that if you wanted to |
| add SSI directives to an existing page, you would have to |
| change the name of that page, and all links to that page, in |
| order to give it a <code>.shtml</code> extension, so that those |
| directives would be executed.</p> |
| |
| <p>The other method is to use the <directive |
| module="mod_include">XBitHack</directive> directive:</p> |
| <highlight language="config"> |
| XBitHack on |
| </highlight> |
| |
| <p><directive module="mod_include">XBitHack</directive> |
| tells Apache to parse files for SSI |
| directives if they have the execute bit set. So, to add SSI |
| directives to an existing page, rather than having to change |
| the file name, you would just need to make the file executable |
| using <code>chmod</code>.</p> |
| <example> |
| chmod +x pagename.html |
| </example> |
| |
| <p>A brief comment about what not to do. You'll occasionally |
| see people recommending that you just tell Apache to parse all |
| <code>.html</code> files for SSI, so that you don't have to |
| mess with <code>.shtml</code> file names. These folks have |
| perhaps not heard about <directive |
| module="mod_include">XBitHack</directive>. The thing to |
| keep in mind is that, by doing this, you're requiring that |
| Apache read through every single file that it sends out to |
| clients, even if they don't contain any SSI directives. This |
| can slow things down quite a bit, and is not a good idea.</p> |
| |
| <p>Of course, on Windows, there is no such thing as an execute |
| bit to set, so that limits your options a little.</p> |
| |
| <p>In its default configuration, Apache does not send the last |
| modified date or content length HTTP headers on SSI pages, |
| because these values are difficult to calculate for dynamic |
| content. This can prevent your document from being cached, and |
| result in slower perceived client performance. There are two |
| ways to solve this:</p> |
| |
| <ol> |
| <li>Use the <code>XBitHack Full</code> configuration. This |
| tells Apache to determine the last modified date by looking |
| only at the date of the originally requested file, ignoring |
| the modification date of any included files.</li> |
| |
| <li>Use the directives provided by |
| <module>mod_expires</module> to set an explicit expiration |
| time on your files, thereby letting browsers and proxies |
| know that it is acceptable to cache them.</li> |
| </ol> |
| </section> |
| |
| <section id="basic"><title>Basic SSI directives</title> |
| |
| <p>SSI directives have the following syntax:</p> |
| <example> |
| <!--#function attribute=value attribute=value ... --> |
| </example> |
| |
| <p>It is formatted like an HTML comment, so if you don't have |
| SSI correctly enabled, the browser will ignore it, but it will |
| still be visible in the HTML source. If you have SSI correctly |
| configured, the directive will be replaced with its |
| results.</p> |
| |
| <p>The function can be one of a number of things, and we'll talk |
| some more about most of these in the next installment of this |
| series. For now, here are some examples of what you can do with |
| SSI</p> |
| |
| <section id="todaysdate"><title>Today's date</title> |
| |
| <example> |
| <!--#echo var="DATE_LOCAL" --> |
| </example> |
| |
| <p>The <code>echo</code> function just spits out the value of a |
| variable. There are a number of standard variables, which |
| include the whole set of environment variables that are |
| available to CGI programs. Also, you can define your own |
| variables with the <code>set</code> function.</p> |
| |
| <p>If you don't like the format in which the date gets printed, |
| you can use the <code>config</code> function, with a |
| <code>timefmt</code> attribute, to modify that formatting.</p> |
| |
| <example> |
| <!--#config timefmt="%A %B %d, %Y" --><br /> |
| Today is <!--#echo var="DATE_LOCAL" --> |
| </example> |
| </section> |
| |
| <section id="lastmodified"><title>Modification date of the file</title> |
| |
| <example> |
| This document last modified <!--#flastmod file="index.html" --> |
| </example> |
| |
| <p>This function is also subject to <code>timefmt</code> format |
| configurations.</p> |
| </section> |
| |
| <section id="cgi"><title>Including the results of a CGI program</title> |
| |
| <p>This is one of the more common uses of SSI - to output the |
| results of a CGI program, such as everybody's favorite, a ``hit |
| counter.''</p> |
| |
| <example> |
| <!--#include virtual="/cgi-bin/counter.pl" --> |
| </example> |
| |
| </section> |
| </section> |
| |
| <section id="additionalexamples"> |
| <title>Additional examples</title> |
| |
| <p>Following are some specific examples of things you can do in |
| your HTML documents with SSI.</p> |
| |
| <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> |
| <!--#config timefmt="%A %B %d, %Y" --><br /> |
| This file last modified <!--#flastmod file="ssi.shtml" --> |
| </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> |
| <!--#config timefmt="%D" --><br /> |
| This file last modified <!--#echo var="LAST_MODIFIED" --> |
| </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="standard-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> |
| function 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> |
| <!--#include virtual="/footer.html" --> |
| </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> function:</p> |
| <example> |
| <!--#config errmsg="[It appears that you don't know how to use SSI]" --> |
| </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> |
| function. 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> |
| <pre><br /> |
| <!--#exec cmd="ls" --><br /> |
| </pre> |
| </example> |
| |
| <p>or, on Windows</p> |
| <example> |
| <pre><br /> |
| <!--#exec cmd="dir" --><br /> |
| </pre> |
| </example> |
| |
| <p>You might notice some strange formatting with this directive |
| on Windows, because the output from <code>dir</code> contains |
| the string ``<<code>dir</code>>'' 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="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> |
| <!--#set var="name" value="Rich" --> |
| </example> |
| |
| <p>In addition to merely setting values literally like that, you |
| can use any other variable, including <a |
| href="../env.html">environment variables</a> or the variables |
| discussed above (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> <!--#set var="modified" value="$LAST_MODIFIED" --> |
| </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> |
| <!--#set var="cost" value="\$100" --> |
| </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> |
| <!--#set var="date" value="${DATE_LOCAL}_${DATE_GMT}" --> |
| </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. |
| <module>mod_include</module> 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> |
| <!--#if expr="test_condition" --><br /> |
| <!--#elif expr="test_condition" --><br /> |
| <!--#else --><br /> |
| <!--#endif --> |
| </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 <module>mod_include</module> |
| documentation.</p> |
| |
| <p>For example, if you wish to customize the text on your web page |
| based on the time of day, you could use the following recipe, placed |
| in the HTML page:</p> |
| |
| <example> |
| Good |
| <!--#if expr="%{TIME_HOUR} <12" --><br /> |
| morning!<br /> |
| <!--#else --><br /> |
| afternoon!<br /> |
| <!--#endif --><br /> |
| </example> |
| |
| <p>Any other variable (either ones that you define, or normal |
| environment variables) can be used in conditional statements. |
| See <a href="../expr.html">Expressions in Apache HTTP Server</a> for |
| more information on the expression evaluation engine.</p> |
| |
| <p>With Apache's ability to set environment variables with the |
| <code>SetEnvIf</code> directives, and other related directives, |
| this functionality can let you do a wide variety of dynamic content |
| on the server side without resorting a full web application.</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> |