[hunchentoot-devel] Middleware with Hunchentoot

Robert Uhl eadmund42 at gmail.com
Fri Jul 20 15:24:22 UTC 2007


"Mac Chan" <emailmac at gmail.com> writes:
>
>>   (create-regex-dispatcher "/foo/bar?baz" (null-effect #'my-handler))
>
> Sorry but your null-effect example doesn't really show the benefit of
> using this middleware wrapper. I can't really tell why I'd want to do
> something like this.

Here's a more realistic example:

  (def-middleware authentication (request)
    (if (apply #'authenticatedp (multiple-value-list (authorization)))
      (call-next-middleware)
      (require-authentication)))

Then the user can force a page to use authentication with:

  (create-regex-dispatcher "/foo/bar" (authentication #'my-handler))

Instead of having to write any code inside MY-HANDLER.

I've not fully fleshed out the idea yet, of course.

Ideally, it'd be possible to specify a single stack of middleware to use
on the _entire_ Hunchentoot server, but I've not yet figured out where
to do that.

>> Obviously middleware could be chained:
>>
>>   (create-regex-dispatcher "/foo/bar?baz"
>>                            (authentication (caching #'my-handler)))
>
> I'm really confused here. I assume that both authentication and
> caching are macros, right?

Nope, just functions created by DEF-MIDDLEWARE.  Something like:

(defun authentication (handler-or-middleware)
  (lambda (request)
    (if (apply #'authenticatedp (multiple-value-list (authorization)))
      (when (handler-or-middleware)
        (funcall handler-or-middleware request))
      (require-authentication))))

That is, they're just functions which create handler wrappers.

> If they are functions, then what do they do? what does the middleware
> framework do? and what all these buy us?
>
> If they are macros, then why not just define them straightforwardly?
>
> (defmacro with-authentication (&body body)
>  `(progn
>    (require-authorization)
>    , at body))

Because having to write:

(defun display-foo-page (request)
  (with-authentication
    (with-caching
      (with-etags
        (with-gzip
          (do-stuff))))))

Gets unwieldy.

But on reflection you're right: handler-specific code is probably best
expressed as a WITH- macro.  Normally one would probably be doing
something like:

(defun display-foo-page (request)
  (with-authorisation (maintainer editor)
    (do-stuff)))

Without more than a single macro.  The other stuff I was thinking of
doing (caching, URL cleaning, gzipping) should really be run around
_all_ handlers, not just a few.  I don't think Hunchentoot exposes a
good place for this kind of thing.  URL cleaning is easy enough: put it
at the beginning of *dispatch-table* where it'll get called early on and
can rewrite (request-uri).  But where would one put gzipping?  It has to
do its magic _after_ any handler runs, and process the handler's output.
It'd be nicest to specify it once, and not in every single handler's
code.

-- 
Robert Uhl <http://public.xdi.org/=ruhl>
I used to think that the brain was the most wonderful organ in my
body.  Then I realised who was telling me this.    --Emo Phillips




More information about the Tbnl-devel mailing list