Search code examples
clojurecompojure

Clojure compojure middleware and arrow syntax


I am trying to understand compojure middlewares :

The following code is from the compojure template :

(def app
  (wrap-defaults app-routes site-defaults))

Is it equivalent to the following ?

(def app
  (-> app-routes
      (wrap-defaults api-defaults)))

I am unsure about this since in the following code my-middleware2 is called before my-middleware1

(def app
  (-> api-routes
      (wrap-defaults api-defaults)
      (my-middleware1)
      (my-middleware2)))

Solution

  • You are correct:

    (def app
      (wrap-defaults app-routes site-defaults))
    

    Is equivalent to:

    (def app
      (-> app-routes
          (wrap-defaults api-defaults)))
    

    The arrow is called the Thread-First Macro and allows you to write nested s-expressions in a linear way.

    In your second example, it makes sense that my-middleware2 is called before my-middleware1 when an HTTP request comes in. You are creating a Ring Handler, not calling the middleware directly.

    (def app
      (-> api-routes
        (wrap-defaults api-defaults)
        my-middleware1
        my-middleware2))
    

    Is expanded to:

    (def app
      (my-middleware2 (my-middleware1 (wrap-defaults app-routes api-defaults))))
    

    When an HTTP request comes in, my-middleware2 handles it first, does something to it (i.e. extracts the session data), and then passes it along to the next middleware until one of them returns an HTTP response.

    Note: I took out the parens from (my-middleware1) and (my-middleware2). When used like that it means that my-middlware1 is a function that when called with no arguments, returns a middleware function. This might be what you wanted but is not common practice.