如何只在`:swagger {:deprecated true}`时使中间件设置响应头?

问题描述 投票:0回答:1

我们使用compojure-api在我们的环形应用程序中为我们提供了一些不错的swagger集成。 :swagger {:deprecated true} meta就像一个冠军,可以让swagger页面正确,但我要求我在路线为:swagger {:deprecated true}时在响应上放置一个特定的标题。我正在努力弄清楚如何使用我一直用来做类似响应头操作的中间件模式来做到这一点。

(ns bob.routes
  (:require [clojure.tools.logging :as log]
            [compojure.api.sweet :refer :all]
            [ring.util.http-response :as status]
            [schema.core :as s]
            [ring.swagger.schema :as rs]))

(s/defschema BobResponse {:message (rs/describe String "Message")})

(defn wrap-bob-response-header [handler]
  (fn [request]
    (let [response (handler request)]
      ;; can I reach into the request or the response to see what
      ;; route served this and if it has the :swagger {:deprecated true}
      ;; meta on it and NOT emit the x-bob header if it does?
      (assoc-in response [:headers "x-bob"] "Robert"))))

(defroutes bob-routes
  (context "" []
    :middleware [wrap-bob-response-header]
    :tags ["bob"]
    :description ["Tease out how to do swagger driven response header"]
    (GET "/notdeprectated" [:as request]
      :swagger {:deprecated false}
      :new-relic-name "GET_notdeprecated"
      :return BobResponse
      (status/ok {:message "All is well"}))
    (GET "/isdeprecated" [:as request]
      :swagger {:deprecated true}
      :new-relic-name "GET_isdeprecated"
      :return BobResponse
      (status/ok {:message "You came to the wrong neighborhood."}))))

如何修改wrap-bob-response-header只在x-bob的路线上发出:swagger {:deprecated true}

clojure compojure ring compojure-api
1个回答
1
投票

使用Compojure-API,可以在它们定义的路径上下文中就地调用中间件。在你的例子中,wrap-bob-response-header还不知道请求的去向(或者它甚至可以匹配任何东西)。如果它知道,您可以使用请求中的注入路由信息(请参阅https://github.com/metosin/compojure-api/blob/master/src/compojure/api/api.clj#L71-L73)来确定端点是否具有swagger信息集。

您可以做的是将标头设置中间件仅安装到需要它的路由。

有一个名为reitit(也由Metosin)的库,它通过应用路由优先架构解决了这个问题:首先完成完整路径查找,然后应用中间件链。因此,所有中间件都知道它们所安装的端点。中间件只能查询端点数据(在请求时或编译时)并相应地执行操作。他们甚至可以决定不安装到特定路线。

Reitit与compojure-api相同,只是语法不同,例如完全数据驱动。

博客中的好例子:https://www.metosin.fi/blog/reitit-ring/

PS。我是两个lib的共同作者。

EDIT.

匹配后将数据注入响应的解决方案:

1)创建中间件,将数据(或元数据)添加到响应中

2)添加或修改重构处理程序,将中间件从1安装到端点,使用给定的数据(在处理程序中可用)

3)读取响应管道中的数据并相应地采取行动

(defn wrap-add-response-data [handler data]
  (let [with-data #(assoc % ::data data)]
    (fn
      ([request]
       (with-data (handler request)))
      ([request respond raise]
       (handler #(respond (with-data %)) raise)))))

(defmethod compojure.api.meta/restructure-param :swagger [_ swagger acc]
  (-> acc
      (assoc-in [:info :public :swagger] swagger)
      (update-in [:middleware] into `[[wrap-add-response-data ~swagger]])))

(def app
  (api
    (context "/api" []
      (GET "/:kikka" []
        :swagger {:deprecated? true}
        (ok "jeah")))))

(app {:request-method :get, :uri "/api/kukka"})
; {:status 200, :headers {}, :body "jeah", ::data {:deprecated? true}}
热门问题
推荐问题
最新问题