Fix paths in swagger.json for endpoints with path parameters

This commit is contained in:
Kirill Chernyshov 2018-05-28 18:09:03 +02:00
parent 91abf8db51
commit b7341265e9
2 changed files with 82 additions and 50 deletions

View file

@ -3,6 +3,7 @@
[meta-merge.core :refer [meta-merge]]
[clojure.spec.alpha :as s]
[clojure.set :as set]
[clojure.string :as string]
[reitit.coercion :as coercion]))
(s/def ::id (s/or :keyword keyword? :set (s/coll-of keyword? :into #{})))
@ -62,6 +63,21 @@
{:name ::swagger
:spec ::spec})
(defn- path->template [path endpoint]
(let [path-parameters (filter (fn [{:keys [in]}]
(= in "path"))
(mapcat (fn [[_ {:keys [parameters]}]]
parameters)
endpoint))]
(loop [{:keys [name] :as path-parameter} (first path-parameters)
path-parameters (rest path-parameters)
path path]
(if path-parameter
(recur (first path-parameters)
(rest path-parameters)
(string/replace path (re-pattern (str ":" name)) (str "{" name "}")))
path))))
(defn create-swagger-handler []
"Create a ring handler to emit swagger spec. Collects all routes from router which have
an intersecting `[:swagger :id]` and which are not marked with `:no-doc` route data."
@ -83,7 +99,7 @@
(dissoc swagger :id))]))
transform-path (fn [[p _ c]]
(if-let [endpoint (some->> c (keep transform-endpoint) (seq) (into {}))]
[p endpoint]))]
[(path->template p endpoint) endpoint]))]
(if id
(let [paths (->> router (r/routes) (filter accept-route) (map transform-path) (into {}))]
{:status 200

View file

@ -19,20 +19,24 @@
:handler (swagger/create-swagger-handler)}}]
["/spec" {:coercion spec/coercion}
["/plus"
["/plus/:z"
{:get {:summary "plus"
:parameters {:query {:x int?, :y int?}}
:parameters {:query {:x int?, :y int?}
:path {:z int?}}
:responses {200 {:body {:total int?}}}
:handler (fn [{{{:keys [x y]} :query} :parameters}]
{:status 200, :body {:total (+ x y)}})}}]]
:handler (fn [{{{:keys [x y]} :query
{:keys [z]} :path} :parameters}]
{:status 200, :body {:total (+ x y z)}})}}]]
["/schema" {:coercion schema/coercion}
["/plus"
["/plus/:z"
{:get {:summary "plus"
:parameters {:query {:x Int, :y Int}}
:parameters {:query {:x Int, :y Int}
:path {:z Int}}
:responses {200 {:body {:total Int}}}
:handler (fn [{{{:keys [x y]} :query} :parameters}]
{:status 200, :body {:total (+ x y)}})}}]]]
:handler (fn [{{{:keys [x y]} :query
{:keys [z]} :path} :parameters}]
{:status 200, :body {:total (+ x y z)}})}}]]]
{:data {:middleware [swagger/swagger-feature
rrc/coerce-exceptions-middleware
@ -42,16 +46,16 @@
(deftest swagger-test
(testing "endpoints work"
(testing "spec"
(is (= {:body {:total 3}, :status 200}
(is (= {:body {:total 6}, :status 200}
(app
{:request-method :get
:uri "/api/spec/plus"
:uri "/api/spec/plus/3"
:query-params {:x "2", :y "1"}}))))
(testing "schema"
(is (= {:body {:total 3}, :status 200}
(is (= {:body {:total 6}, :status 200}
(app
{:request-method :get
:uri "/api/schema/plus"
:uri "/api/schema/plus/3"
:query-params {:x "2", :y "1"}})))))
(testing "swagger-spec"
(let [spec (:body (app
@ -60,43 +64,55 @@
(is (= {:x-id #{::math}
:swagger "2.0"
:info {:title "my-api"}
:paths {"/api/schema/plus" {:get {:parameters [{:description ""
:format "int32"
:in "query"
:name "x"
:required true
:type "integer"}
{:description ""
:format "int32"
:in "query"
:name "y"
:required true
:type "integer"}]
:responses {200 {:description ""
:schema {:additionalProperties false
:properties {"total" {:format "int32"
:type "integer"}}
:required ["total"]
:type "object"}}}
:summary "plus"}}
"/api/spec/plus" {:get {:parameters [{:description ""
:format "int64"
:in "query"
:name "x"
:required true
:type "integer"}
{:description ""
:format "int64"
:in "query"
:name "y"
:required true
:type "integer"}]
:responses {200 {:description ""
:schema {:properties {"total" {:format "int64"
:type "integer"}}
:required ["total"]
:type "object"}}}
:summary "plus"}}}}
:paths {"/api/schema/plus/{z}" {:get {:parameters [{:description ""
:format "int32"
:in "query"
:name "x"
:required true
:type "integer"}
{:description ""
:format "int32"
:in "query"
:name "y"
:required true
:type "integer"}
{:in "path"
:name "z"
:description ""
:type "integer"
:required true
:format "int32"}]
:responses {200 {:description ""
:schema {:additionalProperties false
:properties {"total" {:format "int32"
:type "integer"}}
:required ["total"]
:type "object"}}}
:summary "plus"}}
"/api/spec/plus/{z}" {:get {:parameters [{:description ""
:format "int64"
:in "query"
:name "x"
:required true
:type "integer"}
{:description ""
:format "int64"
:in "query"
:name "y"
:required true
:type "integer"}
{:in "path"
:name "z"
:description ""
:type "integer"
:required true
:format "int64"}]
:responses {200 {:description ""
:schema {:properties {"total" {:format "int64"
:type "integer"}}
:required ["total"]
:type "object"}}}
:summary "plus"}}}}
spec)))))
(deftest multiple-swagger-apis-test