Fundamentals of Computer Science I (CS151 2003F)

CGI Scripting in Scheme

Summary: As you may know, it is possible to write programs that generate Web pages in response to user input (input that is often entered on other Web pages). The most common mechanism for writing such programs is CGI, which stands for common gateway interface. It is possible to write CGI programs (usually called "scripts") in almost any programming language, including Scheme.


Here's how CGI typically works.

  1. The user enters information on a form (simply an HTML page with some special tags that specify data-entry widgets and the name of a script to process the user's niput).
  2. When the user clicks on the Submit button (or something similar) the browser packages up all the information from those fields and sends it to the server.
  3. The server then unpackages the information and passes it on to the CGI script.
  4. The CGI script looks at the information and generates a page.
  5. The CGI script returns the page back to the server.
  6. The server passes the page back to the browser.
  7. The browser displays the page.
  8. Everyone is happy.

So, what do you need to learn in order to write CGI scripts? You already know how to write Scheme to generate an HTML page (or you should if you did the strings lab). So, you have to learn how to get information from the server, tell the server to run your program from a CGI script, and build the HTML page that lets someone enter information.

I've set up some helper programs that make it easier (but not necessarily easy) for you to write CGI scripts in Scheme. I also recommend that you follow a standard process when building your scripts.

The Basic Steps

Here are the steps that I recommend that you undertake when writing a CGI script.

Stage One: Prepare a Scheme Procedure

Let's start with what you should already mostly know how to do.

  1. Decide the purpose of the script: what you want the script to do. Someone (i.e., me) might tell you what to do or you might choose on your own. For example, you might want to write a program that generates a simple greeting page.
  2. Determine what input your script will take. For example, your greeting script might take a user's name as input. We'll call that input user.
  3. Write a Scheme procedure that takes as a parameter the input decided upon in the previous step and generates an appropriate HTML page. See below for a sample procedure.
  4. Test that procedure!
  5. Save that procedure in a .scm file. For example, greetings.scm. The file should be in your public_html directory.
  6. Make that file world-readable with
    % share filename
    But don't type the percent sign!

Stage Two: Extend the Scheme File

Now you need to extend the file so that it works with the CGI system (in terms of getting input from the CGI system and working when called from the CGI system). The way I've set up my CGI gateway, it always calls a procedure named page that has no parameters.

  1. Add the following line to the top of your Scheme file (after your introductory comments):
    (load "/home/rebelsky/Web/Scheme/webutils.scm")
    This line tells Scheme that you need the my library of utility procedures for dealing with CGI scripts.
  2. Add another procedure to your Scheme file that is named page and takes no parameters. This procedure should call your first procedure using values extracted by (get-cgi-variable 'name "default-value"). For example
    (define page
      (lambda ()
        (greeting-page (get-cgi-variable 'user "SamR"))))
    In order for my helper stuff to work correctly, this procedure must be named page!
  3. Test your stuff by loading your code into DrScheme and typing (page).

Stage Three: Build CGI Wrapper

Now it's time to build something that ties your Scheme program to the CGI system.

  1. Build a file of the following form. Make sure that there are no spaces at the beginning of any line:
    /home/rebelsky/bin/schemeweb your-scheme-file
    For example,
    /home/rebelsky/bin/schemeweb greeting.scm
    Note that you should always use the /home/rebelsky/bin no matter who you are!
  2. Save that file in your public_html directory as something that ends in .cgi. For example, greetings.cgi.
  3. Tell Unix that you've written a program with the following commands. Once again, don't type the percent signs.
    % chmod a+x filename.cgi
    % chmod a+r filename.cgi
  4. Test the CGI interface by loading your page in the Web browser with a URL like the following:
    For example,
    Only use letters and numbers for testing!

Stage Four: Build the HTML Interface

Now you're ready to build the HTML page that people will use.

  1. Write an HTML page that can provide input to your page. The input page is typically called a form.

Stage Five: Put it all together

  1. Test, test, and test again.

A Sample Procedure

Here is a Scheme procedure that generates a greeting page based on an input name. It assumes that you've written some helper procedures similar to those from the strings lab.

;;; Procedure
;;;   greeting-page
;;; Parameters:
;;;   user-name, a string that represents the name of a user
;;; Purpose:
;;;   Generates an HTML page that can greet the named person.
;;; Produces:
;;;   page-code, a string that corresponds to that page.
;;; Preconditions:
;;;   user must be nonempty.
;;; Postconditions:
;;;   page-code is valid HTML.
(define greeting-page
  (lambda (user-name)
      (head "Greetings")
      (body (string-append
              (heading 1 "Welcome")
              (string #\newline)
              (paragraph (string-append "Hi " user-name "!")))))))

Here is the extra UI code one might use to build the page:

(define page
  (lambda ()
    (greeting-page (get-cgi-variable 'user "SamR"))))

HTML Forms

As mentioned above, a form is simply some HTML that lets the user enter some input and ties that input to a CGI script. (Forms can do other things, too, but this purpose is enough for now).

As you might expect, you surround a form with form tags. The opening tag must also include two parameters:

For example,

<form method="get" action="greeting.cgi">

You can include normal HTML in a form. Normal HTML is displayed normally and is not uploaded to the server when the user submits values. Rather, it is used to give some information to the user about where things might go.

When you want the user to type a value, you use an input tag with the following parameters:

For example,

<input type="text" name="user" value="">

You should also provide a handy-dandy "Click Here" button. Once again, you use an input tag. This time, you use slightly different parameters:

For example

<input type="submit" value="Enter your name and click here!">

That's it, you know the basics. If you want things other than fields in your forms, ask me about them in class or look them up on the Web.

Basic CGI Steps, Revisited

Here's how CGI works in my recommended environment.

  1. The user enters information on a form (simply an HTML page with some special tags).
  2. When the user clicks on the Submit button (or something similar) the browser packages up all the information from those fields and sends it to the server.
  3. The server then unpackages the information and passes it on to the CGI script.
  4. The CGI script calls my script (/home/rebelsky/bin/schemeweb).
  5. My script calls your the (page) procedure it finds in the file you specified.
  6. Your (page) procedure grabs the information and generates a string which it returns to my script.
  7. My script passes that string back to the server.
  8. The server passes the page back to the browser.
  9. Everyone is happy.

Sample Code

greeting.scm (stored separately; select the link)


/home/rebelsky/bin/schemeweb greeting.scm


<title>Testing Scheme CGI</title>
<form method="get" action="greeting.cgi">
<input type="text" name="user" value=""> <br>
<input type="submit" value="Enter Your Name and Click Me!">



Wednesday, 7 February 2001 [Samuel A. Rebelsky]

Friday, 16 February 2001 [Samuel A. Rebelsky]

Monday, 16 September 2002 [Samuel A. Rebelsky]

Friday, 7 February 2003 [Samuel A. Rebelsky]


Disclaimer: I usually create these pages on the fly, which means that I rarely proofread them and they may contain bad grammar and incorrect details. It also means that I tend to update them regularly (see the history for more details). Feel free to contact me with any suggestions for changes.

This document was generated by Siteweaver on Tue Dec 9 14:00:08 2003.
The source to the document was last modified on Tue Nov 25 14:59:34 2003.
This document may be found at

You may wish to validate this document's HTML ; Valid CSS! ; Check with Bobby

Samuel A. Rebelsky,