2

我正在使用 swagger 为数据库访问程序提供 API。在开发过程中,我通常运行 2 个版本,即我在登录时自动启动的开发版本和生产版本。我想在大张旗鼓的首页上显示一个不同的标题,这样我就不会意外地破坏我的实时数据库。到目前为止,我一直在 swagger 设置中手动编辑标题字段,但这很容易出错,我经常在运行lein uberjar构建 prod 版本之前忘记更改它。

环境设置似乎是一种理想的方式来做到这一点。luminus lein 模板已经使用了一个从 dev 和 prod 配置文件构建的环境映射,它工作正常,允许我为 2 个构建自动指定不同的端口。我在其中添加了一个条目,它给了我一个在 prod 和 dev 版本中不同的标题。我可以从 repl 中看到它,但是将它包含在 swagger 规范中只会给出null.

swagger html页面截图

这是我的 photo-api.routes.services.clj 文件开头的 :swagger 定义:

(ns photo-api.routes.services
  (:require [cheshire.core                     :as json]
            [compojure.api.sweet               :refer :all]
            [image-lib.images                  :as ilim]
            [image-lib.preferences             :as ilpf]
            [image-lib.projects                :as ilpr]
            [image-lib.write                   :as ilwr]
            [photo-api.db.core                 :as db]
            [photo-api.config                  :refer [env]]
            [photo-api.routes.helpers.build    :as build]
            [photo-api.routes.helpers.keywords :as keywords]
            [photo-api.routes.helpers.open     :as open]
            [photo-api.routes.helpers.photos   :as photos]
            [photo-api.routes.helpers.projects :as projects]
            [ring.util.codec                   :refer [url-decode]]
            [ring.util.http-response           :refer [ok]]
            [schema.core                       :as s]
            [clojure.string                    :as str]))

(defapi service-routes
  {:swagger {:ui "/swagger-ui"
             :spec "/swagger.json"
             :data
             {:info
              {:version "1.0.1"
               ;; Switch to correct title before lein uberjar
               ;; TODO Automate this so swagger page always shows dev or prod version
               ;;:title "Photo API"
               :title (:title env)
               :description "Access a mongo database containing details of photos"}}}}

注释掉的 :title 规范工作正常,但(:title env)调用没有,尽管它与我可以从 repl 成功使用的调用完全相同。我相信环境图是作为 photo-api.config 的一部分构建的,并且从我启动服务器时的启动消息来看,它看起来像是在 http-server 之前成功启动的:

{:started
 ["#'photo-api.config/env"
  "#'photo-api.db.core/db*"
  "#'photo-api.db.core/db"
  "#'photo-api.handler/init-app"
  "#'photo-api.handler/app"
  "#'photo-api.core/http-server"]}
user> 

这是 photo-api.config,与 luminus 默认值相同:

(ns photo-api.config
  (:require [cprop.core :refer [load-config]]
            [cprop.source :as source]
            [mount.core :refer [args defstate]]))

(defstate env :start (load-config
                       :merge
                       [(args)
                        (source/from-system-props)
                        (source/from-env)]))

和 dev config.edn 文件:

{:title "**** Photos Development API ****"
 :dev true
 :port 31999
 ;; when :nrepl-port is set the application starts the nREPL server on load
 :nrepl-port 57251}

我在这里遗漏了一些明显的东西吗?是否需要另一个步骤才能使 env 地图对 swagger 设置可见?

编辑:将调用从更改(:title env)为 (env :title) 会导致 cider-jack-in 失败,并出现很长的错误消息/堆栈跟踪,其中包括:

Caused by: java.lang.ClassCastException: mount.core.DerefableState cannot be cast to clojure.lang.IFn

再次将其更改为(@env :title)then 会给出类似长的错误消息/堆栈跟踪,其中包含:

Caused by: java.lang.ClassCastException: mount.core.NotStartedState cannot be cast to clojure.lang.IFn, compiling:(services.clj:29:23)

所以看起来 env 直到从 swagger 设置调用它之后才开始。我仍然不知道为什么当 cider-jack-in 确实起作用时,它清楚地显示了 config.env 状态在 http-server 之前开始。(看上面)

4

1 回答 1

0

它看起来像是(defstate env) 一个需要deref编辑的原子。Mount 的 README指向一些示例的测试。

你可以(:title @env)试试service-routes

(defapi service-routes
  {:swagger {:ui "/swagger-ui"
             :spec "/swagger.json"
             :data
             {:info
              {:version "1.0.1"
               ;; Switch to correct title before lein uberjar
               ;; TODO Automate this so swagger page always shows dev or prod version
               ;;:title "Photo API"
                 :title (:title @env) ;;;--------> UPDATED
                 :description "Access a mongo database containing details of photos"}}}}

编辑 -

不是一个原子。请参阅此问题以了解相同的 deref 错误,这可能意味着不需要 deref。

于 2018-08-07T16:13:49.467 回答