如何通过组合管理多个 compojure 上下文?

How can I manage multiple compojure contexts via composition?

(请注意,以下示例是从一个更大的示例中简化而来的)

(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"))))

所以,鉴于上述情况,我想将其重写为:

(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)

这将使我能够在创建新版本的同时支持 api 的旧版本,而不必担心一个巨大的单个文件可能会被粗心的未来我意外破坏。

按照目前的情况,这样做会导致 swagger 运行,但不会加载提取的上下文。只显示第一种格式的剩余内容。

我是否必须将其分解为宏扩展版本才能使其正常工作?还有更好的方法吗?

我认为这应该可行。

(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))

只是为遇到此问题的其他人添加更多替代方案。

(def v1-routes
  (routes
    (GET "/a" [] (ok "Stable A"))
    (GET "/b" [] (ok "Stable B"))))

(def v0-routes
  (routes
    (GET "/a" [] (ok "Next gen A"))
    (GET "/b" [] (ok "Next gen B"))))

(defapi myapi
  (context "/v0" [] v0-routes)
  (context "/v1" [] v1-routes))

遵循这条路线的一个很好的副作用是可以更改 v*-routes 的 "mounting point" 而无需直接更改它们。子路由不知道它们的父上下文。