Okay, those are a lot of messages. I think your problem is that you don't completely understand how routes and middleware work.
Let's consider a single route as an example:
(GET "/:token" request get-token)
Here we're returning a function, get-token, from the route. If you return a function, Compojure passes it the request, and then returns the result of the function. So the above is equivalent to:
(GET "/:token" request (get-token request))
We could also get the token directly, instead of passing the entire request map:
(GET "/:token" [token] (get-token token))
By using a vector, we tell Compojure to find a parameter called token. This should explain why:
(GET "/:token" [request] (get-token request))
doesn't work. Because you're telling Compojure to find a parameter called request, which is obviously not your intention.
Let's go back to this code:
(GET "/:token" request (get-token request))
The GET macro will transform this into an anonymous function that looks a little like:
(fn [req]
(if (= (:request-method req) :get)
(if-let [route-params (route-matches "/:token" req)]
(let [request (assoc request :route-params route-params)]
(get-token request)))))
If either the request-method or route doesn't match, then nil is returned from the function. This indicates the function didn't match.
If the function did match, then the route parameters are associated with the request. In the above code I've assigned them only to :route-params for simplicity, but in practice they're also merged into :params as well.
This should tell you why your middleware wasn't seeing the parameters in the route, because your middleware surrounds the routes, but the route parameters are only assigned inside the route.
There are ways around this. Compojure has a function called wrap-routes, which is designed to apply middleware inside of a route. You can also apply the middleware inside the route, like so:
(GET "/:token" request (wrap-some-middleware get-token))
However, it's worth noting that Compojure is designed around the idea of controlling the flow of information. If I write something like:
(GET "/:token" request (get-token request))
Then any key in the request map could potentially affect get-token. But if I write:
(GET "/:token" [token] (get-token token))
Then only the value of the token parameter affects get-token. By giving the function only what it needs, we limit the number of things that can go wrong in the application.
You don't need to use Compojure's parameter syntax for this, but it's worth bearing in mind that you should be aiming to limit how functions interact. Clojure is designed around the notion of simplicity, which in this sense means reducing the number of interconnections in software.
- James