在luminus项目的swagger设置中使用cprop env信息

时间:2018-08-06 15:54:54

标签: clojure luminus

我正在使用swagger为数据库访问程序提供API。在开发期间,我通常会运行2个版本,分别是我在登录时自动启动的dev版本和prod版本。我想在招摇的首页上显示一个不同的标题,这样我就不会意外删除我的实时数据库。到目前为止,我一直在swagger设置中手动编辑title字段,但这容易出错,在运行lein uberjar来生成产品版本之前,我常常忘记更改它。

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

screenshot of swagger html page

这是我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服务器之前成功启动的:

{: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}

我在这里缺少明显的东西吗?有没有必要采取其他步骤使环境地图对招摇设置可见?

编辑: 将呼叫从(:title env)更改为(env:title)会导致苹果酒劫持失败,并出现一条较长的错误消息/堆栈跟踪,其中包括:

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

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

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

因此,直到从招摇设置中调用env之后,它似乎才启动。我仍然不知道为什么当苹果酒劫持程序工作时,它清楚地显示config.env状态始于http服务器之前。 (请参见上文)

1 个答案:

答案 0 :(得分:0)

似乎(defstate env) 是需要deref进行原子修饰的原子。 Mount's README指向some examples 的测试。

您可以在(: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错误,请参见this issue,这大概意味着不需要deref。