Server Side Includes (SSI) provides a simple way to embed executable code into a web page. The advantages of SSI are that it is simple to use and easy to learn, and sometimes simplicity is its own reward. The main drawback of SSI is that because of its simplicity, it is limited in what it can do. 
SSI is not CGI (see Chapter 7) ”that is, it is not a program that is executed to generate HTML text, so one needn't be a Perl hacker to use it. Rather, SSI is a collection of directives that can be embedded in an HTML file and processed by Apache. A directive has this form:
<!--# directive param1 =" value1 " param2 =" value2 "... -->
which is simply an HTML comment with a " # " escape to SSI.
Among other things, SSI allows you to
SSI is not intended to be used to perform sophisticated programming tasks . It is mainly used to do simple includes (thus the name ) of basic information. For anything more complex, other things you learn about elsewhere in this book are better choices. But you don't need a cannon to kill a gnat, so SSI has some useful applications if gnats are what need to be swatted.
9.1.1 How It Works
As Figure 9.1 shows, when the user requests a file that ends in the .shtml extension, the Apache server runs the text through the Server Side Includes preprocessor. This processes the SSIs, converting all SSI directives into the appropriate text. The resulting text is then sent back to the browser.
Figure 9.1. How SSI works
If you installed Linux as suggested in Chapter 2, Apache should already be configured to support SSI. To check, make sure these two lines of the Apache configuration file ( /etc/httpd/conf/httpd.conf ) are uncommented:
AddType text/html .shtml AddHandler server-parsed .shtml
These directives add a type of file with the suffix .shtml , whose content is to be treated as HTML and whose file is to be server-parsed, or preprocessed, by the Apache server before being served up. All files with the .shtml suffix are preprocessed, so don't name normal non-SSI HTML files with the .shtml extension ”that only slows down the webserver , because it will preprocess files that do not require it.
As always, if you change the Apache configuration file, restart the server.
SSI is relatively simple to learn, and we can give a short tutorial of its important aspects in just a few pages. SSI consists of a few directives, which implement its functionality.
The echo directive instructs the server to insert ( echo ) the value of a variable at that point in the HTML file. It has this syntax:
<!--#echo var=" variable "-->
The variables that can be echoed are
Let's show an example. First, make a directory for the SSI work, giving it the proper permissions:
$ cd /var/www/html $ mkdir ssi $ chmod a+rx ssi $ cd ssi
Call this example echo.shtml and make sure it is readable (with chmod a+r echo.shtml ”be sure to do this for all the examples in this chapter). Put the following code in it:
<html> <head> <title>Server Side Includes: echo Directive</title> </head> <body bgcolor="#ffffff"> <h1>Examples of the echo directive</h1> Filename: <b><!--#echo var="DOCUMENT_NAME"--></b> <br> URI: <b><!--#echo var="DOCUMENT_URI"--></b> <br> Local time: <b><!--#echo var="DATE_LOCAL"--></b> <br> GMT: <b><!--#echo var="DATE_GMT"--></b> <br> Last modified: <b><!--#echo var="LAST_MODIFIED"--></b> </body> </html>
There are several echo directives, which result in a web page like Figure 9.2. To see for yourself, go to one of these URLs: http://localhost/ssi/echo.shtml or www.opensourcewebbook.com/ssi/echo.shtml.
Figure 9.2. echo SSI directive
The include directive allows you to include the contents of another file in the current document. This is convenient if you want every page to have the same header and/or footer. Let's say we have this HTML in the file header.html :
<html> <head> <title>Server Side Includes: include Directive</title> </head> <body bgcolor="#ffffff"> <h1>You are at www.opensourcewebbook.com</h1>
and this HTML in the file footer.shtml :
<hr> <a href="http://www.opensourcewebbook.com/"> http://www.opensourcewebbook.com/</a> <br> Date: <!--#echo var="DATE_LOCAL"--> </body> </html>
We can wrap header and footer HTML around any HTML ( include.shtml ):
<!--#include file="header.html"--> Here is the stuff between what was included. <!--#include file="footer.shtml"-->
Load this page by going to one of these URLs: http://localhost/ssi/include.shtml or www.opensourcewebbook.com/ssi/include.shtml. The result is Figure 9.3. Notice that the footer filename, footer.shtml , ends in .shtml , which caused it to be preprocessed as well, showing the local date.
Figure 9.3. include SSI directive
fsize and flastmod Directives
The fsize directive inserts the size of the file specified. This is its syntax:
<!--#fsize file=" filename "-->
By default, the size is rounded to the next kilobyte. To change the output format, use the config directive:
The flastmod directive inserts the last modification date of the specified file. Its syntax is:
<!--#flastmod file=" filename "-->
As an example, put this code into file.shtml :
<html> <head> <title>Server Side Includes: fsize and flastmod Directives</title> </head> <body bgcolor="#ffffff"> <h1>Examples of the fsize and flastmod directives</h1> The file <tt>echo.shtml</tt> was last modified <!--#flastmod file="echo.shtml"--> <br> Its size is <!--#fsize file="echo.shtml"--> bytes. <br> <!--#config sizefmt="bytes"--> The size can also be displayed as <!--#fsize file="echo.shtml"--> bytes. </body> </html>
Then go to one of these URLs ” http://localhost/ssi/file.shtml or www.opensourcewebbook.com/ssi/file.shtml ”and get Figure 9.4.
Figure 9.4. fsize and flastmod SSI directives
The exec directive inserts the output of a command or CGI script. This is useful for executing a shell command or CGI script via an SSI directive:
<!--#exec cmd=" command "--> <!--#exec cgi=" cgiscript "-->
This example can be found in exec.shtml :
<html> <head> <title>Server Side Includes: exec Directive</title> </head> <body bgcolor="#ffffff"> <h1>Examples of the exec directive</h1> Here is the disk usage summary for <tt>/home</tt>: <pre> <!--#exec cmd="/bin/df /home"--> </pre> </body> </html>
You can view this by going to either http://localhost/ssi/exec.shtml or www.opensourcewebbook.com/ssi/exec.shtml. This results in Figure 9.5.
Figure 9.5. exec SSI directive
The config directive can be used to change the configuration of SSI output. If an error occurs during the processing of an SSI directive (for instance, including a file that does not exist), the following default error output is displayed:
[an error occurred while processing this directive]
This output can be changed with the config directive:
<!--#config errmsg="Error, contact email@example.com"-->
Earlier in this section, we changed the default output of the fsize directive. The default behavior of many of the directives can be similarly changed. For instance, the time format can also be changed in a number of ways:
<!--#config timefmt=" format "-->
If you want to know more about all the possible configurations of the timefmt directive, check out man strftime .
The set directive allows us to create variables. Its syntax is:
<!--#set var=" varname " value=" varvalue "-->
Here is an example:
<!--#set var="name" value="Ron"--> Name is: <!--#echo var="name"-->
This SSI code produces the text " Name is: Ron ."
Simple conditional expressions are available with the if / elsif / else / endif . This is the syntax:
<!--#if expr=" expression1 "--> text generated if expression1 is true <!--#elsif expr=" expression2 "--> text generated if expression2 is true <!--#else--> text generated if expression1 is false and expression2 is false <!--#endif-->
Here is a simple example that tests whether the $DATE_LOCAL_ SSI variable contains the text "AM" (if so, it is morning):
<!--#config timefmt="%p" --> <!--#if expr="$DATE_LOCAL = /AM/" --> <p>Good Morning!</p> <!--#endif -->
First, the time format is configured to display " AM " or " PM ". Then, the variable $DATE_LOCAL is checked to see whether it matches the regular expression /AM/ , and if so, the expression is true. We could have checked to see whether the variable did not match the regular expression /PM/ with:
<!--#if expr="$DATE_LOCAL != /PM/" -->