In Defense of Anagorism

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

An IndieWeb Webring 🕸💍
mastodon friendica codeberg exercism oeis neocities

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.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

To respond on your own website, enter the URL of your response which should contain a link to this post’s permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post’s URL again. (Find out more about Webmentions.)