33.18. The FastCGI Interface

33.18.1. Overview of FastCGI
33.18.2. Functions in Package FASTCGI
33.18.3. FastCGI Example
33.18.4. Building and configuring the FastCGI Interface

The FastCGI module speeds up CLISP CGI scripts launched by a Web server. Working with a FastCGI-enabled Web server such as Apache with mod_fastcgi, a CLISP program using the FastCGI protocol will run many times faster than a conventional CGI program. The performance improvements stem from the fact that the script's process remains running across HTTP requests, eliminating startup overhead and allowing for caching of data structures and other resources. This is the same approach used is in other languages (e.g., mod_perl for Perl).

When this module is present, *FEATURES* contains the symbol :FASTCGI.

33.18.1. Overview of FastCGI

Traditional CGI programs work by doing input/output with the Web server via the following channels:

  1. Examining environment variables; e.g., HTTP_USER_AGENT is the variable set by the Web server to name the browser used
  2. Reading from standard input. E.g., to get input data in a "method=POST" request
  3. Writing an HTTP response document (usually "Content-type: text/html") to the standard output, for eventual transmission back to the browser client
  4. Writing error messages to the standard error, usually captured by the Web server and logged in its log files.

FastCGI involves replacing calls the standard routines to do the above with calls in the FASTCGI package. These calls will then work exactly as before when the program is invoked as a CGI, but will also work when invoked by a FastCGI-enabled Web server.

FastCGI programs persist across HTTP requests, and thus incur startup overhead costs only once. For Lisp Web programs, this overhead can be substantial: code must be compiled and loaded, files and databases must be opened, etc. Further, because the program stays running from HTTP request to HTTP request, it can cache information in memory such as database connections or large in-memory data structures.

33.18.2. Functions in Package FASTCGI

Access to FastCGI is via these functions in package FASTCGI.

(FASTCGI:IS-CGI)
Returns T if the CLISP program has been launched as a traditional CGI rather than in FastCGI. In traditional CGI, program I/O is via operating system environment variables and standard file streams. Under FastCGI, I/O is done directly with the Web server via the FastCGI protocol.
(FASTCGI:ACCEPT) cgi-forms (FASTCGI:FINISH)

In FastCGI mode, the program loops, ACCEPTing to begin the execution of an HTTP request, and FINISHing to signal that the script is finished writing its response to the HTTP request. ACCEPT blocks until the next HTTP request comes in, returning T if there is a new request to handle, and NIL if no more HTTP requests will occur, usually because the Web server itself has terminated, in which case the FastCGI server loop should also exit.

A typical FastCGI top-level server loop looks like:

(do ()
    ((not (fastcgi:accept)))
  (run-my-script)
  (fastcgi:finish))

(FASTCGI:GETENV varname)
Use in place of EXT:GETENV to get the value of the environment variable named varname, which should be a string. Unlike EXT:GETENV, which accesses the actual host operating system environment, FASTCGI:GETENV obtains its environment via the Web server, over its FastCGI communications channel. For more information, see the FastCGI Web site. Returns NIL if varname is not defined in the operating system environment. See here for a list of useful variables. You must first have called ACCEPT and not yet have called FINISH.
(FASTCGI:WRITE-STDOUT string)
Use in place of standard Lisp calls which print to standard output (i.e., as part of the HTTP response). You must first have called ACCEPT and not yet have called FINISH.
(FASTCGI:WRITE-STDERR string)
Use in place of standard Lisp calls which print to standard error. Rather than being part of the HTTP response, data written to standard error are usually collected by the Web server in its error log. This is useful for diagnostic purposes.
(FASTCGI:SLURP-STDIN)
Reads in the entirety of standard input and returns it as a string. This is usually done for HTTP requests with METHOD="post", when the data are passed to the CGI script via standard input rather than via the environment variable QUERY_STRING. There is no way to read standard input in pieces, which could be a problem, say, for HTTP uploads of very large files.
(FASTCGI:OUT tree)
Like WRITE-STDOUT, except that tree may be an arbitrarily nested list structure containing (at the leaves) numbers and strings. For example, (FASTCGI:OUT '("foo" (" " 10 " " 20))) will write the string "foo 10 20". This function is useful when building strings in memory for display.

33.18.3. FastCGI Example

Below is a simple example CGI script using FastCGI.

#!/usr/local/bin/clisp -q -K full

(do ((count 1 (1+ count)))
    ((not (fastcgi:accept)) nil)
  (fastcgi:out "Content-type: text/plain" #\Newline #\Newline)
  (fastcgi:out
   "I am running in mode: " (if (fastcgi:is-cgi) "CGI" "FastCGI") #\Newline
   "This is execution no.: " count #\Newline
   "The browser string is '" (fastcgi:getenv "HTTP_USER_AGENT") "'" #\Newline)
  (fastcgi:finish))

33.18.4. Building and configuring the FastCGI Interface

It is necessary to download the FastCGI developers' kit, build it, and install it, before building CLISP with FastCGI support. You also need to upgrade your Web server to speak the FastCGI protocol. For Apache this means building in mod_fastcgi, either statically or dynamically, and then adding a line to your Apache config like:

     Addhandler fastcgi-script .fcgi

After that, you can convert foo.cgi by linking it to a script names foo.fcgi. Since a FastCGI script is also a valid CGI script, it can be run unmodified in either mode.


These notes document CLISP version 2.49.93+Last modified: 2018-02-19