Fork me on GitHub

Hi, In my use case, I need to have different middle-ware for specific routes. This is the code:

(ns my-api.handler
  (:require [compojure.api.sweet :refer :all]
            [ring.util.http-response :refer :all]))

(defn echo0[handler]
  (fn [request]
    (prn "ECHO0" #_request)
    (handler request)

(defn echo1[handler]
  (fn [request]
    (prn "ECHO1" #_request)
    (handler request)

(def app
   (middleware [echo0] (swagger-routes))
   (context "/api" []
            :middleware [echo1]
            (GET "/test" [] (ok "1")))))
However, when I run the code echo0 is invoked for /api/test as well. Is there is any way to make those completely separate?


@happy.lisper you might want to try the #ring-swagger channel, that’s where the Metosin guys hang out I think


@happy.lisper if you want better control on when middleware is applied, there is also reitit-ring. More verbose syntax with no default middleware. It implements route-first architecture: the mw chain is only applied if there is a full route match. Your example would be:


Thx for this option, I will definitely consider it as well.


there is #reitit to get help if you want to try that


(require '[reitit.ring :as ring])
(require '[reitit.swagger :as swagger])
(require '[reitit.swagger-ui :as swagger-ui])

(def app
        {:get {:no-doc true
               :middleware [echo0]
               :handler (swagger/create-swagger-handler)}}]

        {:no-doc true
         :middleware [echo0]
         :handler (swagger-ui/create-swagger-ui-handler)}]

        {:middleware [echo1]}

         {:get (fn [_]
                 {:status 200, :body "1"})}]]])))

(app {:request-method :get, :uri "/swagger.json"})
(app {:request-method :get, :uri "/api-docs/index.html"})
(app {:request-method :get, :uri "/api/test"})


… but you would need to add coercion, formatting etc. mw yourself. there are examples for it, but no things like api from compojure-api.