From 4d0c8eb9c2a2a82d27d46c4e966a52097ed0cf61 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Tue, 2 Feb 2016 16:21:19 +0200 Subject: [PATCH 1/4] Single map in endpoint denotes a response --- src/compojure/api/api.clj | 2 +- src/compojure/api/common.clj | 4 ++-- src/compojure/api/meta.clj | 2 +- src/compojure/api/swagger.clj | 2 +- test/compojure/api/common_test.clj | 22 +++++++++++++++++++--- test/compojure/api/integration_test.clj | 19 +++++++++++++++++++ 6 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/compojure/api/api.clj b/src/compojure/api/api.clj index 883e05e3..42687511 100644 --- a/src/compojure/api/api.clj +++ b/src/compojure/api/api.clj @@ -37,7 +37,7 @@ " (:doc (meta #'compojure.api.middleware/api-middleware)))} api [& body] - (let [[options handlers] (common/extract-parameters body) + (let [[options handlers] (common/extract-parameters body false) options (rsc/deep-merge api-defaults options) handler (apply core/routes handlers) routes (routes/get-routes handler (:api options)) diff --git a/src/compojure/api/common.clj b/src/compojure/api/common.clj index 3e31761f..88bb73cb 100644 --- a/src/compojure/api/common.clj +++ b/src/compojure/api/common.clj @@ -12,9 +12,9 @@ 3. else => `{}` Returns a tuple with parameters and body without the parameters" - [c] + [c expect-body] (cond - (plain-map? (first c)) + (and (plain-map? (first c)) (or (not expect-body) (seq (rest c)))) [(first c) (seq (rest c))] (keyword? (first c)) diff --git a/src/compojure/api/meta.clj b/src/compojure/api/meta.clj index cdc621d5..35c669cd 100644 --- a/src/compojure/api/meta.clj +++ b/src/compojure/api/meta.clj @@ -318,7 +318,7 @@ (seq responses) (assoc :responses (apply merge responses)))) (defn restructure [method [path arg & args] {:keys [context?]}] - (let [[options body] (extract-parameters args) + (let [[options body] (extract-parameters args true) [path-string lets arg-with-request arg] (destructure-compojure-api-request path arg) {:keys [lets diff --git a/src/compojure/api/swagger.clj b/src/compojure/api/swagger.clj index 932462d0..883e0d1c 100644 --- a/src/compojure/api/swagger.clj +++ b/src/compojure/api/swagger.clj @@ -76,8 +76,8 @@ (let [[path body] (if (string? (first body)) [(first body) (rest body)] ["/swagger.json" body]) - [extra-info] (extract-parameters body)] (GET path request + [extra-info] (common/extract-parameters body false)] :no-doc true :name ::swagger (let [runtime-info (rsm/get-swagger-data request) diff --git a/test/compojure/api/common_test.clj b/test/compojure/api/common_test.clj index 4120f2c4..869919e0 100644 --- a/test/compojure/api/common_test.clj +++ b/test/compojure/api/common_test.clj @@ -1,7 +1,23 @@ (ns compojure.api.common-test - (:require [compojure.api.common :refer :all] + (:require [compojure.api.common :as common] [midje.sweet :refer :all])) (fact "group-with" - (group-with pos? [1 -10 2 -4 -1 999]) => [[1 2 999] [-10 -4 -1]] - (group-with pos? [1 2 999]) => [[1 2 999] nil]) + (common/group-with pos? [1 -10 2 -4 -1 999]) => [[1 2 999] [-10 -4 -1]] + (common/group-with pos? [1 2 999]) => [[1 2 999] nil]) + +(fact "extract-parameters" + + (facts "expect body" + (common/extract-parameters [] true) => [{} nil] + (common/extract-parameters [{:a 1}] true) => [{} [{:a 1}]] + (common/extract-parameters [:a 1] true) => [{:a 1} nil] + (common/extract-parameters [{:a 1} {:b 2}] true) => [{:a 1} [{:b 2}]] + (common/extract-parameters [:a 1 {:b 2}] true) => [{:a 1} [{:b 2}]]) + + (facts "don't expect body" + (common/extract-parameters [] false) => [{} nil] + (common/extract-parameters [{:a 1}] false) => [{:a 1} nil] + (common/extract-parameters [:a 1] false) => [{:a 1} nil] + (common/extract-parameters [{:a 1} {:b 2}] false) => [{:a 1} [{:b 2}]] + (common/extract-parameters [:a 1 {:b 2}] false) => [{:a 1} [{:b 2}]])) diff --git a/test/compojure/api/integration_test.clj b/test/compojure/api/integration_test.clj index e27ff7c0..64908fb9 100644 --- a/test/compojure/api/integration_test.clj +++ b/test/compojure/api/integration_test.clj @@ -79,6 +79,25 @@ ;; Facts ;; +(facts "core routes" + + (fact "keyword options" + (let [route (GET "/ping" [] + :return String + (ok "kikka"))] + (route {:request-method :get :uri "/ping"}) => (contains {:body "kikka"}))) + + (fact "map options" + (let [route (GET "/ping" [] + {:return String} + (ok "kikka"))] + (route {:request-method :get :uri "/ping"}) => (contains {:body "kikka"}))) + + (fact "map return" + (let [route (GET "/ping" [] + {:body "kikka"})] + (route {:request-method :get :uri "/ping"}) => (contains {:body "kikka"})))) + (facts "middleware ordering" (let [app (api (middleware [middleware* [middleware* 2]] From e5b5a49aa8bc16cb0d1fd1a58ced1e22be3d536d Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Tue, 2 Feb 2016 16:37:42 +0200 Subject: [PATCH 2/4] Swagger via swagger-routes & api-options swagger-ui and swagger-docs are still in sweet in this commit. --- src/compojure/api/api.clj | 20 +++-- src/compojure/api/swagger.clj | 108 ++++++++++++++---------- src/compojure/api/sweet.clj | 3 +- test/compojure/api/integration_test.clj | 4 +- 4 files changed, 79 insertions(+), 56 deletions(-) diff --git a/src/compojure/api/api.clj b/src/compojure/api/api.clj index 42687511..9515457a 100644 --- a/src/compojure/api/api.clj +++ b/src/compojure/api/api.clj @@ -1,16 +1,18 @@ (ns compojure.api.api - (:require [compojure.api.core :as core] + (:require [compojure.api.core :as c] [compojure.api.swagger :as swagger] [compojure.api.middleware :as middleware] [compojure.api.routes :as routes] [compojure.api.common :as common] [ring.swagger.common :as rsc] - [compojure.api.meta :as meta])) + [compojure.api.meta :as meta] + [ring.swagger.middleware :as rsm])) (def api-defaults (merge middleware/api-middleware-defaults - {:api {:invalid-routes-fn routes/log-invalid-child-routes}})) + {:api {:invalid-routes-fn routes/log-invalid-child-routes} + :swagger nil})) (defn ^{:doc (str @@ -31,6 +33,8 @@ invalid routes (not satisfying compojure.api.route.Routing) setting value to nil ignores invalid routes completely. defaults to `compojure.api.routes/log-invalid-child-routes` + - **:swagger** Options to configure the Swagger-routes. Defaults to nil. + See `compojure.api.swagger/swagger-routes` for details. ### api-middleware options @@ -39,15 +43,17 @@ [& body] (let [[options handlers] (common/extract-parameters body false) options (rsc/deep-merge api-defaults options) - handler (apply core/routes handlers) + handler (apply c/routes (concat handlers [(swagger/swagger-routes (:swagger options))])) routes (routes/get-routes handler (:api options)) paths (-> routes routes/ring-swagger-paths swagger/transform-operations) lookup (routes/route-lookup-table routes) + swagger-data (get-in options [:swagger :data]) api-handler (-> handler - (middleware/api-middleware (dissoc options :api)) + (cond-> swagger-data (rsm/wrap-swagger-data swagger-data)) + (middleware/api-middleware (dissoc options :api :swagger)) (middleware/wrap-options {:paths paths - :coercer (meta/memoized-coercer) - :lookup lookup}))] + :coercer (meta/memoized-coercer) + :lookup lookup}))] (routes/create nil nil {} [handler] api-handler))) (defmacro diff --git a/src/compojure/api/swagger.clj b/src/compojure/api/swagger.clj index 883e0d1c..cee6b1e9 100644 --- a/src/compojure/api/swagger.clj +++ b/src/compojure/api/swagger.clj @@ -1,7 +1,6 @@ (ns compojure.api.swagger - (:require [compojure.api.common :refer :all] - [compojure.api.core :refer [GET undocumented]] - [compojure.api.common :refer [extract-parameters]] + (:require [compojure.api.core :as c] + [compojure.api.common :as common] [compojure.api.middleware :as mw] [ring.util.http-response :refer [ok]] [ring.swagger.common :as rsc] @@ -13,10 +12,6 @@ [compojure.api.routes :as routes] [cheshire.core :as cheshire])) -;; -;; generate schema names -;; - #_(defn ensure-parameter-schema-names [endpoint] (if (get-in endpoint [:parameters :body]) (update-in endpoint [:parameters :body] #(swagger/with-named-sub-schemas % "Body")) @@ -33,51 +28,34 @@ responses)))) endpoint)) -;; -;; routes -;; +(defn- base-path [request] + (let [context (swagger/context request)] + (if (= "" context) "/" context))) + +(defn- swagger-spec-path + [app] + (some-> app + routes/get-routes + routes/route-lookup-table + ::swagger + keys + first)) (defn transform-operations [swagger] (->> swagger (swagger2/transform-operations routes/non-nil-routes) (swagger2/transform-operations routes/strip-no-doc-endpoints))) -(defn base-path [request] - (let [context (swagger/context request)] - (if (= "" context) "/" context))) - -;; -;; Public api -;; - (defn swagger-ui [& params] - (undocumented + (c/undocumented (apply rsui/swagger-ui params))) -(defn swagger-docs - "Route to serve the swagger api-docs. If the first - parameter is a String, it is used as a url for the - api-docs, otherwise \"/swagger.json\" will be used. - Next Keyword value pairs OR a map for meta-data. - Meta-data can be any valid swagger 2.0 data. Common - case is to introduce API Info and Tags here: - - {:info {:version \"1.0.0\" - :title \"Sausages\" - :description \"Sausage description\" - :termsOfService \"http://helloreverb.com/terms/\" - :contact {:name \"My API Team\" - :email \"foo@example.com\" - :url \"http://www.metosin.fi\"} - :license {:name: \"Eclipse Public License\" - :url: \"http://www.eclipse.org/legal/epl-v10.html\"}} - :tags [{:name \"sausages\", :description \"Sausage api-set}]}" - [& body] +(defn swagger-docs [& body] (let [[path body] (if (string? (first body)) [(first body) (rest body)] ["/swagger.json" body]) - (GET path request [extra-info] (common/extract-parameters body false)] + (c/GET path request :no-doc true :name ::swagger (let [runtime-info (rsm/get-swagger-data request) @@ -88,13 +66,51 @@ spec (swagger2/swagger-json swagger options)] (ok spec))))) -(defn swagger-spec-path [app] - (some-> app - routes/get-routes - routes/route-lookup-table - ::swagger - keys - first)) +;; +;; Public api +;; + +(def swagger-defaults {:ui "/", :spec "/swagger.json"}) + +(defn swagger-routes + "Returns routes for swagger-articats (ui & spec). Accepts an options map, with the + following options: + + **:ui** Uri for the swagger-ui (defaults to \"/\"). + Setting the value to nil will cause the swagger-ui not to be mounted + + **:spec** Uri for the swagger-spec (defaults to \"/swagger.json\") + Setting the value to nil will cause the swagger-ui not to be mounted + + **:data** Swagger data in the Ring-Swagger format. + + **:options** + **:ui** Options to configure the ui + **:spec** Options to configure the spec. Nada at the moment. + + Example options: + + {:ui \"/api-docs\" + :spec \"/swagger.json\" + :options {:ui {:jsonEditor true} + :spec {}} + :data {:info {:version \"1.0.0\" + :title \"Sausages\" + :description \"Sausage description\" + :termsOfService \"http://helloreverb.com/terms/\" + :contact {:name \"My API Team\" + :email \"foo@example.com\" + :url \"http://www.metosin.fi\"} + :license {:name: \"Eclipse Public License\" + :url: \"http://www.eclipse.org/legal/epl-v10.html\"}} + :tags [{:name \"sausages\", :description \"Sausage api-set\"}]}}" + ([] (swagger-routes {})) + ([options] + (if options + (let [{:keys [ui spec data] {ui-options :ui spec-options :spec} :options} (merge swagger-defaults options)] + (c/routes + (if ui (apply swagger-ui ui (mapcat identity (merge ui-options (if spec {:swagger-docs spec}))))) + (if spec (apply swagger-docs spec (mapcat identity data)))))))) (defn validate "Validates a api. If the api is Swagger-enabled, the swagger-spec diff --git a/src/compojure/api/sweet.clj b/src/compojure/api/sweet.clj index d4fd8e0d..d250ab27 100644 --- a/src/compojure/api/sweet.clj +++ b/src/compojure/api/sweet.clj @@ -39,7 +39,8 @@ [compojure.api.swagger swagger-ui - swagger-docs] + swagger-docs + swagger-routes] [ring.swagger.json-schema diff --git a/test/compojure/api/integration_test.clj b/test/compojure/api/integration_test.clj index 64908fb9..9e53d473 100644 --- a/test/compojure/api/integration_test.clj +++ b/test/compojure/api/integration_test.clj @@ -949,10 +949,10 @@ (fact "swagger-spec-path" (fact "defaults to /swagger.json" (let [app (api (swagger-docs))] - (swagger/swagger-spec-path app) => "/swagger.json")) + (#'swagger/swagger-spec-path app) => "/swagger.json")) (fact "follows defined path" (let [app (api (swagger-docs "/api/api-docs/swagger.json"))] - (swagger/swagger-spec-path app) => "/api/api-docs/swagger.json"))) + (#'swagger/swagger-spec-path app) => "/api/api-docs/swagger.json"))) (defrecord NonSwaggerRecord [data]) From 806c9cb063e27c995ff27a1a86d9c0cd3001c9b9 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Tue, 2 Feb 2016 18:13:22 +0200 Subject: [PATCH 3/4] Convert all swagger-routes --- examples/src/examples/thingie.clj | 42 +++++++-------- src/compojure/api/swagger.clj | 4 +- src/compojure/api/sweet.clj | 2 - test/compojure/api/integration_test.clj | 68 ++++++++++++------------- test/compojure/api/routes_test.clj | 6 +-- test/compojure/api/sweet_test.clj | 20 ++++---- 6 files changed, 70 insertions(+), 72 deletions(-) diff --git a/examples/src/examples/thingie.clj b/examples/src/examples/thingie.clj index 592e9318..4cec8f08 100644 --- a/examples/src/examples/thingie.clj +++ b/examples/src/examples/thingie.clj @@ -23,27 +23,27 @@ (def app (api - (swagger-ui) - (swagger-docs - {:info {:version "1.0.0" - :title "Thingies API" - :description "the description" - :termsOfService "http://www.metosin.fi" - :contact {:name "My API Team" - :email "foo@example.com" - :url "http://www.metosin.fi"} - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"}} - :tags [{:name "math", :description "Math with parameters"} - {:name "pizzas", :description "Pizza API"} - {:name "failing", :description "Handling uncaught exceptions"} - {:name "dates", :description "Dates API"} - {:name "responses", :description "Responses demo"} - {:name "primitives", :description "Returning primitive values"} - {:name "context", :description "context routes"} - {:name "echo", :description "Echoes data"} - {:name "ordered", :description "Ordered routes"} - {:name "file", :description "File upload"}]}) + {:swagger {:ui "/" + :spec "/swagger.json" + :data {:info {:version "1.0.0" + :title "Thingies API" + :description "the description" + :termsOfService "http://www.metosin.fi" + :contact {:name "My API Team" + :email "foo@example.com" + :url "http://www.metosin.fi"} + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"}} + :tags [{:name "math", :description "Math with parameters"} + {:name "pizzas", :description "Pizza API"} + {:name "failing", :description "Handling uncaught exceptions"} + {:name "dates", :description "Dates API"} + {:name "responses", :description "Responses demo"} + {:name "primitives", :description "Returning primitive values"} + {:name "context", :description "context routes"} + {:name "echo", :description "Echoes data"} + {:name "ordered", :description "Ordered routes"} + {:name "file", :description "File upload"}]}}} (context "/math" [] :tags ["math"] diff --git a/src/compojure/api/swagger.clj b/src/compojure/api/swagger.clj index cee6b1e9..431ea642 100644 --- a/src/compojure/api/swagger.clj +++ b/src/compojure/api/swagger.clj @@ -28,11 +28,11 @@ responses)))) endpoint)) -(defn- base-path [request] +(defn base-path [request] (let [context (swagger/context request)] (if (= "" context) "/" context))) -(defn- swagger-spec-path +(defn swagger-spec-path [app] (some-> app routes/get-routes diff --git a/src/compojure/api/sweet.clj b/src/compojure/api/sweet.clj index d250ab27..72646f5c 100644 --- a/src/compojure/api/sweet.clj +++ b/src/compojure/api/sweet.clj @@ -38,8 +38,6 @@ [compojure.api.swagger - swagger-ui - swagger-docs swagger-routes] [ring.swagger.json-schema diff --git a/test/compojure/api/integration_test.clj b/test/compojure/api/integration_test.clj index 9e53d473..e367556b 100644 --- a/test/compojure/api/integration_test.clj +++ b/test/compojure/api/integration_test.clj @@ -245,7 +245,7 @@ (fact ":responses" (fact "normal cases" (let [app (api - (swagger-docs) + (swagger-routes) (GET "/lotto/:x" [] :path-params [x :- Long] :responses {403 {:schema [String]} @@ -451,7 +451,7 @@ (fact "swagger-docs" (let [app (api {:format {:formats [:json-kw :edn]}} - (swagger-docs) + (swagger-routes) (GET "/user" [] (continue)))] @@ -467,7 +467,7 @@ (facts "swagger-docs with anonymous Return and Body models" (let [app (api - (swagger-docs) + (swagger-routes) (POST "/echo" [] :return (s/either {:a String}) :body [_ (s/maybe {:a String})] @@ -496,7 +496,7 @@ (facts "https://github.com/metosin/compojure-api/issues/53" (let [app (api - (swagger-docs) + (swagger-routes) (POST "/" [] :return ReturnValue :body [_ Boundary] @@ -522,7 +522,7 @@ ; https://github.com/metosin/compojure-api/issues/94 (facts "preserves deeply nested schema names" (let [app (api - (swagger-docs) + (swagger-routes) (POST "/" [] :return Urho :body [_ Olipa] @@ -539,7 +539,7 @@ (fact "swagger-docs works with the :middleware" (let [app (api - (swagger-docs) + (swagger-routes) (GET "/middleware" [] :query-params [x :- String] :middleware [[constant-middleware (ok 1)]] @@ -562,7 +562,7 @@ (= body response))) not-ok? (comp not ok?) app (api - (swagger-docs) + (swagger-routes {:ui nil}) (GET "/" [] ok) (GET "/a" [] ok) (context "/b" [] @@ -635,7 +635,7 @@ (fact "external deep schemas" (let [app (api - (swagger-docs) + (swagger-routes) burger-routes (POST "/pizza" [] :return Pizza @@ -659,7 +659,7 @@ (fact "multiple routes with same path & method in same file" (let [app (api - (swagger-docs) + (swagger-routes) (GET "/ping" [] :summary "active-ping" (ok {:ping "active"})) @@ -677,7 +677,7 @@ (fact "multiple routes with same path & method over context" (let [app (api - (swagger-docs) + (swagger-routes) (context "/api" [] (context "/ipa" [] (GET "/ping" [] @@ -699,7 +699,7 @@ (fact "multiple routes with same overall path (with different path sniplets & method over context" (let [app (api - (swagger-docs) + (swagger-routes) (context "/api/ipa" [] (GET "/ping" [] :summary "active-ping" @@ -721,7 +721,7 @@ ; https://github.com/metosin/compojure-api/issues/98 ; https://github.com/metosin/compojure-api/issues/134 (fact "basePath" - (let [app (api (swagger-docs))] + (let [app (api (swagger-routes))] (fact "no context" (-> app get-spec :basePath) => "/") @@ -730,11 +730,11 @@ (against-background (rsc/context anything) => "/v2") (-> app get-spec :basePath) => "/v2")) - (let [app (api (swagger-docs {:basePath "/serve/from/here"}))] + (let [app (api (swagger-routes {:data {:basePath "/serve/from/here"}}))] (fact "override it" (-> app get-spec :basePath) => "/serve/from/here")) - (let [app (api (swagger-docs {:basePath "/"}))] + (let [app (api (swagger-routes {:data {:basePath "/"}}))] (fact "can set it to the default" (-> app get-spec :basePath) => "/"))) @@ -745,7 +745,7 @@ (fact "api-spec with 2 schemas with non-equal contents" (let [app (api - (swagger-docs) + (swagger-routes) (GET "/" [] :responses {200 {:schema (s/schema-with-name {:a {:d #"\D"}} "Kikka")} 201 {:schema (s/schema-with-name {:a {:d #"\D"}} "Kikka")}} @@ -760,7 +760,7 @@ (fact "anonymous body models over defined routes" (let [app (api - (swagger-docs) + (swagger-routes) over-the-hills-and-far-away)] (fact "generated model doesn't have namespaced keys" (-> app get-spec :definitions vals first :properties keys first) => :a))) @@ -785,7 +785,7 @@ (fact "response descriptions" (let [app (api - (swagger-docs) + (swagger-routes) response-descriptions-routes)] (-> app get-spec :paths vals first :get :responses :500 :description) => "Horror")) @@ -794,7 +794,7 @@ {:exceptions {:handlers {::ex/request-validation custom-validation-error-handler ::ex/request-parsing custom-validation-error-handler ::ex/response-validation custom-validation-error-handler}}} - (swagger-docs) + (swagger-routes) (POST "/get-long" [] :body [body {:x Long}] :return Long @@ -826,7 +826,7 @@ (let [app (api {:exceptions {:handlers {::ex/default custom-exception-handler ::custom-error custom-error-handler}}} - (swagger-docs) + (swagger-routes) (GET "/some-exception" [] (throw (new RuntimeException))) (GET "/some-error" [] @@ -887,7 +887,7 @@ (fact "ring-swagger options" (let [app (api {:ring-swagger {:default-response-description-fn status/get-description}} - (swagger-docs) + (swagger-routes) (GET "/ping" [] :responses {500 nil} identity))] @@ -948,11 +948,11 @@ (fact "swagger-spec-path" (fact "defaults to /swagger.json" - (let [app (api (swagger-docs))] - (#'swagger/swagger-spec-path app) => "/swagger.json")) + (let [app (api (swagger-routes))] + (swagger/swagger-spec-path app) => "/swagger.json")) (fact "follows defined path" - (let [app (api (swagger-docs "/api/api-docs/swagger.json"))] - (#'swagger/swagger-spec-path app) => "/api/api-docs/swagger.json"))) + (let [app (api (swagger-routes {:spec "/api/api-docs/swagger.json"}))] + (swagger/swagger-spec-path app) => "/api/api-docs/swagger.json"))) (defrecord NonSwaggerRecord [data]) @@ -960,7 +960,7 @@ (fact "a swagger api with valid swagger records" (let [app (api - (swagger-docs) + (swagger-routes) (GET "/ping" [] :return {:data s/Str} (ok {:data "ping"})))] @@ -975,7 +975,7 @@ (fact "a swagger api with invalid swagger records" (let [app (api - (swagger-docs) + (swagger-routes) (GET "/ping" [] :return NonSwaggerRecord (ok (->NonSwaggerRecord "ping"))))] @@ -1045,7 +1045,7 @@ (fact ":swagger params just for ducumentation" (let [app (api - (swagger-docs) + (swagger-routes) (GET "/route" [q] :swagger {:x-name :boolean :operationId "echoBoolean" @@ -1073,9 +1073,10 @@ (fact "more swagger-data can be (deep-)merged in - either via swagger-docs at runtime via mws, fixes #170" (let [app (api (middleware [[rsm/wrap-swagger-data {:paths {"/runtime" {:get {}}}}]] - (swagger-docs - {:info {:version "2.0.0"} - :paths {"/extra" {:get {}}}}) + (swagger-routes + {:data + {:info {:version "2.0.0"} + :paths {"/extra" {:get {}}}}}) (GET "/normal" [] (ok))))] (get-spec app) => (contains {:paths (just @@ -1087,14 +1088,14 @@ (s/defschema Foo {:a [s/Keyword]}) (defapi with-defapi - (swagger-docs) + (swagger-routes) (GET "/foo" [] :return Foo (ok {:a "foo"}))) (defn with-api [] (api - (swagger-docs) + (swagger-routes) (GET "/foo" [] :return Foo (ok {:a "foo"})))) @@ -1169,8 +1170,7 @@ (fact "using local symbols for restructuring params" (let [responses {400 {:schema {:fail s/Str}}} app (api - (swagger-docs - {:info {:version "2.0.0"}}) + {:swagger {:data {:info {:version "2.0.0"}}}} (GET "/a" [] :responses responses :return {:ok s/Str} diff --git a/test/compojure/api/routes_test.clj b/test/compojure/api/routes_test.clj index 2e1b94c4..30873b4d 100644 --- a/test/compojure/api/routes_test.clj +++ b/test/compojure/api/routes_test.clj @@ -49,7 +49,7 @@ (ok {:message (str "Hello, " name)})) (more-routes version))) app (api - (swagger-docs) + (swagger-routes) routes)] (fact "all routes can be invoked" @@ -95,7 +95,7 @@ :path-params [version :- String] (more-routes version)) app (api - (swagger-docs) + (swagger-routes) routes)] (fact "all routes can be invoked" @@ -118,7 +118,7 @@ (fact "route merging" (routes/get-routes (routes (routes))) => [] - (routes/get-routes (routes (swagger-ui))) => [] + (routes/get-routes (routes (swagger-routes {:spec nil}))) => [] (routes/get-routes (routes (routes (GET "/ping" [] "pong")))) => [["/ping" :get {}]]) (fact "invalid route options" diff --git a/test/compojure/api/sweet_test.clj b/test/compojure/api/sweet_test.clj index 5573d8ee..78aaa5f5 100644 --- a/test/compojure/api/sweet_test.clj +++ b/test/compojure/api/sweet_test.clj @@ -18,16 +18,16 @@ (def app (api - (swagger-docs - {:info {:version "1.0.0" - :title "Sausages" - :description "Sausage description" - :termsOfService "http://helloreverb.com/terms/" - :contact {:name "My API Team" - :email "foo@example.com" - :url "http://www.metosin.fi"} - :license {:name "Eclipse Public License" - :url "http://www.eclipse.org/legal/epl-v10.html"}}}) + {:swagger {:spec "/swagger.json" + :data {:info {:version "1.0.0" + :title "Sausages" + :description "Sausage description" + :termsOfService "http://helloreverb.com/terms/" + :contact {:name "My API Team" + :email "foo@example.com" + :url "http://www.metosin.fi"} + :license {:name "Eclipse Public License" + :url "http://www.eclipse.org/legal/epl-v10.html"}}}}} ping-route (context "/api" [] ping-route From be251794e6aba39db7ee4911a8f21003a9e18023 Mon Sep 17 00:00:00 2001 From: Tommi Reiman Date: Tue, 2 Feb 2016 18:47:56 +0200 Subject: [PATCH 4/4] Update Changelog & README --- CHANGELOG.md | 25 ++++++++++++++++++++++--- README.md | 10 +++++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5ec4bbf..386cbe24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,7 +46,26 @@ * `context*` => `context` * `defroutes*` => `defroutes` -* **BREAKING** `public-resource-routes` & `public-resources` are removed from `compojure.api.middleware`. +* **BREAKING** `swagger-docs` and `swagger-ui` are now longer in `compojure.api.sweet` + * Syntax was hairy and when configuring the spec-url it needed to be set to both in order to work + * In future, there are multiple ways of setting the swagger stuff: + * via api-options `:swagger` (has no defaults) + * via `swagger-routes` function, mounting both the `swagger-ui` and `swagger-docs` and wiring them together + * by default, mounts the swagger-ui to `/` and the swagger-spec to `/swagger.json` + * via the old `swagger-ui` & `swagger-docs` (need to be separately imported from `compojure.api.swagger`). + * see https://github.com/metosin/compojure-api/wiki/Swagger-integration for details + +```clj +(defapi app + (swagger-routes) + (GET "/ping" [] + (ok {:message "pong"}))) + +(defapi app + {:swagger {:ui "/", :spec "/swagger.json"}} + (GET "/ping" [] + (ok {:message "pong"}))) +``` * **BREAKING**: api-level coercion option is now a function of `request => type => matcher` as it is documented. Previously required a `type => matcher` map. Options are checked against `type => matcher` coercion input, and a @@ -70,6 +89,8 @@ take a vector of middleware containing either has been renamed to `:swagger`. * will break at macro-expansion time with helpful exception +* **BREAKING** `public-resource-routes` & `public-resources` are removed from `compojure.api.middleware`. + * **BREAKING**: `compojure.api.legacy` namespace has been removed. ### Migration guide @@ -84,8 +105,6 @@ https://github.com/metosin/compojure-api/wiki/Migration-Guide-to-1.0.0 * top-level `api` is now just function, not a macro. It takes an optional options maps and a top-level route function. -* `swagger-docs` and `swagger-ui` are now functions instead of macros. - * Coercer cache is now at api-level with 10000 entries. * Code generated from restructured route macros is much cleaner now diff --git a/README.md b/README.md index dd5e7d93..f970214d 100644 --- a/README.md +++ b/README.md @@ -52,11 +52,11 @@ Stuff on top of [Compojure](https://github.com/weavejester/compojure) for making :city s/Str}}) (defapi app - (swagger-ui) - (swagger-docs - {:info {:title "My Swagger API" - :description "Compojure Api example"} - :tags [{:name "api", :description "sample api"}]}) + {:swagger {:spec "/swagger.json" + :ui "/api-docs" + :data {:data {:info {:title "My Swagger API" + :description "Compojure Api example"} + :tags [{:name "api", :description "sample api"}]}}) (context "/api" [] :tags ["api"] (GET "/hello" []