Skip to content
Mischov edited this page Jan 20, 2014 · 19 revisions

Gate middleware is just standard Ring middleware, but Gate does a few things which makes it even nicer to use.


What is Ring Middleware?

Ring middleware is any function that accepts a handler and returns a function accepting a request.

(defn upperware
  [handler]
  (fn [request]
    (let [response (handler request)
          body (get response :body)]
      (assoc response :body (clojure.string/upper-case body)))))

Applying Middleware to Handlers

There are a bunch of different ways you can apply middleware to handlers with Gate.

First off, you can apply middleware to all the routes in a router by adding that middleware to the :middleware vector of a router's settings. In the following example the middleware upperware will be added to all of the routes in the router.

(defrouter your-router
  [{:name :hello
    :path "/hello"
    :get  (fn [_] "Hello!")}
   {:name :goodbye
    :path "/goodbye"
    :get  (fn [_] "Goodbye!")}]
  {:middleware [upperware]})

Many times, however, you don't want middleware to apply to all of your routes. In that case you can apply middleware to just a single route by adding a :middleware vector to that route. In the following example upperware will only be applied on the route :hello.

(defrouter your-router
  [{:name :hello
    :path "/hello"
    :middleware [upperware]
    :get  (fn [_] "Hello!")}
   {:name :goodbye
    :path "/goodbye"
    :get  (fn [_] "Goodbye!")}])

Middleware from a parent route is applied to all child routes. In the following example the route :greeter has the upperware applied to it because :greeter is a child route to :hello.

(defrouter your-router
  [{:name :hello
    :path "/hello"
    :middleware [upperware]
    :get  (fn [_] "Hello!")
    :children [
               {:name :greeter
                :path "/:name"
                :get (fn [req]
                        (let [name (get-in req [:params :name])]
                          (str "Hello, " name "!")))}]}])

You can even restrict middleware to a certain method of a route. In the following example upperware is applied to GET requests, but not to POST requests.

(defrouter your-router
  [{:name :hello
    :path "/hello"
    :get  {:handler (fn [_] "Hello!")
           :middleware [upperware]}
    :post (fn [_] "Nothing here!")}])

Combining Middleware

Middleware vectors accept middleware functions, as shown above, but they can also accept sequences of Ring middleware. This fact makes it exceedingly simple to combine middlewares that need to be used together into a single middleware.

Compojure has a middleware compojure.handler/api that combines together three ring middlewares and is defined like this:

(defn api
  [routes]
  (-> routes
      wrap-keyword-params
      wrap-nested-params
      wrap-params))

Gate has a similar middleware, defined thusly:

(def api
  [wrap-params
   wrap-nested-params
   wrap-keyword-params])

To use this combined middleware, you would just add it to a vector of middlewares like normal.

(defrouter your-router
  [{:name :hello
    :path "/hello"
    :middleware [api]
    :get  (fn [_] "Hello!")}])
Clone this wiki locally