"Mac Chan" emailmac@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) ,@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.