Next: , Previous: filesystem, Up: Top


11 (www server-utils cgi-prep)

Often the server cannot do everything by itself, and makes use of external programs invoked in a common gateway interface environment. These programs are also known as CGI scripts.

The (www server-utils cgi-prep) module provide a procedure to set up such an environment. Actually invoking the CGI script is not covered.

— Procedure: cgi-environment-manager initial-bindings

Return a closure encapsulating initial-bindings, a list of pairs (name . value), where name is a symbol listed in the following table, and value is a string unless otherwise noted.

If name is not recognized, signal "unrecognized key" error. Encapsulation includes name=value formatting.

The closure accepts these commands:

name value
Encapsulate an additional binding. name and value are as above.
#:clear!
Drop the additional bindings. Note that initial bindings can never be dropped (you can always create a new closure).
#:environ-list
Return a list of strings suitable for passing to environ or as the second argument to execle.

Any other command results in a "bad command" error.

example

Following is a simple example of how to use cgi-environment-manager. A more realistic example would include port and connection management, input validation, error handling, logging, etc. First, we set up the manager with more-or-less constant bindings.

     (define M (cgi-environment-manager
                 '((server-software . "FooServe/24")
                   (server-protocol . "HTTP/1.0")
                   (server-port . 80))))

Later, we add connection-specific bindings. We use read-first-line from the parse-request module.

     (define PORT ...)
     (define UPATH (list-ref (read-first-line PORT) 1))
     (define QMARK (string-index UPATH #\?))
     (define CGI (substring UPATH 0 QMARK))
     
     (M 'script-name CGI)
     (M 'query-string (substring UPATH (1+ QMARK)))

Lastly, we spawn the child process, passing the constructed environment as the second arg to execle, and drop the connection-specific bindings afterwards.

     (let ((pid (primitive-fork)))
       (if (zero? pid)
           (execle CGI (M #:environ-list) (list CGI)) ; child
           (waitpid pid)))                            ; parent
     
     (M #:clear!)

Now we can re-use M for another connection.