[Chapter 12] 12.4 Logging and Simulation
Author: Shishir Gundavaram
Date: Tue Aug 26 16:44:10 1997

#

| Chapter 12 Debugging and Testing CGI Applications |

## 12.4 Logging and Simulation

At this point, you might be wondering where all the CGI errors get logged. If you are using the NCSA server, the log files directory is the place that holds them. You can manually place debugging messages into the error_log file by doing the following:

    print STDERR "Calendar v1.0 - Just about to calculate center", "\n";
    $center = ($diameter / 2) + $x_offset;
    print STDERR "Calendar v1.0 - Finished calculating. Center = ", $center, "\n";

After the program is finished, you can look at the log file to see the various debugging messages. It is a good practice to insert the name of your program into the message, so you can find it among all of the different messages logged to the file. Another trick you can use is to "dupe" (or duplicate) standard error to standard output:

    print "Content-type: text/plain", "\n\n";
    open (STDERR, ">&" . STDOUT);
    print STDERR "About to execute for loop", "\n";
    for ($loop=0; $loop <= 10; $loop++) {
        $point[$loop] = ($loop * $center) + $random_number;
        print STDERR "Point number ", $loop, " is ", $point[$loop], "\n";
    }
    close (STDERR);

In this case, the errors generated by the CGI program will go to the browser as well as to the log file.

### Client Simulation

In order to get a good feel for how the Web works, you should connect to a server and simulate a client's actions. You can do this by using the telnet protocol. Here is an example:

    % telnet www.ora.com 80
    Trying 198.112.208.13 ...
    Connected to amber.ora.com.
    Escape character is '^]'.
    GET / HTTP/1.0
    <HTML><HEAD>
      <TITLE>O'Reilly Home Page</TITLE>
    </HEAD><BODY>
    <P><A HREF="http://bin.gnn.com/cgi-bin/imagemap/radio">
    <IMG SRC="/gnn/bus/ora/radio.gif"  ALT="" ISMAP></A>
    .
    .
    .
    </BODY></HTML>
    Connection closed by foreign host.

You can enter other HTTP commands as well. But remember that HTTP is a stateless protocol. In other words, you can issue only one request, after which the server terminates the connection. Now let's look at the issues behind server simulation.

### Server Simulation

If you do not have access to a server on a full-time basis, you can simulate the features of a server quite easily. Before we look at how this can be accomplished, let's look briefly at what the server actually does:

- Gets a request from the client to serve a resource (either a file or a CGI program).

- Checks to see if the file is a CGI script.

- If it is, passes various environment variables/input stream to the CGI program, and waits for output.

- Sends the output from either a regular file or CGI to the client.

In order to test CGI scripts, all we would have to do is emulate the third step in this process. Let's look at a typical GET request. First, we have to create a file to set the environment variables (e.g., environment.vars). Here is how you can do it in the C shell:

    setenv REQUEST_METHOD     'GET'
    setenv QUERY_STRING       'name=John%20Surge&company=ABC%20Corporation%21'
    setenv HTTP_ACCEPT        'image/gif, image/x-xbitmap, image/jpeg, */*'
    setenv SERVER_PROTOCOL    'HTTP/1.0'
    setenv REMOTE_ADDR        '198.198.198.198'
    setenv DOCUMENT_ROOT      '/usr/local/bin/httpd_1.4.2/public'
    setenv GATEWAY_INTERFACE  'CGI/1.1'
    setenv REQUEST_METHOD     'GET'
    setenv SCRIPT_NAME        '/cgi-bin/abc.pl'
    setenv SERVER_SOFTWARE    'NCSA/1.4.2'
    setenv REMOTE_HOST        'gateway.cgi.com'

In a Bourne-compatible shell (such as Korn shell, bash, or zsh), the previous commands will not work. Instead, you need the following syntax:

    export REQUEST_METHOD = 'GET'
    export QUERY_STRING =  'name=John%20Surge&company=ABC%20Corporation%21'
    .
    .
    .

Then, we have to execute this script with the following command (assuming the commands are stored in the file environment.vars) in the C shell:

    % source environment.vars

In a Bourne-compatible shell, you need to do the following:

    % . environment.vars

Now, you can simply run your CGI script, and it should work as though it was being executed by the server. For POST requests, the process is slightly different. You first have to create a file that contains the POST information (e.g., post_data.txt):

    name=John%20Surge&company=ABC%20Corporation%21&sports=Basketball&
    exercise=3&runners=no

Once that is done, you need to determine the content length (or the size in bytes) of the data. You can do that with the wc command:

    % wc -c post_data.txt
       86

Then you need to add the following two lines to the environment variable file that we created above (assuming C shell):

    setenv REQUEST_METHOD     'POST'
    setenv CONTENT_LENGTH     '86'

Now all you have to do is send the data in the file to the CGI program through a pipe:

    % /usr/local/bin/httpd_1.4.2/cgi-bin/abc.pl < post_data.txt

That's all there is to it. The CGI Lint application automates this procedure, as we will see next.

Environment Variables |  | CGI Lint--A Debugging/Testing Tool