On Thu, Jul 19, 2007 at 10:11:58PM -0600, Robert Uhl wrote:
From Python's WSGI I've gotten the idea of middleware--that is, stuff
which runs around user-defined code in some user-defined order. A null-effect middleware function might be defined like this:
(defun null-effect (request next) (when next (funcall next request)))
One can see how a middleware function could set things up for the user-defined handler, could decide whether or not to call the user's handler and could override whatever that handler returns.
A convenience macro def-middleware might make it possible to write the null-effect function like this:
(def-middleware null-effect (request) (call-next-middleware))
And the user might be able to create a dispatcher thus:
(create-regex-dispatcher "/foo/bar?baz" (null-effect #'my-handler))
Obviously middleware could be chained:
(create-regex-dispatcher "/foo/bar?baz" (authentication (caching #'my-handler)))
Question: does this seem like a reasonable way to handle middleware, particularly authentication/authorisation mechanisms? I'm fairly new to Lisp, but it _seems_ like it's a fairly Lispy way to go about things.
Thoughts?
These are called "closures".
Here's a function I use in several places:
(defun call-with-protection (&key username password realm function) "Return a closure that calls FUNCTION if the remote username and password match USERNAME and PASSWORD, or returns an authorization required response otherwise." (lambda () (multiple-value-bind (web-username web-password) (authorization) (if (and web-username web-password (string= web-username username) (string= web-password password)) (funcall function) (require-authorization realm)))))
Here's an example use;
(wf:serve-function (wf:call-with-protection :username "blubba" :password "frink" :realm "roflbot" :function 'recent-page) "/roflbot/recent")
The FUNCTION argument to CALL-WITH-PROTECTION could be another closure generator, and these could be chained as much or as little as you like.
Zach