In Defense of Anagorism

political economy in the non-market, non-state sector

Author: Lorraine Lee

  • A simple CGI example in Scheme

    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 #\<) "&lt;") #\>) "&gt;"))
    
    
    
    ; 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.