The easy-routes
library makes it easy and fast to define Rails-like HTTP
routes for Hunchentoot. It has the concept of decorators which are functions
that form part of the request handling sequence but not part of the main
request handler. Decorator functions are usually general functions which are
applicable to many request handlers, for example, to set up a database
connection before handling a request.
Parameterless decorators
Most decorators are simple functions which do not take any parameters from the request handler. The DB connection decorator can be defined as below:
(defun @db (next)
(postmodern:with-connection *db-spec*
(funcall next)))
All decorators take the next
parameter which is the function that should be
called after this decorator has completed its task. The parameter is supplied
by easy-routes
.
A route that uses a decorator is defined like this:
(defroute api-handler ("/api"
:method :get
:decorators (@db @auth))
...)
The :decorators
keyword takes a list of decorator names in the order they
need to be executed. In the example above the @db
function will run, followed
by the @auth
function and then api-handler
. Since @auth
runs after @db
it can assume an open database connection. Note that the next
parameter is
not mentioned anywhere.
Parameterised decorators
For more complex cases where the decorator needs input from the route handler, it can be defined with extra parameters like this:
(defun @check (predicate http-error next)
(if (funcall predicate)
(funcall next)
(http-error http-error)))
The next
parameter must be last in the parameter list.
With a predicate function defined like below,
(defun test-p ()
...)
a route handler can be defined like this:
(defroute api-handler
("/api"
:method :get
:decorators (@db @auth
(@check test-p hunchentoot:+http-forbidden+))
)
...)
Decorators with additional parameters are passed as a list with the decorator
name as the first list item followed by the parameters, excluding next
. The
list is not quoted.