mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 00:11:11 +00:00
commit
73f0f355eb
5 changed files with 51 additions and 22 deletions
19
CHANGELOG.md
19
CHANGELOG.md
|
|
@ -6,6 +6,25 @@
|
|||
* should only concern you if you are not using [Muuntaja](https://github.com/metosin/muuntaja).
|
||||
* the `r/routes` returns just the path + data tuples as documented, not the compiled route results. To get the compiled results, use `r/compiled-routes` instead.
|
||||
|
||||
## `reitit-swagger`
|
||||
|
||||
* In case of just one swagger api per router, the swagger api doesn't have to identified, so this works now:
|
||||
|
||||
```clj
|
||||
(require '[reitit.ring :as ring])
|
||||
(require '[reitit.swagger :as swagger])
|
||||
(require '[reitit.swagger-ui :as swagger-ui])
|
||||
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
[["/ping"
|
||||
{:get (fn [_] {:status 200, :body "pong"})}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]])
|
||||
(swagger-ui/create-swagger-ui-handler {:path "/"}))
|
||||
```
|
||||
|
||||
## `reitit-swagger-ui`
|
||||
|
||||
* **BREAKING**: pass swagger-ui `:config` as-is (instead of mixed-casing keys) to swagger-ui, fixes [#109](https://github.com/metosin/reitit/issues/109):
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ The following route data keys contribute to the generated swagger specification:
|
|||
|
||||
| key | description |
|
||||
| --------------|-------------|
|
||||
| :swagger | map of any swagger-data. Must have `:id` (keyword or sequence of keywords) to identify the api
|
||||
| :swagger | map of any swagger-data. Can have `:id` (keyword or sequence of keywords) to identify the api
|
||||
| :no-doc | optional boolean to exclude endpoint from api docs
|
||||
| :tags | optional set of strings of keywords tags for an endpoint api docs
|
||||
| :summary | optional short string summary of an endpoint
|
||||
|
|
@ -67,7 +67,7 @@ Webjars also hosts a [version](https://github.com/webjars/swagger-ui) of the swa
|
|||
|
||||
### Simple example
|
||||
|
||||
* two routes in a single swagger-api `::api`
|
||||
* two routes
|
||||
* swagger-spec served from `"/swagger.json"`
|
||||
* swagger-ui mounted to `"/"`
|
||||
|
||||
|
|
@ -84,8 +84,7 @@ Webjars also hosts a [version](https://github.com/webjars/swagger-ui) of the swa
|
|||
["/pong" {:post (constantly "pong")}]]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]
|
||||
{:data {:swagger {:id ::api}}}) ;; for all routes
|
||||
:handler (swagger/create-swagger-handler)}}]])
|
||||
(swagger-ui/create-swagger-ui-handler {:path "/"})))
|
||||
```
|
||||
|
||||
|
|
@ -95,7 +94,7 @@ The generated swagger spec:
|
|||
(app {:request-method :get :uri "/swagger.json"})
|
||||
;{:status 200
|
||||
; :body {:swagger "2.0"
|
||||
; :x-id #{:user/api}
|
||||
; :x-id #{:reitit.swagger/default}
|
||||
; :paths {"/api/ping" {:get {}}
|
||||
; "/api/pong" {:post {}}}}}
|
||||
```
|
||||
|
|
@ -138,8 +137,7 @@ Whole example project is in [`/examples/ring-swagger`](https://github.com/metosi
|
|||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
{:swagger {:id ::math}}
|
||||
|
||||
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:swagger {:info {:title "my-api"}}
|
||||
|
|
@ -195,9 +193,9 @@ http://localhost:3000 should render now the swagger-ui:
|
|||
|
||||

|
||||
|
||||
## Advanced
|
||||
## Multiple swagger apis
|
||||
|
||||
Route data in path `[:swagger :id]` can be either a keyword or a sequence of keywords. This enables one route to be part of multiple swagger apis. Normal route data [scoping rules](../basics/route_data.md#nested-route-data) rules apply.
|
||||
There can be multiple swagger apis within a router. Each route can be part of 0..n swagger apis. Swagger apis are identified by value in route data under key path `[:swagger :id]`. It can be either a keyword or a sequence of keywords. Normal route data [scoping rules](../basics/route_data.md#nested-route-data) rules apply.
|
||||
|
||||
Example with:
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
{:swagger {:id ::math}}
|
||||
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
|
|
|
|||
|
|
@ -74,13 +74,13 @@
|
|||
"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."
|
||||
(fn [{:keys [::r/router ::r/match :request-method]}]
|
||||
(let [{:keys [id] :as swagger} (-> match :result request-method :data :swagger)
|
||||
(let [{:keys [id] :or {id ::default} :as swagger} (-> match :result request-method :data :swagger)
|
||||
->set (fn [x] (if (or (set? x) (sequential? x)) (set x) (conj #{} x)))
|
||||
ids (->set id)
|
||||
swagger (->> (dissoc swagger :id)
|
||||
(merge {:swagger "2.0"
|
||||
:x-id ids}))
|
||||
accept-route #(-> % second :swagger :id ->set (set/intersection ids) seq)
|
||||
accept-route #(-> % second :swagger :id (or ::default) ->set (set/intersection ids) seq)
|
||||
transform-endpoint (fn [[method {{:keys [coercion no-doc swagger] :as data} :data}]]
|
||||
(if (and data (not no-doc))
|
||||
[method
|
||||
|
|
@ -92,7 +92,6 @@
|
|||
transform-path (fn [[p _ c]]
|
||||
(if-let [endpoint (some->> c (keep transform-endpoint) (seq) (into {}))]
|
||||
[(path->template p) endpoint]))]
|
||||
(if id
|
||||
(let [paths (->> router (r/compiled-routes) (filter accept-route) (map transform-path) (into {}))]
|
||||
{:status 200
|
||||
:body (meta-merge swagger {:paths paths})})))))
|
||||
(let [paths (->> router (r/compiled-routes) (filter accept-route) (map transform-path) (into {}))]
|
||||
{:status 200
|
||||
:body (meta-merge swagger {:paths paths})}))))
|
||||
|
|
|
|||
|
|
@ -129,6 +129,9 @@
|
|||
:summary "plus"}}}}
|
||||
spec)))))
|
||||
|
||||
(defn spec-paths [app uri]
|
||||
(-> {:request-method :get, :uri uri} app :body :paths keys))
|
||||
|
||||
(deftest multiple-swagger-apis-test
|
||||
(let [ping-route ["/ping" {:get (constantly "ping")}]
|
||||
spec-route ["/swagger.json"
|
||||
|
|
@ -149,15 +152,13 @@
|
|||
["/deep" {:swagger {:id ::one}}
|
||||
ping-route]]
|
||||
["/one-two" {:swagger {:id #{::one ::two}}}
|
||||
spec-route]]))
|
||||
spec-paths (fn [uri]
|
||||
(-> {:request-method :get, :uri uri} app :body :paths keys))]
|
||||
spec-route]]))]
|
||||
(is (= ["/common/ping" "/one/ping" "/two/deep/ping"]
|
||||
(spec-paths "/one/swagger.json")))
|
||||
(spec-paths app "/one/swagger.json")))
|
||||
(is (= ["/common/ping" "/two/ping"]
|
||||
(spec-paths "/two/swagger.json")))
|
||||
(spec-paths app "/two/swagger.json")))
|
||||
(is (= ["/common/ping" "/one/ping" "/two/ping" "/two/deep/ping"]
|
||||
(spec-paths "/one-two/swagger.json")))))
|
||||
(spec-paths app "/one-two/swagger.json")))))
|
||||
|
||||
(deftest swagger-ui-congif-test
|
||||
(let [app (swagger-ui/create-swagger-ui-handler
|
||||
|
|
@ -168,3 +169,16 @@
|
|||
(is (= {:jsonEditor true, :url "/swagger.json"}
|
||||
(->> {:request-method :get, :uri "/config.json"}
|
||||
(app) :body (m/decode m/instance "application/json"))))))
|
||||
|
||||
(deftest without-swagger-id-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/ping"
|
||||
{:get (constantly "ping")}]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))]
|
||||
(is (= ["/ping"] (spec-paths app "/swagger.json")))
|
||||
(is (= #{::swagger/default}
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
(app) :body :x-id)))))
|
||||
|
|
|
|||
Loading…
Reference in a new issue