Server Parsed Documents

(Server Side Includes)

Overview
Server Side Includes (SSI) are a powerful way of embedding dynamic content in your web pages. SSI documents are parsed by the server before being sent to the client. This allows you to embed SSI tags within HTML pages which are expanded by the server before being sent to the client. The Zeus server has an exceptionally flexible SSI engine which can expand SSI tags, regardless of how the HTML was generated. The Zeus SSI engine is optimised so SSI documents do not degrade the performance of the server.

SSI enabled HTML files require a MIME type of text/x-server-parsed-html which by default is mapped on to the .shtml file extension. Any output generated which has a MIME type of text/x-server-parsed-html will be parsed by the server, whether it is from a static file, a CGI script or a Java Servelet.

SSI Directives
SSI Directives are special values in your HTML files which the server will look for to parse. In order not to interfere with your HTML design the SSI directives are included in HTML comments. HTML comments have a special starting tag "<!-->" and ending tag "-->"

<!-- HTML Comments look like this -->

SSI directives contain a command, and a number of parameters and arguments. So they take the form :

<!--#command parameter(s)="argument"-->

The #echo Command
The echo command makes available the set of environment variables sent to CGI programs. Using this command you can send these variables back to the user without having to resort to CGI programs. The echo command is followed by the parameter and argument values "var=environment variable". For a full list of environment variables see the CGI documentation.

Example : Output Environmental Variables

The following SHTML file displays a selection of SSI variables. <html> <head> <title>SSI Variables</title> </head> <h1>SSI Environment Variables</h1> <pre> SERVER SOFTWARE : <!--#echo var="SERVER_SOFTWARE"--> GATEWAY_INTERFACE : <!--#echo var="GATEWAY_INTERFACE"--> SERVER_PROTOCOL : <!--#echo var="SERVER_PROTOCOL"--> SERVER_NAME : <!--#echo var="SERVER_NAME"--> SERVER_PORT : <!--#echo var="SERVER_PORT"--> REQUEST_METHOD : <!--#echo var="REQUEST_METHOD"--> REMOTE_HOST : <!--#echo var="REMOTE_HOST"--> HTTP_USER_AGENT : <!--#echo var="HTTP_USER_AGENT"--> DATE_LOCAL : <!--#echo var="DATE_LOCAL"--> DATE_GMT : <!--#echo var="DATE_GMT"--> </pre> </body> </html>

Will result in something similar to the following being sent to the client:

<html> <head> <title>SSI Variables</title> </head> <h1> SSI Environment Variables </h1> <pre> SERVER SOFTWARE : Zeus/3.0 GATEWAY_INTERFACE : CGI/1.1 SERVER_PROTOCOL : HTTP/1.0 SERVER_NAME : www.zeus.co.uk SERVER_PORT : 80 REQUEST_METHOD : GET REMOTE_HOST : pc203.zeus.co.uk REMOTE_ADDR : 10.0.0.14 HTTP_USER_AGENT : Mozilla/4.0b5 [en] (Win95; I) DATE_LOCAL : 06:12:16 PM 06/02/97 DATE_GMT : 05:12:16 PM 06/02/97 </pre> </body> </html>

The #include Command
Managing a complex web site can be a considerable task, particularly if you wish to maintain a common look and feel through out all the pages. Including a common footer or navigation bar to your site helps your visitors identify where they are and helps them move quickly to the information they need. However if you then need to change the footer, you would need to update every page on your site. By using SSI to insert a file at the end of each of your pages you would only need to change one file.

The SSI directive include allows us to merge other files into our HTML pages. It is followed by the parameters file or virtual. file specifies a filename relative to the current directory, virtual can specify a relative filename or an absolute URL within the whole document root for the virtual server.

<!--#include virtual="/dir/filename"-->

<!--#include file="filename"-->

Example : Including a footer.

Going back to our original scenario, displaying a common footer for all your documents is now easy. Each page on your server will reference the same document via the include SSI directive.

A .shtml file :

<HTML> <HEAD><TITLE>SSI Test</TITLE></HEAD> <BODY> <P> This is my text from index.shtml <P> <!--#include virtual="/includes/footer.html"--> </BODY> </HTML> The /includes/footer.html file : Please email <a href="mailto:harry@mycompany.co.uk"> Harry</a> for more details on our products. Will result in the following output being set to the client: <HTML> <HEAD><TITLE>SSI Test</TITLE></HEAD> <BODY> <P> This is my text from index.shtml <P> Please email <a href="mailto:harry@mycompany.co.uk"> Harry</a> for more details on our products. </BODY> </HTML>

The #fsize and #flastmod Commands
The #fsize command will insert the size of the specified file into the document. There are occasions when you may want a visitor to your web site to download information which could be substantial in size. In these cases it is polite to include the file size in the document so the visitor can estimate how long the download will take. You could include the file size directly in the HTML, but if the files were to change you would need to update the HTML pages as well. The #fsize command allows you to include the size of files which may change regularly.

The #fsize command is followed by the parameters file or virtual with the same meaning as the #include command described above. Each parameter take a file location as an argument.

The #flastmod command works in the same manner returning the data the file was last modified.

By using the recursive nature of the Zeus SSI engine it would be possible to generate a file listing from a CGI script, but obtain the file sizes and modification dates via the SSI commands.

Example : File Size of Downloads

A University publishes hourly satellite pictures on the web. Due to the difference in time and weather, combined with the effect of the compression code, the size can alter considerably. Using the #fsize and #flastmod commands the web page always has the correct information displayed.

The .shtml file:

<html> <head> <title>Pictures</title> </head> <body> <h1>Satellite Pictures</h1> Please download the <a href="picture.jpg">picture, it is only <!--#fsize file="picture.jpg"--> in size. <br> Last updated on <!--#flastmod file="picture.jpg"--> </body> </html> Will result in something similar to the following being sent to the client: <html> <head> <title>Pictures</title> </head> <body> <h1>Satellite Pictures</h1> Please download the picture, it is only 4.8Kb in size. Last updated on 05:52:21 PM 06/03/97 </body> </html>

The #config Command
The #config command can be used to change the output format of certain SSI directives, specifically those which return a time / date or a filesize. This allows you to use a more understandable format than the defaults for your particular application.

The #config command takes two parameters, timefmt to modify the date and time formats, and sizefmt to modify the file size format.

The timefmt parameter takes a free form text string of tokens as an argument in a similar vein to the UNIX library call strftime. These tokens are expanded by the server to produce the desired time format.

%aDay : abbreviated Mon, Tue, Wed
%ADayMonday, Tuesday
%bMonth : abbreviated (%h) Jan, Feb, Mar
%BMonthJanuary, February
%CYear : Without Century "00" - "99"
%dDay of Month"01" - "31"
%DDate : mm/dd/yy"01/01/00" - "12/31/99"
%eDay of Month : Single figures "1" - "31"
%hMonth : abbreviated (%b) Jan, Feb, Mar
%HHour of Day : 24 hour clock "00" - "23"
%IHour of Day "01" - "12"
%jJulian Day of Year "001" - "366"
%mMonth of Year"01" - "12"
%MMinute"00" - "59"
%nNewline character
%pAM or PM"AM" | "PM"
%rTime in %I:%M:%S %p "00:00:00 am" - "12:59:59 pm"
%RTime in %H:%M"00:00" - "23:59"
%SSeconds "00" - "61"
%tTab character
%TTime in %H:%M:%S"00:00:00" - "23:59:59"
%uNumbered Day of the Week : Starting with Monday = 1 "1" - "7"
%wNumbered Day of the Week : Starting with Sunday = 0 "0" - "6"
%yYear : Without Century "00" - "99"
%YYear "0000" - "9999"
%ZTime Zone"GMT", "BST", "CST" ..
%%Percentage Character
Sophisticated time and date information can be constructed using these tokens. Additional text can also be included in the string, allowing additional explanation.

The sizefmt parameter takes an argument of either bytes or abbrev. The bytes value will cause all filesize information to be displayed exactly in bytes, while the abbrev value will display an approximate value with the units appended (Kb, Mb, Gb).

Example : Formatting The Date

Displaying a date on the welcome page for your site is quite a common requirement, but you probably don't want to got to all the trouble of writing a CGI script to display the whole page. You also probably don't want to use the default time format either. Using #config and the SSI environment variable date_local we can easily display the time in the way we want.

The .shtml file:

<html> <head> <title>SSI Date Test</title> </head> <body> The current time is : <b><!--#echo var="DATE_LOCAL"--></b> <br> But the time looks nicer this way : <!--#config timefmt="It's <b>%A</b> and the time is <b>%I:%M %p</b>!"--> <!--#echo var="DATE_LOCAL"--> <hr> </body> </html> Will result in something similar to the following being sent to the client: <html> <head> <title>SSI Date Test</title> </head> <body> The current time is : <b>08:00:35 PM 06/02/97</b> <br> But the time looks nicer this way : It's <b>Monday</b> and the time is <b>08:00 PM</b>! <hr> </body> </html> We are even able to include HTML tags in text string which defined the date.

The #exec command
There are occasions when SSI includes and SSI variables cannot achieve the dynamic content you want, but still don't want to go to the trouble of writing a CGI program to generate the entire page content. By using the #exec command, you can include the output of a program within your HTML pages. The exec command is followed by the cgiparameter, and a valid CGI program as the attribute.

<!--#exec cgi="prog.cgi" -->

Example : A CGI to Display Machine Load

To prove that your server machine is capable you might want to include a load meter on the machine spec page. The page contains a lot of information and is updated frequently so you don't want a CGI program to generate the complete HTML code. The examples below will obtain the load average of the machine, then determine what colour to display the text.

A .shtmlfile :

<HTML> <HEAD><TITLE>SSI Test</TITLE> <META HTTP-EQUIV="Refresh" CONTENT="2; test.shtml"> </HEAD> <BODY> This is a big page about our large machine. <p> <!--#exec cgi="load.cgi"--> </BODY> </HTML> The CGI Program: #!/usr/bin/perl print "Content-type: text/html", "\n\n"; $uptime = `uptime`; @fields = split /,/, $uptime; $load = @fields[$#fields-1]; print "<p>"; if ($load < 1) { $colour = "white"; } elsif ($load < 2) { $colour = "yellow"; } elsif ($load < 3) { $colour = "orange"; } else { $load ="red"; } print "Load average is :<FONT color = $colour> ", $load, " </FONT>\n"; print "<p>", "<HR>", "\n"; exit 0 Possible (this is dynamic after all) result in the HTML: <HTML> <HEAD><TITLE>SSI Test</TITLE> <META HTTP-EQUIV="Refresh" CONTENT="2; test.shtml"> </HEAD> <BODY> This is a big page about our large machine. <p> <p>Load average is :<FONT color = white> 0.32 </FONT> <p><HR> </BODY> </HTML>

Executing arbitrary shell commands

The exec command can also be used to execute arbitrary shell commands when used with the cmd= tag. For this tag to be available, the server needs to have `CGI enable anywhere' turned on. <!--#exec cmd="command"--> The server will execute the equivalent of /bin/sh -c "command" and replace the tag with the output of that command.

For example:

<!--#exec cmd="cat /etc/passwd | cut -f1 -d':' | sort"-->

The #set command
The #set command allows you to add your own variables that can be used with the #echo command. For format of a #set command is:

<!--#set var="..." value="..." --> For example: <!--#set var="title" value="My document's title" --> The #set command is extremely powerful as it provides a means of passing 'arguments' to recursively included SSI pages. This is because the #set command adds to the global variable environment, so a parsed document can set a variable then include another parsed document which uses this variable, or vice versa. For example:

File title.shtml:

<!-- requires title --> <!-- Imagine this is a complicated table --> <!-- which puts the title at the top of --> <!-- the page in a standard fashion. --> <html> <head> <title><!--#echo var="title"--></title> </head> <body bgcolor=#ffffff> <table bgcolor=#f0f0c3 cellspacing=4> <tr> <td> <font size=+3> <!--#echo var="title"--> </font> </td> </tr> </table>

Then we could use this complex standard title in a document "About Zeus" as follows:

<!-- Set title, and include standard document header --> <!--#set var="title" value="About Zeus"--> <!--#include file="title.shtml"--> Document body goes here. <!-- We'd probably do the footer in the --> <!-- same way, but for now we'll just --> <!-- terminate the html manually. --> </body> </html> Using the #set command allows the reuse of 'components' of HTML and is extremely useful in large web-site design.