Dispatch mechanism (was: Re: [hunchentoot-devel] Re: hunchentoot authorization)

Michael Weber michaelw+tbnl at foldr.org
Sun Apr 13 10:49:13 UTC 2008


On Apr 13, 2008, at 03:21 , Cyrus Harmon wrote:
> I'd like to stay away from a full-fledged web framework ala UCW or  
> weblocks

Yes. please.  I use Hunchentoot primarily as a thin layer above HTTP,  
which shields me from dealing with the raw bytes on the wire.  Also, I  
have to say I haven't seen a convincing CL web framework yet.  They  
all seem to be UI centric, whereas I am dealing mostly with resources.

> I'm willing to 1) make this library totally hunchentoot-specific and  
> 2) if necessary propose modifications to hunchentoot that would  
> facilitate the implementation of this library.

I have no problem with that.  For me, the only reason to prefer  
something else over HT would be if I couldn't deploy behind mod_proxy,  
and then I'd probably rather write an adaptor for that situation  
(FastCGI, WSGI, ...).

> In particular, the hunchentoot dispatch stuff, while flexible,  
> could, I think, be improved in ways that would make the  
> implementation of this library more facile.

I actually find it overly flexible.  (This is perhaps another of the  
"organic growth" areas.)
There are several ways to plug into the dispatcher.  At the moment, I  
am using this:

   (defvar *toplevel-routing-table*
     (let ((rt (make-instance 'ht-routing-table)))
       (shiftf (get-routes rt) hunchentoot:*dispatch-table* rt)
       rt))

   (defmethod hunchentoot:dispatch-request ((table routing-table))
     (let ((controller (find-controller table *request*)))
       (handle-request controller *request*)))

However, another option for me would be to just push

   (lambda ()
     (hunchentoot:dispatch-request *toplevel-routing-table* *request*))

onto hunchentoot:*dispatch-table*.  And I haven't even look at the  
meta-dispatcher stuff and starting multiple server instances.

There's probably a way to simplify all this without losing any power  
or convenience.


Cheers,
Michael
BTW: The reasons behind all this:
* I like the mappings between URLs and handlers a little more  
descriptive than bare function designators, for example, to print out  
the mapping or appropriate Apache config stanzas.  So I use CLOS  
objects.  Alternatively, I could have used (:metaclass funcallable- 
standard-class).

* I like to be able to rearrange URL mappings while running in  
development.  (make-prefix-matcher "/foo/") is a little too static for  
my taste.

* I bundle several end points (handlers) together (into a  
"controller"), because on their own, they don't make sense.  Also, the  
end points don't know anything about the URL they are mapped to.

* I can deploy a single controller several times on different URL  
routes (e.g., "/~foo/...", "/~bar/...", etc.).  The routing dissects  
the URL and provides parameters to controller and end points.   
Deploying multiple "web apps" comes for free.

* Authentication is done by Apache, for the moment, because it's  
convenient and works for files served statically, too.

* Authorization is done by Apache and by controllers (for, say, DB  
access), because all end points are usually subject to the same  
rules.  End points can do additional checks with finer granularity.




More information about the Tbnl-devel mailing list