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

Cyrus Harmon ch-tbnl at bobobeach.com
Sun Apr 13 19:27:33 UTC 2008


On Apr 13, 2008, at 3:49 AM, Michael Weber wrote:

> 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:

Yes, I think this is part of the challenge here. There are many ways  
to plug the sort of functionality I'm thinking of into hunchentoot.  
I'm not satisfied with the current approach taken by hunchentoot-auth  
and the myriad of choices for plugging this stuff in is what initially  
precipitated this discussion.

At the risk of taking this discussion from the philosophical to the  
practical, allow me to discuss some options for wedging in the  
authorization stuff.

+ authorized-page macro

The existing approach is an authorized-page -style macro that wraps  
each page and does the following:

* check if an https connection is required and if so that we're  
actually using an https connection otherwise, redirect to an https  
page on the appropriate port.
* either check that the supplied user and password are correct or that  
the user's session was properly authenticated. If necessary, squirrel  
away the user name in a per-session hash-table and set a flag that in  
a per-session hash-table that the user is authenticated.

The disadvantage of this approach is that it requires wrapping the  
code that generates each page with the authorized-page macro. One  
can't take arbitrary request handling code and make the page require  
authorization without somehow wrapping it, or another function that  
calls it, with this macro.

+ *meta-dispatcher*

One could rig up *meta-dispatcher* such that it checked for  
authorization and possibly redirect things along the way. The problem  
with this is that there is only one meta-dispatcher, so you only get  
to do this once per hunchentoot instance.

And, of course, one could override the value of *dispatch-table*,  
which is what the default *meta-dispatcher* returns.

+ server-dispatch-table

Similarly to the case of *meta-dispatcher*, one could use the dispatch- 
table slot of the server instance to hijack the dispatch and check for  
authentication. But it's not clear to me how the elements of this  
table should be ordered.

Interestingly, there's a dispatch-request generic function that could  
be used with a suitably defined class.

Clearly there's plenty of rope for extensibility here, the challenge,  
for hunchentoot-auth at least, is figuring which of these hooks to  
exploit.

>  (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.

Right. Multiple server-instances is another issue and it becomes  
important for what i'm doing because I use two server instances, one  
for http and one for https. There's no built-in infrastructure for  
managing multiple "servers". One could imagine some sort of meta- 
server (or renaming the server class to a listener and allowing for  
the server to have multiple listeners, but I guess that's just a  
nomenclature issue).

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

Right.

> 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 agree. I like having more of the "metadata" kept with the function  
too.

> * 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.

Hmm... I've taken the perhaps crazy approach of using ht for  
everything, static files, CGI scripts, etc...

> * 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.

Thanks for your comments,

Cyrus




More information about the Tbnl-devel mailing list