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