3

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)))
1
  • 1
    Compojure brings some convenient macros on top of Ring. To be precise, Middlewares are Ring's ones, not Compojure's. Commented Jan 12, 2015 at 5:07

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks it helps. And would a thread last macro make sense here ? What would be the common practice here ? Ex. when adding a json parser, where should it be ?
Thread last macro is not usually used with Ring middleware since the convention is (middleware handler options).
For JSON look at (wrap-json-body handler) from github.com/ring-clojure/ring-json and you should add it before any other handler that assumes the bodys request is a Clojure data structure.
this answered a lot of my questions about middleware and the thread-first, thanks a lot guys! =)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.