The following text describes how to setup the TBNL Lisp web toolkit with SBCL on Linux and shows a simple web application. See the TBNL homepage for more information about TBNL web toolkit.
I've tested it on a Debian Sarge system, but it should work on most Linux systems, too.
For Debian and if you want to use the latest SBCL, login as root and execute the following commands for updating your kernel and removing old sbcl installations.
Note: you don't need the kernel-image package, if you have already a 2.6 kernel (you can check this with "uname -r").
aptitude remove sbcl aptitude install kernel-image-2.6-386 (don't do this, if you have 2.6 already installed)
Note: Skip this chapter, if you don't want to use the mod_lisp Apache module, if you want to serve your web pages from TBNL immediatly, without Apache.
To compile mod_lisp2.c (instead downloading it from my homepage, you can get the latest version of mod_lisp from the fractal concept homepage, if you like).
aptitude install apache2-threaded-dev wget http://www.frank-buss.de/lisp/mod_lisp2.c apxs2 -c -i -a mod_lisp2.c
This adds automaticly a LoadModule line to /etc/apache2/httpd.conf. Edit the file and add the mod_lisp configuration. The httpd.conf file should look like this:
LoadModule lisp_module /usr/lib/apache2/modules/mod_lisp2.so LispServer 127.0.0.1 3000 "tbnl" <Location /tbnl> SetHandler lisp-handler </Location>
Restart Apache2 with "/etc/init.d/apache2 restart". Now download sbcl-0.9.12 and install it like this:
tar -xjf sbcl-0.9.12-x86-linux-binary.tar.bz2 cd sbcl-0.9.12-x86-linux sh install.sh
Now add a new use "lisp" (for security reasons the TBNL Lisp process will run with this user, but you can start it from root, too, if you don't care) and install all needed Lisp libraries:
adduser --disabled-password lisp su lisp cd wget http://www.frank-buss.de/lisp/tbnl-starterkit.tgz tar -xzf tbnl-starterkit.tgz
My TBNL startkit contains Pierre R. Mai's MD5, Kevin Rosenberg's KMRCL and CL-BASE64, Janis Dzerins' RFC2388 and Edi Weitz' TBNL, CL-PPCRE, CL-WHO and URL-REWRITE. You can download the latest version of theses packages from their homepages, if you like.
Now start "sbcl" from the Lisp user account and start TBNL like this:
(require "asdf") (loop for dir in '("cl-base64-3.3.1" "tbnl-0.9.8" "md5-1.8.5" "cl-ppcre-1.2.13" "url-rewrite" "rfc2388" "kmrcl-1.85" "cl-who-0.6.0") do (push (truename (make-pathname :directory `(:relative ,dir))) asdf:*central-registry*)) (asdf:oos 'asdf:load-op 'cl-who) (asdf:oos 'asdf:load-op 'tbnl) (tbnl:start-tbnl)
After lots of loading and compiling message (will be fewer when starting again, because the SBCL has compiled all packages) the last message should be "#<KMRCL:LISTENER port 3000>".
Note: this was tested with LispWorks 4.3.7 (you can download a free personal edition from their website), but it should work with other Lisp implementations, too.
Download the TBNL starterkit and unpack it (if you can't unpack it, install 7-Zip, which can handle tgz archives). Start your Lisp implementation and enter this (this assumes that you have unpacked the packages to "c:\data\projects\asdf", change this, if you have unpacked it to another location and skipt the ASDF loading, if you have already asdf installed)
(load "/data/projects/asdf/asdf.lisp") (loop for dir in '("cl-base64-3.3.1" "tbnl-0.9.8" "md5-1.8.5" "cl-ppcre-1.2.13" "url-rewrite" "rfc2388" "kmrcl-1.85" "cl-who-0.6.0") do (push (truename (make-pathname :directory (list :absolute "data" "projects" "asdf" dir))) asdf:*central-registry*)) (asdf:oos 'asdf:load-op 'cl-who) (asdf:oos 'asdf:load-op 'tbnl) (tbnl:start-tbnl)
Now create a sample page and register it in the dispatch table:
(defpackage :name-list (:use :cl :tbnl :cl-who #+sbcl(:sb-ext))) (in-package :name-list) (defparameter *names* '()) (defmacro with-html (&body body) `(with-html-output-to-string (*standard-output* nil :prologue t) ,@body)) (defun main-page () (let ((name (post-parameter "name"))) (no-cache) (with-html (:html (:head (:title "Name List Demo with TBNL")) (:body (:h1 "Name List Demo with TBNL") (when name (push name *names*) (htm (:p (esc name) " was added."))) (:p "Enter a name") (:p (:form :method :post (:input :name "name" :size "50") (:input :type "submit" :value "Add"))) (:p "Name list:" (:ul (loop for name in *names* do (htm (:li (esc name))))))))))) (setq *dispatch-table* (list (create-prefix-dispatcher "/tbnl" 'main-page)))
Finally you can load the web page with http://127.0.0.1/tbnl/ (or http://127.0.0.1:3000/tbnl/, if you don't use the Apache proxy and replace 127.0.0.1 with your server name, if you access it remotly) you should see a page like this:
When a name is entered, it appears in the name list. Try entering *names* at the REPL and you'll see all names entered so far. If you want to run the application after logout from an remote server, use the screen command or detachtty.
This is only the beginning, on the TBNL homepage is the rest described, e.g. that you have to set *show-lisp-backtraces-p* to t, if you want to see the backtrace of failed functions in /var/log/apache2/error.log and links to tutorials with more complex web applications.
1. Mai 2006, Frank Buß