Guide Categories:  Drivers | Questions & Answers | Write to Us
Technical Questions and Answers Silicon Guide
Search SiliconGuide:

Parsing CGI output using Server Side Includes (SSI)

August 2, 2002

Leo Galleguillos wrote:

Q. Do you know how to enable server-side includes to be parsed within the HTML that a cgi-script outputs? Thank you.

Eric Georgieff answered:

A. You pose a question that I have asked myself many years ago. After searching many years for a solution I have determined the following.

As you may have noticed, it would be quite convenient if it were possible to get the output of CGI scripts (such as those written using the Perl programming language) to be parsed by the server side include engine (SSI) before it is sent to the client. In this way, it would be possible to simply output SSI commands from your CGI script and then allow the server software to do the work of actually fetching the data from a physical file present on the web server. This would allow you to write less actual HTML within the code of your CGI scripts and to follow the same format you are currently using throughout your web site, should you already be using the power of server side includes.

It is unfortunately impossible to obtain this desired effect with most current web server software. Both Apache 1.3, which is currently used by about 56 percent of all internet sites (see the NetCraft Web Server Survey), and Microsoft Internet Information Server 5.0 (IIS) do not allow CGI script output to be parsed before it is sent to the client.

The IIS server uses ISAPI modules (often contained within dll files) that are called whenever a file with a certain registered extension is called. These ISAPI modules then perform the required operation using the data provided by the web server and return their parsed data to the web server which then forwards it to the client. So, if you had a file with the extension *.cgi or *.pl, for instance, the Perl ISAPI module would be invoked. The same applies for practically any type of extension, *.asp (Microsoft Active Server Pages), *.jsp (Java Server Pages), *.shtml (Server Side Includes), being merely a few popular examples. My theory is that it is only possible for one ISAPI module to handle data before a result is sent to the web client. Since it would hence be impossible to daisy chain ISAPI modules, it would be impossible for the Server Side Includes (SSI) module to parse the output of the Perl module.

As for the Apache web server, I have not had much more success. Here too, it would appear that it is impossible to parse the server side includes present in the output of your CGI scripts. The Apache 1.3 FAQ states the following:

How can I have my script output parsed?

So you want to include SSI directives in the output from your CGI script, but can't figure out how to do it? The short answer is "you can't." This is potentially a security liability and, more importantly, it can not be cleanly implemented under the current server API. The best workaround is for your script itself to do what the SSIs would be doing. After all, it's generating the rest of the content.

This is a feature The Apache Group hopes to add in the next major release after 1.3.

So it would appear that they planed to add this feature in Apache 2.0 which is currently available for download, but it is not clear if they actually managed to implement it or not, nor have I played around with Apache 2.0 to find out. You may download the Apache 2.0 web server to see if it works.

Here at Siliconguide.com, we use the Apache 1.3 web server, running on a Microsoft Windows 2000 server and have decided to get our scripts to do what the SSIs would be doing, as suggested by the Apache 1.3 documentation. The following Perl code snippets perform approximately the same thing as would a corresponding SSI routine. If you are not using Perl to write your script, you should still be able to understand the general idea and write code in the particular language you are using (e.g. C++).

To include the contents of a file into your script output, simply read the data from the actual physical file on disk into a variable (in this case we will use an array) and then print out the contents of the variable as follows. This is the equivalent of using the "<!--#include virtual="LOCATION_OF_FILE"-->" SSI command.

open (include, "<$include_file") or &error("Unable to open the file to include");
@include=<include>;
close(include);
print @include;

To include the output of another CGI program, that is being called from the SSI code of one of the files you are manually including (using the above method), you can scan through the file you wish to include and replace any "<!--#include virtual="LOCATION_OF_CGI_SCRIPT"-->" or "<!--#exec cmd="LOCATION_OF_CGI_SCRIPT" -->" SSI commands with the actual output of the desired CGI program as follows. This requires manually executing the CGI script in the system's shell. In the following example, we are scanning for the strings "<!--#exec cgi=\"../../cgi-bin/ads/ads.cgi\" -->\n" and "<!--#include virtual=\"../../cgi-bin/ads/ads.cgi?buttons\" -->\n" and replacing them with the output of the CGI programs they refer to (e:/wwwroot/siliconguide/cgi-bin/ads/ads.cgi and e:/wwwroot/siliconguide/cgi-bin/ads/buttons.cgi respectively). Please note that this example is intended to work in a Windows environment and will require modifications to work properly under Unix.

foreach $i (@header) {
if ($i eq "<!--#exec cgi=\"../../cgi-bin/ads/ads.cgi\" -->\n") {
system("perl e:/wwwroot/siliconguide/cgi-bin/ads/ads.cgi");
}
if ($i eq "<!--#include virtual=\"../../cgi-bin/ads/ads.cgi?buttons\" -->\n") {
system("perl e:/wwwroot/siliconguide/cgi-bin/ads/buttons.cgi");
}
else {
print ($i);
}
}

In a similar way, it is possible to duplicate the effect of all types of server side include routines.

Home | Web Development | Hardware and Upgrading | Internet | Technical Questions & Answers | Tips and Tricks | Write to Us

Last modified on: Friday, 02-Aug-2002 17:34:48 EDT
Copyright © 1999 - 2008 SiliconPharm Corporation, All Rights Reserved
Powered by Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny3 with Suhosin-Patch (More Info)