Description

Bindings for the FCGX API of libfcgi.

Author

Alex Drummond

Version

Usage

(require-extension fastcgi)

Download

fastcgi.egg

Documentation

This egg provides a high-level interface to the FCGX API of libfcgi, part of the FastCGI Devkit.

procedure: (fcgi-external-server-accept-loop SOCKET/PORT BACKLOG CALLBACK)

(Note that for backwards compatibility with previous versions of this egg, fcgi-accept-loop is a synonim for this function.) Given either the filename of a UNIX local socket (string) or a port (integer) as its first argument, this procedure opens a socket and starts a loop for accepting FastCGI requests. An exception is raised if there is an error opening/listening on the socket. Every time a request is accepted, the CALLBACK argument is called with four procedure arguments which will be refered to as 'in', 'out', 'err' and 'env' in the documentation below. The BACKLOG argument is passed to the listen system call.

If the callback returns #f, the accept loop is terminated.

procedure: fcgi-dynamic-server-accept-loop CALLBACK

This works exactly like fcgi-external-server-accept-loop, except that there are obviously no SOCKET/PORT or BACKLOG arguments. The function returns FCGI_LISTENSOCK_FILENO (see this section of the FastCGI spec), which will always be 0 (STDIN) in the current implementation.

procedure: (in [INT])

[This procedure is passed to the CALLBACK argument of fcgi-accept-loop.]

If called with no arguments, this procedure reads in as much data as possible from the input stream, returning #f if the stream is empty, and a string otherwise.

If called with a single integer argument >= 0, it reads exactly the specified number of characters from the stream (and will block indefinitely if the stream is empty or contains too few characters and no EOF is encountered). In either case, an exception is raised if there is an error reading from the stream.

If called with #f, the entire input stream is read in and discarded, and an empty string is returned. For backwards compatibility, you can also use any negative integer in place of #f.

Don't use (in) to read in post data, since there is no guarantee that it will read all of it. Instead, call in with the value of the HTTP_CONTENT_LENGTH or CONTENT_LENGTH environment variable, or use the fcgi-get-post-data procedure.

The variable *fcgi-slurp-chunk-size* determines the size of the input buffer which will be allocated by a zero-argument call to in. The value of this variable does not affect the maximum amount of input which can be read in, since additional buffers are automatically allocated as necessary (with increasing buffer size to increase efficiency).

procedure: (out STRING)

[This procedure is passed to the CALLBACK argument of fcgi-accept-loop.]

Writes STRING to the output stream, raising an exception if there is an error.

procedure: (err STRING)

[This procedure is passed to the CALLBACK argument of fcgi-accept-loop.]

Writes STRING to the error stream, raising an exception if there is an error.

procedure: (env [VARNAME [DEFAULT]])

[This procedure is passed to the CALLBACK argument of fcgi-accept-loop.]

If called with no arguments, this procedure returns a list of (name . value) pairs giving the name and value of every variable in the environment. If called with a single argument VARNAME, it returns the value of the specified variable, or #f if that variable is not set. VARNAME may optionally be followed by a second argument, which specifies a default value to be returned if the variable is not set. (env X) is thus equivalent to (env X #f).

Note that this procedure cannot be called after another request has been accepted, since libfcgi does not maintain environments from previous requests (you will most likely get a segfault). However, an old environment can easily be saved if necessary by storing the return value of (env).

procedure: (fcgi-get-post-data IN ENV)

Given an 'in' procedure and an 'env' procedure, this procedure returns a string containing the post data for the last request, or #f if the last request was not a post request. This procedure uses HTTP_CONTENT_LENGTH, or CONTENT_LENGTH if the former is not defined.

Examples

(require-extension fastcgi)

(fcgi-external-server-accept-loop
  "/tmp/fastcgi-socket-0"
  0
  (lambda (in out err env)
    (out "Content-type: text/html\r\n\r\n")
    (out "<html><body>")

    ;; Look up the value of the SERVER_NAME environment variable
    ;; and print it.
    (out "<b>This server is: </b>")
    (out (env "SERVER_NAME" "[unknown]"))
    (out "<br><br>")

    ;; Print the name and value of every environment variable.
    (out "<table><tr><th align=\"left\">Variable</th>")
    (out "<th align=\"left\")>Value</th></tr>")
    (for-each
      (match-lambda
        ((key . value)
         (out "<tr><td>")
         (out key)
         (out "</td><td>")
         (out value)
         (out "</td></tr>")))
      (env))
    (out "</table>")
    (out "<br><br>")

    ;; Print POST data, if there is any.
    (let ((post-data (fcgi-get-post-data in env)))
      (when post-data
        (out "The following post data was given:<br>")
        (out post-data)))
    (out "</body></html>")))