CPSC 225: Intermediate Programming, Spring 2002
Programming Assignment 5: CGI in C++


WEB-SITE PROGRAMMING is based on a standard called "CGI" (Common Gateway Interface). In the traditional version of CGI, a Web server receives a "request" from a Web browser that requires some kind of processing beyond simply returning a static HTML document. To handle the necessary processing, the Web server runs an external program. The server provides information about the request, and the program uses that information to construct a "response" to be sent back to the Web browser. The CGI standard specifies how information is communicated between the server and the external program.

Now, traditional CGI has a reputation of being slow, since the Web server must start another program to process the request. A more modern approach is to build the processing into the server itself. However, some of the reputation for slowness is due to the fact that many CGI applications were written in Perl, and executing a Perl script involves starting up a rather large and complicated Perl interpretor, no matter how simple the Perl script itself is. The fact is that traditional CGI can be reasonably speedy, provided small compiled programs are used to do the CGI processing.

For this assignment, you will be writing a couple of CGI applications in C++. You will use two classes, CGIRequest and CGIResponse, to handle some of the more technical details. A CGI program will use an object of type CGIRequest to get information about the request that was sent from the browser to the server. This information can include data from a form on a Web page, for example. The program will use an object of type CGIResponse to construct the response that will be sent back to the browser. Generally, the response is just a page of HTML source code.

The files that define CGIRequest and CGIResponse can be found in the directory /home/cs225/cgi. This directory also includes some sample CGI applications. You should copy this entire directory into your www directory, for example with the command:

               cp  -r  /home/cs225/cgi  ~/www

The documentation for the two classes is in the header file CGI.h. The definitions for the member functions are in CGI.cc, but you don't need to read or understand these definitions. A CGI application must make the two classes available for use with an include directive of the form #include "CGI.h". Note the use of quotes, rather than angle brackets, around the file name. This tells the compiler to look for CGI.h in the current directory. The sample CGI programs are defined in env.cc, comments.cc, and survey.cc. The corresponding compiled applications are called env.cgi, comments.cgi, and survey.cgi. (To run a CGI application from your own www directory, you must give it a name ending in .cgi.)


CGI from C++

When a CGIRequest object is constructed, it gathers all the available information about the Web request, and it organizes this information into "variables". Each variable has a name and a value. You can obtain the values of these variables by calling the object's getVar method. The sample CGI application, env.cgi, is designed to show the values of all the available request variables. If you access the URL

    http://math.hws.edu/eck/cs225/cgi/env.cgi

you will see a table of the basic "CGI variables" that are sent with every Web request. For example, there is the variable with the name "REMOTE_ADDR", which tells you the IP address of the computer where the request originated. Other variables can come from the URL itself. For example, the URL

    http://math.hws.edu/eck/cs225/cgi/env.cgi?name=fred&year=sophomore

defines two "GET variables", name with value "fred" and year with value "sophomore". If you follow the above link, you will see these GET variables listed at the bottom of the page. Finally, there are "POST variables", which generally come from forms on Web pages. For example, the following form sends its data to the env.cgi application using the POST method:

Enter your name:
What year are you:

Each input item in the form has a name, which becomes the name of the variable in the CGIRequest object. Note that in general, you do not need to distinguish between the different types of variables. You just ask for the variable you want by name.

Most commonly, CGI applications are used with HTML forms. The form sends the data to the Web server, which passes it on the the CGI program. You can see this in action in the other two sample programs, which are called by the forms on these Web pages:

          http://math.hws.edu/eck/cs225/cgi/comments.html

          http://math.hws.edu/eck/cs225/cgi/survey.html

In both of these examples, data is saved to a file. If you have copied the directory /home/cs225/cgi to your web directory, you can access the same examples in your own account. Just change the URL's to replace math.hws.edu/eck/cs225/cgi with math.hws.edu/~username/cgi (with username replaced by your own user name). When a CGI application runs from your www directory, it can create and use files in your account.

In general, a CGI application simply writes an HTML page that is sent back to the Web browser. A CGIResponse object has a put method that adds a string to this response. You are responsible for using correct HTML syntax in these strings.


The Assignment

This assignment allows you to work with classes (for the first time) and with files (for the second time). For the assignment, you will write two CGI programs.

The first program is a companion to the comments.cgi example, which takes a comment submitted from a Web page and appends it to a file. You should write a CGI program that will read all the saved comments from that file and display them on a Web page. This program, like env.cgi, will be called up directly, by a URL such as http://math.hws.edu/~jsmith/cgi/showcomments.cgi. It will not be called from a form. (You might also want to modify the file comments.html to ask for comments about something more interesting.)

The second part of the assignment consists of a Web page with a form and a CGI program to process the data from that form. These will be a more elaborate version of the survey example. Your Web page should have a survey form for the user to fill out. The CGI program should add the data from the form to a file and display a summary of at least some of the results from the survey. The sample survey only has one question. Your survey should be more ambitious than that. (Keep in mind, though, that Web surveys are basically bogus, especially when they have no protection against ballot-box stuffing.)

The assignment is due next Wednesday, March 6.


Compiling your programs

When you write a CGI program using CGIRequest and CGIResponse, the program source code comes in three pieces: CGI.h, CGI.cc, and the source code that you write for the main program. There are several ways to compile the program. Let's say that the program source code is in the file mainapp.cc. The simplest way to compile the program is to provide both mainapp.cc and CGI.cc to the g++ compiler:

           g++  -o mainapp.cgi  mainapp.cc  CGI.cc

(CGI.h is read automatically, since it is #included in the other files.) However, this will recompile CGI.cc every time, even though you won't be making any changes to it. You can avoid this unnecessary recompilation. I have already compiled CGI.cc to make a compiled file named CGI.o. This file is incomplete. It must be "linked" to a main program. This can be done with

           g++  -o mainapp.cgi  mainapp.cc  CGI.o

Here, since CGI.o is already compiled, it is merely linked into the program. In fact, you can build the main program even if you don't have CGI.cc. All you really need is CGI.o. By default, g++ does two things: It compiles any C++ source code files that you give it, and then it links all the necessary compiled files and libraries to produce a complete compiled program. To have it do a compilation only, you can add the "-c" option to the command. For example, CGI.o was produced with the command:

          g++  -c  CGI.cc

You could even compile mainapp.cc in the same way to give mainapp.o, and then link mainapp.o together with CGI.o. The entire compilation would require three commands:

          g++  -c  CGI.cc
          g++  -c  mainapp.cc
          g++  -o mainapp.cgi  mainapp.cc  CGI.cc

The advantage of doing things this way becomes more apparent when you consider large programs that are divided into many source code files. When you make a change to one file, it would be silly to recompile them all. All you need to do is recompile the one file and then re-link the main program.


David Eck, 25 February 2002