Codebase list comidi-clojure / b116202
(TK-248) Add mechanism for wrapping intermediate comidi routes with middleware Add a new wrap-routes function that is analagous to compojure's that wraps each leaf handler with a middleware. Scott Walker 8 years ago
2 changed file(s) with 70 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
264264 [method pattern bindings body]
265265 `[~pattern {~method (handler-fn* ~bindings ~body)}])
266266
267 (defn wrap-routes*
268 "Help function, used by compojure-like wrap-routes function to wrap leaf handlers
269 in the bidi route with the middleware"
270 [loc middleware]
271 (let [node (zip/node loc)
272 loc (cond
273 (fn? node) (zip/replace loc (middleware node))
274 (map? node) (zip/replace
275 loc
276 (reduce-kv (fn [m k v] (assoc m k (middleware v))) {} node))
277 :else loc)]
278 (if (zip/end? loc)
279 loc
280 (wrap-routes* (zip/next loc) middleware))))
281
267282 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
268283 ;;;; Public - core functions
269284
295310 :match-context match-context))))))
296311
297312 (schema/defn ^:always-validate
298 routes :- bidi-schema/RoutePair
313 wrap-routes :- bidi-schema/RoutePair
314 "Wraps middleware around the handlers at every leaf in the route in a manner
315 analagous to compojure's wrap-routes function"
316 [routes :- bidi-schema/RoutePair
317 middleware :- (schema/pred fn?)]
318 (-> routes
319 zip/vector-zip
320 (wrap-routes* middleware)
321 zip/root))
322
323 (schema/defn ^:always-validate
324 routes :- bidi-schema/RoutePair
299325 "Combines multiple bidi routes into a single data structure; this is largely
300326 just a convenience function for grouping several routes together as a single
301327 object that can be passed around."
303329 ["" (vec routes)])
304330
305331 (schema/defn ^:always-validate
306 context :- bidi-schema/RoutePair
332 context :- bidi-schema/RoutePair
307333 "Combines multiple bidi routes together into a single data structure, but nests
308334 them all under the given url-prefix. This is similar to compojure's `context`
309335 macro, but does not accept a binding form. You can still destructure variables
287287 routes->handler
288288 wrap-with-fake-match-context)]
289289 (is (= "bar!" (handler {:uri "/bunk"}))))))
290
291 (deftest wrap-leaves-with-middleware-test
292 (let [inner-middleware (fn [handler]
293 (fn [request]
294 (update-in (handler request) [:body] #(str "inner-" %))))
295 bb-wrapper-middleware (fn [handler]
296 (fn [request]
297 (update-in (handler request) [:body] #(str "bb-wrapper-" %))))
298 outer-middleware (fn [handler]
299 (fn [request]
300 (update-in (handler request) [:body] #(str "outer-" %))))
301 aa-route (GET "/aa" request "aa!")
302 bb-route (ANY "/bb" request "bb!")
303 cc-route (ANY "/cc" request "cc!")
304 dd-route (DELETE "/dd" request "dd!")
305 ee-route (GET "/ee" request "ee!")
306 ff-route (ANY "/ff" request "ff!")
307 left-routes (context "/left" aa-route bb-route)
308 middle-routes (context "/middle" cc-route dd-route)
309 right-routes (context "/right" ee-route ff-route)
310 handler (-> (routes left-routes middle-routes right-routes) routes->handler)]
311 (testing "Routes without middleware applied"
312 (is (= (:body (handler {:uri "/left/aa" :request-method :get})) "aa!"))
313 (is (= (:body (handler {:uri "/left/bb" :request-method :post})) "bb!"))
314 (is (= (:body (handler {:uri "/middle/cc" :request-method :get})) "cc!"))
315 (is (= (:body (handler {:uri "/middle/dd" :request-method :delete})) "dd!"))
316 (is (= (:body (handler {:uri "/right/ee" :request-method :get})) "ee!"))
317 (is (= (:body (handler {:uri "/right/ff" :request-method :delete})) "ff!")))
318 (testing "Routes but now with middleware applied"
319 (let [wrapped-bb-route (-> bb-route (wrap-routes bb-wrapper-middleware))
320 left-routes (-> (context "/left" aa-route wrapped-bb-route)
321 (wrap-routes inner-middleware)
322 (wrap-routes outer-middleware))
323 middle-routes (context "/middle" cc-route dd-route)
324 right-routes (-> (context "/right" ee-route ff-route) (wrap-routes outer-middleware))
325 handler (-> (routes left-routes middle-routes right-routes) routes->handler)]
326 (is (= (:body (handler {:uri "/left/aa" :request-method :get})) "outer-inner-aa!"))
327 (is (= (:body (handler {:uri "/left/bb" :request-method :post})) "outer-inner-bb-wrapper-bb!"))
328 (is (= (:body (handler {:uri "/middle/cc" :request-method :get})) "cc!"))
329 (is (= (:body (handler {:uri "/middle/dd" :request-method :delete})) "dd!"))
330 (is (= (:body (handler {:uri "/right/ee" :request-method :get})) "outer-ee!"))
331 (is (= (:body (handler {:uri "/right/ff" :request-method :delete})) "outer-ff!"))))))