Getting Started with CGI

Since you are reading this section, it is presumed that you already know what CGI processing is. If not, a good introduction can be found here. Yahoo! has a good index of CGI references.

Getting started with CGI can seem to be a daunting task. Many of the posts to comp.infosystems.www.servers.unix contain requests for help to get CGI working. Like all types of network programming, it is necessary to get more than one thing running correctly before you see any results, but it's not difficult, others have done it before, and after setting the configuration options in this section, your server should be configured to process CGI requests.

Note: Through out this document, I refer to CGI scripts. This is only a convention. CGI programs can be written in virtually any language you are conversant with. The can be compiled or interpreted or a mixture of both. The choice is yours. This guide will not help you write CGI scripts, but will help you get them to run, and help you to debug them is they don't. If you don't know how to program, you are going to have to learn, or find someone who will do the programming for you!.

Minimum Configuration

Apache provides a number of configuration options relating to CGIs. There are two main options for CGIs and Apache:
  • Configure a directory where all CGI scripts will reside or
  • Configure Apache to recognize specific file extensions as CGI programs.
We are going to use the first option, and define a directory, by convention cgi-bin which will contain all our scripts. Again this is a convention which many (most?) web sites Adhere to. Your milage may vary.

Many Linux distributions now have cgi-bin enabled in the default configuration.

CGI Location

The ScriptAlias option allows you to group all you CGI scripts into a single directory. Any files found in this directory will be treated by Apache as CGI scripts.

I have a personal dislike for the default location of the cgi-bin directory for Apache 2.x under the Ubuntu distribution. For some reason it is located in:

/usr/lib/cgi-bin>

which forces you to either be SuperUser to update it, or give yourself write privileges to a sub-directory of /usr/lib, and area that is generally read-only on most disto's and Unix's.

My personal preference is to have the cgi-bin directory adjacent to the DocumentRoot (html) directory, in some where like /var/virtual/VM_Name/, but then that's just my personal preferences.

To specify a directory where you cgi scripts will reside, edit srm.conf and change

 
# ScriptAlias: This controls which directories contain server scripts.
# Format: ScriptAlias fakename realname

#ScriptAlias /cgi-bin/ /apache/cgi-bin/
  To: (just remove the '#' comment character)  
# ScriptAlias: This controls which directories contain server scripts.
# Format: ScriptAlias fakename realname

ScriptAlias /cgi-bin/ /apache/cgi-bin/
  Here we have specified that files found in the directory /apache/cgi-bin/ should be treated as CGI scripts. NT users would specify:  
# ScriptAlias: This controls which directories contain server scripts.
# Format: ScriptAlias fakename realname

ScriptAlias /cgi-bin/ c:/apache/cgi-bin/
  Note: in both the Unix and NT examples, we have specified an absolute path from the root of the file system.

CGI scripts, in the above example would be referenced by the url:

<a href="http://your.host.name/cgi-bin/your_script_name">

or

<a href="/cgi-bin/your_script_name">

Once you have decided where you CGI directory will be located, edit access.conf and change the following to conform with the ScriptAliases changes.

 
# /apache/cgi-bin should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.

<Directory c:/apache/cgi-bin>
AllowOverride None
Options None
</Directory>
  Re-start your Apache web server and then proceed to test your CGI configuration.

References

General

Apache Directives

Testing CGI

Here is a simple shell script which I always use when I first set up a new web server. It prints out some of the CGI environment variables and gives you a warm feeling that everything is working.
 
#!/bin/sh

# disable filename globbing
set -f

echo Content-type: text/plain
echo

echo CGI/1.0 test script report:
echo

echo argc is $#. argv is "$*".
echo

echo SERVER_SOFTWARE = $SERVER_SOFTWARE
echo SERVER_NAME = $SERVER_NAME
echo GATEWAY_INTERFACE = $GATEWAY_INTERFACE
echo SERVER_PROTOCOL = $SERVER_PROTOCOL
echo SERVER_PORT = $SERVER_PORT
echo REQUEST_METHOD = $REQUEST_METHOD
echo HTTP_ACCEPT = "$HTTP_ACCEPT"
echo PATH_INFO = "$PATH_INFO"
echo PATH_TRANSLATED = "$PATH_TRANSLATED"
echo SCRIPT_NAME = "$SCRIPT_NAME"
echo QUERY_STRING = "$QUERY_STRING"
echo REMOTE_HOST = $REMOTE_HOST
echo REMOTE_ADDR = $REMOTE_ADDR
echo REMOTE_USER = $REMOTE_USER
echo AUTH_TYPE = $AUTH_TYPE
echo CONTENT_TYPE = $CONTENT_TYPE
echo CONTENT_LENGTH = $CONTENT_LENGTH
  Cut and past this file into your favorite editor and save it in your CGI directory as testcgi. Make sure to set the execute permissions on it (Unix).  
chmod +x testcgi
 

And an NT version which is not quit as good, but give you most of the information. I would appreciate an e-mail on how to get the argument count and all the arguments (like **argv in 'C') in a dos batch file.

 
@echo off

echo Content-type: text/plain 
echo.

echo CGI/1.0 test script report:
echo.

rem echo argc is %0
echo argv is %0
echo.

echo SERVER_SOFTWARE = %SERVER_SOFTWARE%
echo SERVER_NAME = %SERVER_NAME%
echo GATEWAY_INTERFACE = %GATEWAY_INTERFACE%
echo SERVER_PROTOCOL = %SERVER_PROTOCOL%
echo SERVER_PORT = %SERVER_PORT%
echo REQUEST_METHOD = %REQUEST_METHOD%
echo HTTP_ACCEPT = "%HTTP_ACCEPT%"
echo PATH_INFO = "%PATH_INFO%"
echo PATH_TRANSLATED = "%PATH_TRANSLATED%"
echo SCRIPT_NAME = "%SCRIPT_NAME%"
echo QUERY_STRING = "%QUERY_STRING%"
echo REMOTE_HOST = %REMOTE_HOST%
echo REMOTE_ADDR = %REMOTE_ADDR%
echo REMOTE_USER = %REMOTE_USER%
echo AUTH_TYPE = %AUTH_TYPE%
echo CONTENT_TYPE = %CONTENT_TYPE%
echo CONTENT_LENGTH = %CONTENT_LENGTH%
  NT users should save this file as testcgi.bat. Be sure to use the .bat extension on NT so that NT can make the association with the file extension and run it correctly.

Accessing the script

 
http://your_domain/cgi-bin/testcgi.bat

or

http://your_ip_address/cgi-bin/testcgi.bat
 

What you should see

If all goes well, your script should display something like.
 
CGI/1.0 test script report:

argc is 0. argv is .

SERVER_SOFTWARE = Apache/1.2.4
SERVER_NAME = www.jlk.net
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.0
SERVER_PORT = 80
REQUEST_METHOD = GET
HTTP_ACCEPT = image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
PATH_INFO = 
PATH_TRANSLATED = 
SCRIPT_NAME = /cgi-bin/test-cgi
QUERY_STRING = 
REMOTE_HOST = 158.76.200.102
REMOTE_ADDR = 158.76.200.102
REMOTE_USER =
AUTH_TYPE =
CONTENT_TYPE =
CONTENT_LENGTH =
 

What can go wrong, and
what to do about it

 
Not Found

The requested URL /cgi-bin/testcgi was not found on this server.
  You have either:
  • typed in the incorrect URL
  • saved the file with a different name

    Check you typing and/or the file names in you CGI directory.

  • specified a different directory for CGIs
  • or CGIs are not configured

    Check your srm.conf configuration for ScriptAliases (see Getting Started with CGIs)
 
Internal Server Error

The server encountered an internal error or mis-configuration and 
was unable to complete your request.

Please contact the server administrator, webmaster@jlk.net and 
inform them of the time the error occurred, and anything you 
might have done that may have caused the error.
  It means, that someway, somehow, you have screwed up the above scripts. Every CGI script must return:
  1. One or more Header lines
    (i.e. Content-type: text/html)
  2. A blank line
  3. the body of the document (optional but recommended)
and when this error occurs, either 1 or 2 or both are missing.

Check you scripts!

 
Forbidden

You don't have permission to access /cgi-bin/test-cgi on this server.
  You have forgotten to set the execute bit on the script (Unix though you may be able to mess with the permissions on NT and get this error).  
# cd /var/apache/cgi-bin
# ls -l test-cgi
-rw-r--r--   1 103      20           757 Apr  8 14:12 test-cgi
# chmod +x test-cgi
# ls -l test-cgi
-rwxr-xr-x   1 103      20           757 Apr  8 14:12 test-cgi
#
  Once you have basic CGIs working, there are some more Apache configuration options which you can apply that may make your life easier while developing CGI scripts.

Debugging CGI

Once you have a basic CGI configuration working, there are some additional Apache directives which can assist you in debugging your CGI scripts. Warning! You should only use these directives during development. They are not optimised for a production machine and can cause a significant overhead on you server.

Getting more Information

Adding the directive ScriptAliases in your srm.comf will enable logging of CGI error information.
 
# ScriptAlias: This controls which directories contain server scripts.
# Format: ScriptAlias fakename realname

ScriptAlias /cgi-bin/ c:/apache/cgi-bin/

ScriptLog c:/apache/logs/cgi_errors_logs
  Remember! to re-start Apache after any changes you make to the configuration file.

So we can show the difference between a good and bad script response, we are going to "modify" the test-cgi script we used to in Testing CGI to give a bad error response.

Change the script so as to remove the header information.

 
@echo off

rem echo Content-type: text/plain
rem echo argv is %0
rem echo.

echo SERVER_SOFTWARE = %SERVER_SOFTWARE%
      .
      .
      .
  And then try out the script file again. Your ErrorLog should product something like....  
[Thu Apr 09 10:33:00 1998] [error] malformed header from script. 
Bad header=SERVER_SOFTWARE = Apache/1.3b3: c:/apache/cgi-bin/test-cgi.bat
  Which in this simple case, is sufficient to determine what is causing the error. The ScriltLog produces considerable more information.

We can see that Apache returned error code 500: and Internal Server Error We know from our modifications, that this is caused by the lack of header information.

After the %stdout we can see actually what the script was attempting to send back to the browser. As per the error code, there is no

Content-type: text/plain

header information.

 
%% [Thu Apr 09 10:33:00 1998] GET /cgi-bin/test-cgi.bat HTTP/1.0
%% 500 c:/apache/cgi-bin/test-cgi.bat
%request
Connection: Keep-Alive
User-Agent: Mozilla/4.0 [en] (WinNT; I)
Pragma: no-cache
Host: jaunty
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
%response
SERVER_SOFTWARE = Apache/1.3b3
%stdout
SERVER_NAME = jaunty
GATEWAY_INTERFACE = CGI/1.1
SERVER_PROTOCOL = HTTP/1.0
SERVER_PORT = 80
REQUEST_METHOD = GET
HTTP_ACCEPT = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"
PATH_INFO = ""
PATH_TRANSLATED = ""
SCRIPT_NAME = "/cgi-bin/test-cgi.bat"
QUERY_STRING = ""
REMOTE_HOST = 158.76.200.102
REMOTE_ADDR = 158.76.200.102
REMOTE_USER = 
AUTH_TYPE = 
CONTENT_TYPE = 
CONTENT_LENGTH = 
  Here is a Unix example using Perl. A simple script which prints the now famous "hello, world". There is a minor syntax error on the last line of the script. The semi-colon ";" is a missing.  
#!/usr/local/bin/perl

print "Content-type: text/html\n\n";
print "<html><head><title>hello, world</title></head>";
print "<body><h1>hello, world</body></html>"
  When we try to access the script, the ErrorLog shows us that their was and error in running the script.  
[Thu Apr  9 11:53:22 1998] access to /var/apache/cgi-bin/hello.pl 
failed for 158.76.200.102, reason: Premature end of script headers 
  But the ScriptLog shows us why it went wrong. Perl wrote on stderr that there was a syntax error near line 5.  
%% [Thu Apr  9 11:53:22 1998] GET /cgi-bin/hello.pl HTTP/1.0
%% 500 /var/apache/cgi-bin/hello.pl
%request
Connection: Keep-Alive
User-Agent: Mozilla/4.0 [en] (WinNT; I)
Pragma: no-cache
Host: www.jlk.net
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
%response
%stderr
syntax error at /var/apache/cgi-bin/hello.pl line 5, near "print"
Execution of /var/apache/cgi-bin/hello.pl aborted due to compilation errors.
  This trivial error could have been found by running hello.pl from the command line but is sufficient to demonstrate the additional script debugging features of Apache.

There are a few other directives that you should be aware of when debugging CGIs scripts with Apache.

Other Debug Directives

ScriptLog file logs grow very quickly due the the amount of data generated. You can limit the size of of ScriptLog file with the ScriptLogLength to a certain number of bytes.
ScriptLogLength 5000000
  Additionally the number of bytes logged during a Post request to a CGI script can be limited with the ScriptLogBuffer
ScriptLogBuffer 512
 

References

Apache Directives

 


RTFM Index   Server Side Includes
Tell us what you think!
Copyright © 2006 Open Source Migrations ltd. All Rights Reserved.
Apache RTFM last updated Saturday October 21 2006