5
votes

I am writing a web app that would require the hunchentoot web server. I have almost no working knowledge of hunchentoot, or any web server for that matter, and I am wondering how my app written in Common Lisp would serve pages to a web client. I have seen some excellent examples (e.g. Hunchentoot Primer, Lisp for the Web) esp. the one listed on the Hunchentoot page. Do you know where I can find more of such examples? Thanks.

2
What is it that you find lacking in the examples? If you don't say, chances are you'll get more links to examples that lack the same thing. - John Saunders
Well, I'd like to see more clearly how to connect the rest of the application's code to hunchentoot; just how the app should talk to hunchentoot. - Harrison
The link is dead, long live the new link: newartisans.com/2007/11/a-quick-hunchentoot-primer - tjb

2 Answers

8
votes

I am wondering how my app written in Common Lisp would serve pages to a web client.

Hunchentoot serves all things that are in its *dispatch-table*, which is just a list of dispatch handlers.

The simplest thing to do is to serve a static file. One typical example would be a CSS file:

(push (create-static-file-dispatcher-and-handler "/example.css"
                                                 "example.css")
      *dispatch-table*)

For a web application, you would most likely want to dynamically create a web page. You do this by defining a function that returns the page as a string (e.g. with CL-WHO), then creating a handler for this function:

(defun foo ()
  (with-html-output-to-string ; ...
  ))

(push (create-prefix-dispatcher "/foo.html" 'foo)
      *dispatch-table*)

You can eliminate a lot of boilerplate through macros, by the way:

(defmacro standard-page ((title) &body body)
  `(with-html-output-to-string (*standard-output* nil :prologue t :indent t)
     (:html :xmlns "http://www.w3.org/1999/xhtml"
          :xml\:lang "de"
          :lang "de"
          (:head 
           (:meta :http-equiv "Content-Type" 
                      :content "text/html;charset=utf-8")
           (:title ,title)
               (:link :type "text/css" 
              :rel "stylesheet"
              :href "/example.css"))
              (:body
               ,@body))))

(defmacro defpage (name (title) &body body)
  `(progn
     (defmethod ,name ()
       (standard-page (,title)
         ,@body))
     (push (create-prefix-dispatcher ,(format nil "/~(~a~).html" name) ',name)
           *dispatch-table*)))

The examples you have found should be sufficient to get you started, and if you run into problems, read the manual, then ask concrete questions.

2
votes

define-easy-handler registers the handler you are defining automatically in a global variable which gets checked when a HTTP request arrives (the variable is called *easy-handler-alist*). So it's being taken care of automatically. Do you want to use a handler of a different form than the one defined in the tutorial?

I think there is an example using Hunchentoot in the Elephant distribution (Elephant being a Persistent Object Database for Common Lisp.)