This example is tested with Guile 1.8.8, a nice lightweight open-source Scheme. The string-split
function is not part of the RSR5 standard, but shouldn’t be too hard to hand-code. I found a ready-made one, but apparently that one requires a single character split expression to be “listed,” which is to say, in the code below, #\=
would be replaced by '(#\=)
. As is always the case setting up new languages for CGI access, there is a need to tweak /etc/apache2/httpd.conf
. This is what I’m running with:
LoadModule cgi_module modules/mod_cgi.so ScriptAlias /cgi-bin/ /var/www/perl/ AddHandler cgi-script .cgi .pl .scm <Directory "/var/www/perl/"> Options +ExecCGI </Directory> <Directory "/var/www/scheme/"> Options +ExecCGI </Directory>
The Scheme script is pretty trivial. Its task is to display the environment variables and their values as a table. Here is the script:
#!/usr/bin/guile -s !# ; Convert an element of the return value of (environ), which is a single string ; in which the #\= character separates key and value, to a pair in which the ; key is the car (suitable for lookup via assoc) and the value is the cdr. If ; the string contains more than one #\=, only the first one is a delimiter; ; hence re-joining the cdr of the result of string-split. (define (assocify equate-string) (let ((stuff (string-split equate-string #\=))) (cons (car stuff) (string-join (cdr stuff) "=")))) ; Return the value of the environment variable QUERY_STRING (define (query-string) (cdr (assoc "QUERY_STRING" (map assocify (environ))))) ; Escape out angle brackets in text. This of course needs to be modified to ; cover all escapable characters. (define (deangulate text) (string-join (string-split (string-join (string-split text #\<) "<") #\>) ">")) ; Output one table row, containing an environment variable in the first column ; and its value in the right column. (define (display-environment-row key-value-pair) (let ((key (car key-value-pair)) (value (cdr key-value-pair))) (display "<tr><th>") (display key) (display "</th><td>") (display (deangulate value)) (display "</td></tr>\n"))) ; Output a table containing all of the environment variables and their values. (define (display-environment-table title) (display "<table>\n<caption>") (display title) (display "</caption>\n<thead>\n<tr><th>varable</th><th>value</th></tr>\n</thead>\n") (display "<tbody>\n") (let ((environment-assoc-list (map assocify (environ)))) (for-each display-environment-row environment-assoc-list)) (display "</tbody>\n") (display "</table>\n")) ; Output a <head> element for our web page. (define (display-head title) (display "<head>\n") (display "<meta http-equiv=\"Content-type\" content=\"text/html;charset=UTF-8\" />\n") (display "<link rel=\"stylesheet\" href=\"/scheme/cgi-test.css\" type=\"text/css\" />\n") (display "<title>") (display title) (display "</title>\n") (display "</head>\n")) ; Output the <body> element for our web page, which contains a table listing ; the environment variables and their values. (define (display-body title) (display "<body>\n") (display-environment-table title) (display "</body>\n")) ; Output a complete web page. (define (display-document title) (display "Content-type: text/html\n\n") (display "<!DOCTYPE HTML>\n") (display-head title) (display-body title) (display "</html>\n")) ; The function call that does it all: (display-document "Hello, world!")
Below is a screenshot. Notice the slash after the filename (cgi-test.scm
), and how this is reflected in the value of REQUEST_URI
. Also note the GET parameters, reflected in both REQUEST_URI
and QUERY_STRING
.
Leave a Reply