Search code examples
clojureswaggercompojure

How can I manage multiple compojure contexts via composition?


(please note, the following example has been simplified from a much larger example)

(ns example-app
  (:require [ring.util.http-response :refer :all]
            [compojure.api.sweet :refer :all]
            [schema.core :as s]))

(defapi my-api
  {:formats [:json]}
  (context* "v0" [] 
    :tags ["unversioned"]
    (GET* "api-endpoint-1" []
      :return Long
      :summary "example endpoint v0/1"
      (ok 123)))
  (context* "v1" []
    :tags ["version-1"]
    (GET* "api-endpoint-2 []
      :return String
      :summary "example endpoint v1/1"
      (ok "hello"))))

So, given the above, I'd like to rewrite it as:

(def context-v0 
  (context* "v0" [] 
    :tags ["unversioned"]
    (GET* "api-endpoint-1" []
      :return Long
      :summary "example endpoint v0/1
      (ok 123)))
(def context-v1
  (context* "v1" []
    :tags ["version-1"]
    (GET* "api-endpoint-2 []
      :return String
      :summary "example endpoint v1/1"
      (ok "hello")))      
(defapi my-api
   context-v0
   context-v1)

This would allow me to support older versions of the api while creating new ones without having to worry about a gigantic single file that could get accidentally clobbered by careless future me.

As it stands right now, doing this causes swagger to run, but the extracted contexts do not load. Only ones left in the first format show up.

Do I have to explode this out into its macroexpanded version to get it to work? Any better way?


Solution

  • I think this should work.

    (def v1 '("v0" [] 
              :tags ["unversioned"]
              (GET* "api-endpoint-1" []
                  :return Long
                  :summary "example endpoint v0/1"
                  (ok 123)))
    (defapi my-api
            (apply context* v0)
            (apply context* v2))