Next: cookies, Previous: filesystem, Up: Top
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.
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.
server-hostnamegateway-interfaceserver-port(integer)request-methodpath-infopath-translatedscript-namequery-stringremote-hostremote-addrauthentication-typeremote-userremote-identcontent-typecontent-length(integer, or#f)http-user-agenthttp-cookieserver-softwareserver-protocolhttp-accept-types(list of strings)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
environor as the second argument toexecle.Any other command results in a "bad command" error.
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.