diff --git a/doc/ring/swagger.md b/doc/ring/swagger.md index 54eca320..719a0611 100644 --- a/doc/ring/swagger.md +++ b/doc/ring/swagger.md @@ -23,6 +23,7 @@ The following route data keys contribute to the generated swagger specification: | :tags | optional set of string or keyword tags for an endpoint api docs | :summary | optional short string summary of an endpoint | :description | optional long description of an endpoint. Supports http://spec.commonmark.org/ +| :operationId | optional string specifying the unique ID of an Operation Coercion keys also contribute to the docs: diff --git a/modules/reitit-swagger/src/reitit/swagger.cljc b/modules/reitit-swagger/src/reitit/swagger.cljc index daffaff4..0286565a 100644 --- a/modules/reitit-swagger/src/reitit/swagger.cljc +++ b/modules/reitit-swagger/src/reitit/swagger.cljc @@ -13,9 +13,10 @@ (s/def ::operationId string?) (s/def ::summary string?) (s/def ::description string?) +(s/def ::operationId string?) (s/def ::swagger (s/keys :opt-un [::id])) -(s/def ::spec (s/keys :opt-un [::swagger ::no-doc ::tags ::operationId ::summary ::description])) +(s/def ::spec (s/keys :opt-un [::swagger ::no-doc ::tags ::summary ::description ::operationId])) (def swagger-feature "Feature for handling swagger-documentation for routes. @@ -77,7 +78,7 @@ (let [{:keys [id] :or {id ::default} :as swagger} (-> match :result request-method :data :swagger) ids (trie/into-set id) strip-top-level-keys #(dissoc % :id :info :host :basePath :definitions :securityDefinitions) - strip-endpoint-keys #(dissoc % :id :operationId :parameters :responses :summary :description) + strip-endpoint-keys #(dissoc % :id :parameters :responses :summary :description :operationId) swagger (->> (strip-endpoint-keys swagger) (merge {:swagger "2.0" :x-id ids})) @@ -90,13 +91,13 @@ (if (and data (not no-doc)) [method (meta-merge - base-swagger-spec - (apply meta-merge (keep (comp :swagger :data) middleware)) - (apply meta-merge (keep (comp :swagger :data) interceptors)) - (if coercion - (coercion/get-apidocs coercion :swagger data)) - (select-keys data [:tags :operationId :summary :description]) - (strip-top-level-keys swagger))])) + base-swagger-spec + (apply meta-merge (keep (comp :swagger :data) middleware)) + (apply meta-merge (keep (comp :swagger :data) interceptors)) + (if coercion + (coercion/get-apidocs coercion :swagger data)) + (select-keys data [:tags :summary :description :operationId]) + (strip-top-level-keys swagger))])) transform-path (fn [[p _ c]] (if-let [endpoint (some->> c (keep transform-endpoint) (seq) (into {}))] [(swagger-path p (r/options router)) endpoint])) diff --git a/test/cljc/reitit/swagger_test.clj b/test/cljc/reitit/swagger_test.clj index d1b2c81b..96dfed23 100644 --- a/test/cljc/reitit/swagger_test.clj +++ b/test/cljc/reitit/swagger_test.clj @@ -22,33 +22,35 @@ :swagger {:info {:title "my-api"}} :handler (swagger/create-swagger-handler)}}] - ["/spec" {:coercion spec/coercion} - ["/plus/:z" - {:patch {:summary "patch" - :handler (constantly {:status 200})} - :options {:summary "options" - :middleware [{:data {:swagger {:responses {200 {:description "200"}}}}}] + ["/spec" {:coercion spec/coercion} + ["/plus/:z" + {:patch {:summary "patch" + :operationId "Patch" :handler (constantly {:status 200})} - :get {:summary "plus" - :parameters {:query {:x int?, :y int?} - :path {:z int?}} - :swagger {:responses {400 {:schema {:type "string"} - :description "kosh"}}} - :responses {200 {:body {:total int?}} - 500 {:description "fail"}} - :handler (fn [{{{:keys [x y]} :query - {:keys [z]} :path} :parameters}] - {:status 200, :body {:total (+ x y z)}})} - :post {:summary "plus with body" - :parameters {:body (ds/maybe [int?]) - :path {:z int?}} - :swagger {:responses {400 {:schema {:type "string"} - :description "kosh"}}} - :responses {200 {:body {:total int?}} - 500 {:description "fail"}} - :handler (fn [{{{:keys [z]} :path - xs :body} :parameters}] - {:status 200, :body {:total (+ (reduce + xs) z)}})}}]] + :options {:summary "options" + :middleware [{:data {:swagger {:responses {200 {:description "200"}}}}}] + :handler (constantly {:status 200})} + :get {:summary "plus" + :operationId "GetPlus" + :parameters {:query {:x int?, :y int?} + :path {:z int?}} + :swagger {:responses {400 {:schema {:type "string"} + :description "kosh"}}} + :responses {200 {:body {:total int?}} + 500 {:description "fail"}} + :handler (fn [{{{:keys [x y]} :query + {:keys [z]} :path} :parameters}] + {:status 200, :body {:total (+ x y z)}})} + :post {:summary "plus with body" + :parameters {:body (ds/maybe [int?]) + :path {:z int?}} + :swagger {:responses {400 {:schema {:type "string"} + :description "kosh"}}} + :responses {200 {:body {:total int?}} + 500 {:description "fail"}} + :handler (fn [{{{:keys [z]} :path + xs :body} :parameters}] + {:status 200, :body {:total (+ (reduce + xs) z)}})}}]] ["/malli" {:coercion malli/coercion} ["/plus/*z" @@ -118,6 +120,7 @@ (app {:request-method :get :uri "/api/schema/plus/3" :query-params {:x "2", :y "1"}}))))) + (testing "swagger-spec" (let [spec (:body (app {:request-method :get :uri "/api/swagger.json"})) @@ -126,6 +129,7 @@ :info {:title "my-api"} :paths {"/api/spec/plus/{z}" {:patch {:parameters [] :summary "patch" + :operationId "Patch" :responses {:default {:description ""}}} :options {:parameters [] :summary "options" @@ -156,7 +160,8 @@ 400 {:schema {:type "string"} :description "kosh"} 500 {:description "fail"}} - :summary "plus"} + :summary "plus" + :operationId "GetPlus"} :post {:parameters [{:in "body", :name "body", :description "",