mirror of
https://github.com/metosin/reitit.git
synced 2025-12-16 16:01:11 +00:00
Merge remote-tracking branch 'origin/master' into fix/top-level-mw-registry
This commit is contained in:
commit
4e572e86d6
63 changed files with 304 additions and 187 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
|
@ -12,12 +12,25 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
|
|||
|
||||
[breakver]: https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md
|
||||
|
||||
## UNRELEASED
|
||||
## Unreleased
|
||||
|
||||
* Allow multimethods as handlers when validating [#755](https://github.com/metosin/reitit/pull/755)
|
||||
* Improve error reporting when generating OpenAPI fails [#754](https://github.com/metosin/reitit/pull/754)
|
||||
|
||||
## 0.9.1 (2025-05-27)
|
||||
|
||||
* **FIX**: response coercion threw an exception for unlisted HTTP status codes if there was no `:default`. Broken in 0.9.0. [#742](https://github.com/metosin/reitit/issues/742)
|
||||
|
||||
## 0.9.0 (2025-05-23)
|
||||
|
||||
* Improvements to mime type handling in `create-file-handler` and `create-resource-handler` [#733](https://github.com/metosin/reitit/pull/733)
|
||||
* New `:mime-types` option to configure a map from file extension to mime type
|
||||
* Don't set Content-Type header at all if mime type is not known
|
||||
* Fix location of openapi deprecated metadata [#714](https://github.com/metosin/reitit/pull/714)
|
||||
* Fix location of OpenAPI deprecated metadata [#714](https://github.com/metosin/reitit/pull/714)
|
||||
* **BREAKING** Fix & clarify `:responses :default` and `:content :default` handling. See [docs](./doc/ring/coercion.md). [#735](https://github.com/metosin/reitit/pull/735)
|
||||
* Summary: If `:responses <status>` is present, `:responses :default` is not used, even if `:responses <status>` defines no schema.
|
||||
* Should not break normal use, but might cause surprises related to defaults applying/not applying
|
||||
* **NOTE** This release depends on malli 0.18.0, which changes the format of OpenAPI & Swagger named schemas from `foo.bar/quux` to `foo.bar.quux`
|
||||
|
||||
## 0.8.0 (2025-03-28)
|
||||
|
||||
|
|
|
|||
53
README.md
53
README.md
|
|
@ -1,4 +1,4 @@
|
|||
# reitit
|
||||
# reitit
|
||||
|
||||
[](https://github.com/metosin/reitit/actions)
|
||||
[](https://cljdoc.org/d/metosin/reitit/)
|
||||
|
|
@ -54,7 +54,7 @@ There is [#reitit](https://clojurians.slack.com/messages/reitit/) in [Clojurians
|
|||
* `metosin/reitit-sieppari` support for [Sieppari](https://github.com/metosin/sieppari)
|
||||
* `metosin/reitit-dev` - development utilities
|
||||
|
||||
... * This is not a typo; the new `reitit-openapi` was released under the new, verified `fi.metosin` group. Existing
|
||||
... * This is not a typo; the new `reitit-openapi` was released under the new, verified `fi.metosin` group. Existing
|
||||
modules will continue to be released under `metosin` for compatibility purposes.
|
||||
|
||||
## Extra modules
|
||||
|
|
@ -66,7 +66,7 @@ modules will continue to be released under `metosin` for compatibility purposes.
|
|||
All main modules bundled:
|
||||
|
||||
```clj
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
```
|
||||
|
||||
Optionally, the parts can be required separately.
|
||||
|
|
@ -109,6 +109,7 @@ A Ring routing app with input & output coercion using [data-specs](https://githu
|
|||
(require '[reitit.ring :as ring])
|
||||
(require '[reitit.coercion.spec])
|
||||
(require '[reitit.ring.coercion :as rrc])
|
||||
(require '[reitit.ring.middleware.exception :as exception])
|
||||
(require '[reitit.ring.middleware.muuntaja :as muuntaja])
|
||||
(require '[reitit.ring.middleware.parameters :as parameters])
|
||||
|
||||
|
|
@ -124,39 +125,45 @@ A Ring routing app with input & output coercion using [data-specs](https://githu
|
|||
;; router data affecting all routes
|
||||
{:data {:coercion reitit.coercion.spec/coercion
|
||||
:muuntaja m/instance
|
||||
:middleware [parameters/parameters-middleware
|
||||
:middleware [parameters/parameters-middleware ; decoding query & form params
|
||||
muuntaja/format-middleware ; content negotiation
|
||||
exception/exception-middleware ; converting exceptions to HTTP responses
|
||||
rrc/coerce-request-middleware
|
||||
muuntaja/format-response-middleware
|
||||
rrc/coerce-response-middleware]}})))
|
||||
```
|
||||
|
||||
Valid request:
|
||||
|
||||
```clj
|
||||
(app {:request-method :get
|
||||
:uri "/api/math"
|
||||
:query-params {:x "1", :y "2"}})
|
||||
(-> (app {:request-method :get
|
||||
:uri "/api/math"
|
||||
:query-params {:x "1", :y "2"}})
|
||||
(update :body slurp))
|
||||
; {:status 200
|
||||
; :body {:total 3}}
|
||||
; :body "{\"total\":3}"
|
||||
; :headers {"Content-Type" "application/json; charset=utf-8"}}
|
||||
```
|
||||
|
||||
Invalid request:
|
||||
|
||||
```clj
|
||||
(app {:request-method :get
|
||||
:uri "/api/math"
|
||||
:query-params {:x "1", :y "a"}})
|
||||
;{:status 400,
|
||||
; :body {:type :reitit.coercion/request-coercion,
|
||||
; :coercion :spec,
|
||||
; :spec "(spec-tools.core/spec {:spec (clojure.spec.alpha/keys :req-un [:$spec20745/x :$spec20745/y]), :type :map, :keys #{:y :x}, :keys/req #{:y :x}})",
|
||||
; :problems [{:path [:y],
|
||||
; :pred "clojure.core/int?",
|
||||
; :val "a",
|
||||
; :via [:$spec20745/y],
|
||||
; :in [:y]}],
|
||||
; :value {:x "1", :y "a"},
|
||||
; :in [:request :query-params]}}
|
||||
(-> (app {:request-method :get
|
||||
:uri "/api/math"
|
||||
:query-params {:x "1", :y "a"}})
|
||||
(update :body jsonista.core/read-value))
|
||||
; {:status 400
|
||||
; :headers {"Content-Type" "application/json; charset=utf-8"}
|
||||
; :body {"spec" "(spec-tools.core/spec {:spec (clojure.spec.alpha/keys :req-un [:spec$8974/x :spec$8974/y]), :type :map, :leaf? false})"
|
||||
; "value" {"x" "1"
|
||||
; "y" "a"}
|
||||
; "problems" [{"via" ["spec$8974/y"]
|
||||
; "path" ["y"]
|
||||
; "pred" "clojure.core/int?"
|
||||
; "in" ["y"]
|
||||
; "val" "a"}]
|
||||
; "type" "reitit.coercion/request-coercion"
|
||||
; "coercion" "spec"
|
||||
; "in" ["request" "query-params"]}}
|
||||
```
|
||||
|
||||
## More examples
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ There is [#reitit](https://clojurians.slack.com/messages/reitit/) in [Clojurians
|
|||
All bundled:
|
||||
|
||||
```clj
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
```
|
||||
|
||||
Optionally, the parts can be required separately.
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ The default exception formatting uses `reitit.exception/exception`. It produces
|
|||
## Pretty Errors
|
||||
|
||||
```clj
|
||||
[metosin/reitit-dev "0.8.0"]
|
||||
[metosin/reitit-dev "0.9.1"]
|
||||
```
|
||||
|
||||
For human-readable and developer-friendly exception messages, there is `reitit.dev.pretty/exception` (in the `reitit-dev` module). It is inspired by the lovely errors messages of [ELM](https://elm-lang.org/blog/compiler-errors-for-humans) and [ETA](https://twitter.com/jyothsnasrin/status/1037703436043603968) and uses [fipp](https://github.com/brandonbloom/fipp), [expound](https://github.com/bhb/expound) and [spell-spec](https://github.com/bhauman/spell-spec) for most of heavy lifting.
|
||||
|
|
|
|||
|
|
@ -32,10 +32,6 @@ We use [Break Versioning][breakver]. Remember our promise: patch-level bumps nev
|
|||
[breakver]: https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md
|
||||
|
||||
```bash
|
||||
# Check that you're using Java 8! Making the release with a newer Java version
|
||||
# means that it is broken when used with Java 8.
|
||||
java -version
|
||||
|
||||
# new version
|
||||
./scripts/set-version "1.0.0"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Default Interceptors
|
||||
|
||||
```clj
|
||||
[metosin/reitit-interceptors "0.8.0"]
|
||||
[metosin/reitit-interceptors "0.9.1"]
|
||||
```
|
||||
|
||||
Just like the [ring default middleware](../ring/default_middleware.md), but for interceptors.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ Reitit has also support for [interceptors](http://pedestal.io/reference/intercep
|
|||
## Reitit-http
|
||||
|
||||
```clj
|
||||
[metosin/reitit-http "0.8.0"]
|
||||
[metosin/reitit-http "0.9.1"]
|
||||
```
|
||||
|
||||
A module for http-routing using interceptors instead of middleware. Builds on top of the [`reitit-ring`](../ring/ring.md) module having all the same features.
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
[Pedestal](http://pedestal.io/) is a backend web framework for Clojure. `reitit-pedestal` provides an alternative routing engine for Pedestal.
|
||||
|
||||
```clj
|
||||
[metosin/reitit-pedestal "0.8.0"]
|
||||
[metosin/reitit-pedestal "0.9.1"]
|
||||
```
|
||||
|
||||
Why should one use reitit instead of the Pedestal [default routing](http://pedestal.io/reference/routing-quick-reference)?
|
||||
|
|
@ -26,8 +26,8 @@ A minimalistic example on how to to swap the default-router with a reitit router
|
|||
```clj
|
||||
; [io.pedestal/pedestal.service "0.5.5"]
|
||||
; [io.pedestal/pedestal.jetty "0.5.5"]
|
||||
; [metosin/reitit-pedestal "0.8.0"]
|
||||
; [metosin/reitit "0.8.0"]
|
||||
; [metosin/reitit-pedestal "0.9.1"]
|
||||
; [metosin/reitit "0.9.1"]
|
||||
|
||||
(require '[io.pedestal.http :as server])
|
||||
(require '[reitit.pedestal :as pedestal])
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Sieppari
|
||||
|
||||
```clj
|
||||
[metosin/reitit-sieppari "0.8.0"]
|
||||
[metosin/reitit-sieppari "0.9.1"]
|
||||
```
|
||||
|
||||
[Sieppari](https://github.com/metosin/sieppari) is a new and fast interceptor implementation for Clojure, with pluggable async supporting [core.async](https://github.com/clojure/core.async), [Manifold](https://github.com/ztellman/manifold) and [Promesa](http://funcool.github.io/promesa/latest).
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ There is an extra option in http-router (actually, in the underlying interceptor
|
|||
### Printing Context Diffs
|
||||
|
||||
```clj
|
||||
[metosin/reitit-interceptors "0.8.0"]
|
||||
[metosin/reitit-interceptors "0.9.1"]
|
||||
```
|
||||
|
||||
Using `reitit.http.interceptors.dev/print-context-diffs` transformation, the context diffs between each interceptor are printed out to the console. To use it, add the following router option:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
Ring [defines middleware](https://github.com/ring-clojure/ring/wiki/Concepts#middleware) as a function of type `handler & args => request => response`. It is relatively easy to understand and allows for good performance. A downside is that the middleware chain is just a opaque function, making things like debugging and composition hard. It is too easy to apply the middlewares in wrong order.
|
||||
|
||||
For the basics of reitit middleware, [read this first](ring.md#middleware).
|
||||
|
||||
Reitit defines middleware as data:
|
||||
|
||||
1. A middleware can be defined as first-class data entries
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Default Middleware
|
||||
|
||||
```clj
|
||||
[metosin/reitit-middleware "0.8.0"]
|
||||
[metosin/reitit-middleware "0.9.1"]
|
||||
```
|
||||
|
||||
Any Ring middleware can be used with `reitit-ring`, but using data-driven middleware is preferred as they are easier to manage and in many cases yield better performance. `reitit-middleware` contains a set of common ring middleware, lifted into data-driven middleware.
|
||||
|
|
@ -17,8 +17,6 @@ Any Ring middleware can be used with `reitit-ring`, but using data-driven middle
|
|||
`reitit.ring.middleware.parameters/parameters-middleware` to capture query- and form-params. Wraps
|
||||
`ring.middleware.params/wrap-params`.
|
||||
|
||||
**NOTE**: This middleware will be factored into two parts: a query-parameters middleware and a Muuntaja format responsible for the the `application/x-www-form-urlencoded` body format. cf. https://github.com/metosin/reitit/issues/134
|
||||
|
||||
## Exception Handling
|
||||
|
||||
See [Exception Handling with Ring](exceptions.md).
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Exception Handling with Ring
|
||||
|
||||
```clj
|
||||
[metosin/reitit-middleware "0.8.0"]
|
||||
[metosin/reitit-middleware "0.9.1"]
|
||||
```
|
||||
|
||||
Exceptions thrown in router creation can be [handled with custom exception handler](../basics/error_messages.md). By default, exceptions thrown at runtime from a handler or a middleware are not caught by the `reitit.ring/ring-handler`. A good practice is to have a top-level exception handler to log and format errors for clients.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
Read more about the [Ring Concepts](https://github.com/ring-clojure/ring/wiki/Concepts).
|
||||
|
||||
```clj
|
||||
[metosin/reitit-ring "0.8.0"]
|
||||
[metosin/reitit-ring "0.9.1"]
|
||||
```
|
||||
|
||||
## `reitit.ring/router`
|
||||
|
|
@ -141,7 +141,7 @@ Name-based reverse routing:
|
|||
|
||||
# Middleware
|
||||
|
||||
Middleware can be mounted using a `:middleware` key - either to top-level or under request method submap. Its value should be a vector of `reitit.middleware/IntoMiddleware` values. These include:
|
||||
Middleware can be mounted using a `:middleware` key in [Route Data](../basics/route_data.md) - either to top-level or under request method submap. Its value should be a vector of `reitit.middleware/IntoMiddleware` values. These include:
|
||||
|
||||
1. normal ring middleware function `handler -> request -> response`
|
||||
2. vector of middleware function `[handler args*] -> request -> response` and it's arguments
|
||||
|
|
@ -194,11 +194,56 @@ Top-level middleware, applied before any routing is done:
|
|||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [[mw :api]]}
|
||||
["/api" {:middleware [[wrap :api]]}
|
||||
["/get" {:get handler}]])
|
||||
nil
|
||||
{:middleware [[mw :top]]}))
|
||||
{:middleware [[wrap :top]]}))
|
||||
|
||||
(app {:request-method :get, :uri "/api/get"})
|
||||
; {:status 200, :body [:top :api :ok]}
|
||||
```
|
||||
|
||||
Same middleware for all routes, using [top-level route data](route_data.md#top-level-route-data):
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
["/get" {:get handler
|
||||
:middleware [[wrap :specific]]}]]
|
||||
{:data {:middleware [[wrap :generic]]}})))
|
||||
|
||||
(app {:request-method :get, :uri "/api/get"})
|
||||
; {:status 200, :body [:generic :specific :handler]}
|
||||
```
|
||||
|
||||
## Execution order
|
||||
|
||||
Here's a full example that shows the execution order of the middleware
|
||||
using all of the above techniques:
|
||||
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api" {:middleware [[wrap :3-parent]]}
|
||||
["/get" {:get handler
|
||||
:middleware [[wrap :4-route]]}]]
|
||||
{:data {:middleware [[wrap :2-top-level-route-data]]}})
|
||||
nil
|
||||
{:middleware [[wrap :1-top]]}))
|
||||
|
||||
(app {:request-method :get, :uri "/api/get"})
|
||||
; {:status 200, :body [:1-top :2-top-level-route-data :3-parent :4-route :handler]}
|
||||
```
|
||||
|
||||
## Which method should I use for defining middleware?
|
||||
|
||||
- If you have middleware that you want to apply to the default handler (second argument of `ring/ring-handler`), use _top-level middleware_
|
||||
- If you have a generic middleware, that doesn't depend on the route, use _top-level middleware_ or _top-level route data_
|
||||
- If you are using top-level route data anyway for some other reasons, it might be clearest to have all the middleware there. This is what most of the reitit examples do.
|
||||
- If you want to apply a middleware to only a couple of routes, use _nested middleware_ (ie. _route data_)
|
||||
- If you want a middleware to apply to all routes, but use route-specific data, you need _top-level route data_ combined with [Compiling Middleware](compiling_middleware.md)
|
||||
- This is what many reitit features like [Ring Coercion](coercion.md) do. Check the examples & docs for the reitit features you want to use!
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Swagger Support
|
||||
|
||||
```
|
||||
[metosin/reitit-swagger "0.8.0"]
|
||||
[metosin/reitit-swagger "0.9.1"]
|
||||
```
|
||||
|
||||
Reitit supports [Swagger2](https://swagger.io/) documentation, thanks to [schema-tools](https://github.com/metosin/schema-tools) and [spec-tools](https://github.com/metosin/spec-tools). Documentation is extracted from route definitions, coercion `:parameters` and `:responses` and from a set of new documentation keys.
|
||||
|
|
@ -47,7 +47,7 @@ If you need to post-process the generated spec, just wrap the handler with a cus
|
|||
[Swagger-ui](https://github.com/swagger-api/swagger-ui) is a user interface to visualize and interact with the Swagger specification. To make things easy, there is a pre-integrated version of the swagger-ui as a separate module.
|
||||
|
||||
```
|
||||
[metosin/reitit-swagger-ui "0.8.0"]
|
||||
[metosin/reitit-swagger-ui "0.9.1"]
|
||||
```
|
||||
|
||||
`reitit.swagger-ui/create-swagger-ui-handler` can be used to create a ring-handler to serve the swagger-ui. It accepts the following options:
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ There is an extra option in the Ring router (actually, in the underlying middlew
|
|||
### Printing Request Diffs
|
||||
|
||||
```clj
|
||||
[metosin/reitit-middleware "0.8.0"]
|
||||
[metosin/reitit-middleware "0.9.1"]
|
||||
```
|
||||
|
||||
Using `reitit.ring.middleware.dev/print-request-diffs` transformation, the request diffs between each middleware are printed out to the console. To use it, add the following router option:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@
|
|||
:description "Reitit Buddy Auth App"
|
||||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[buddy "2.0.0"]]
|
||||
:repl-options {:init-ns example.server})
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
[ring "1.12.1"]
|
||||
[hiccup "1.0.5"]
|
||||
[org.clojure/clojurescript "1.11.132"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit-schema "0.8.0"]
|
||||
[metosin/reitit-frontend "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/reitit-schema "0.9.1"]
|
||||
[metosin/reitit-frontend "0.9.1"]
|
||||
[cljsjs/react "17.0.2-0"]
|
||||
[cljsjs/react-dom "17.0.2-0"]
|
||||
;; Just for pretty printting the match
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
[ring "1.12.1"]
|
||||
[hiccup "1.0.5"]
|
||||
[org.clojure/clojurescript "1.11.132"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit-schema "0.8.0"]
|
||||
[metosin/reitit-frontend "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/reitit-schema "0.9.1"]
|
||||
[metosin/reitit-frontend "0.9.1"]
|
||||
[cljsjs/react "17.0.2-0"]
|
||||
[cljsjs/react-dom "17.0.2-0"]
|
||||
;; Just for pretty printting the match
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
[ring "1.12.1"]
|
||||
[hiccup "1.0.5"]
|
||||
[org.clojure/clojurescript "1.10.520"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit-spec "0.8.0"]
|
||||
[metosin/reitit-frontend "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/reitit-spec "0.9.1"]
|
||||
[metosin/reitit-frontend "0.9.1"]
|
||||
[cljsjs/react "17.0.2-0"]
|
||||
[cljsjs/react-dom "17.0.2-0"]
|
||||
;; Just for pretty printting the match
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
[ring "1.12.1"]
|
||||
[hiccup "1.0.5"]
|
||||
[org.clojure/clojurescript "1.11.132"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit-malli "0.8.0"]
|
||||
[metosin/reitit-frontend "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/reitit-malli "0.9.1"]
|
||||
[metosin/reitit-frontend "0.9.1"]
|
||||
[cljsjs/react "17.0.2-0"]
|
||||
[cljsjs/react-dom "17.0.2-0"]
|
||||
;; Just for pretty printting the match
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
[ring "1.12.1"]
|
||||
[hiccup "1.0.5"]
|
||||
[org.clojure/clojurescript "1.11.132"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit-spec "0.8.0"]
|
||||
[metosin/reitit-frontend "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/reitit-spec "0.9.1"]
|
||||
[metosin/reitit-frontend "0.9.1"]
|
||||
[cljsjs/react "17.0.2-0"]
|
||||
[cljsjs/react-dom "17.0.2-0"]
|
||||
;; Just for pretty printting the match
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
(defproject frontend-re-frame "0.1.0-SNAPSHOT"
|
||||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[org.clojure/clojurescript "1.11.132"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[reagent "1.2.0"]
|
||||
[re-frame "0.10.6"]
|
||||
[cljsjs/react "17.0.2-0"]
|
||||
|
|
|
|||
|
|
@ -10,9 +10,9 @@
|
|||
[ring "1.12.1"]
|
||||
[hiccup "1.0.5"]
|
||||
[org.clojure/clojurescript "1.11.132"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit-spec "0.8.0"]
|
||||
[metosin/reitit-frontend "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/reitit-spec "0.9.1"]
|
||||
[metosin/reitit-frontend "0.9.1"]
|
||||
[cljsjs/react "17.0.2-0"]
|
||||
[cljsjs/react-dom "17.0.2-0"]
|
||||
;; Just for pretty printting the match
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[aleph "0.7.1"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/ring-swagger-ui "5.9.0"]]
|
||||
:repl-options {:init-ns example.server})
|
||||
|
|
|
|||
|
|
@ -5,5 +5,5 @@
|
|||
[funcool/promesa "11.0.678"]
|
||||
[manifold "0.4.2"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]]
|
||||
[metosin/reitit "0.9.1"]]
|
||||
:repl-options {:init-ns example.server})
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@
|
|||
:description "Reitit coercion with vanilla ring"
|
||||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]])
|
||||
[metosin/reitit "0.9.1"]])
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[metosin/jsonista "0.3.8"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/ring-swagger-ui "5.9.0"]]
|
||||
:repl-options {:init-ns example.server}
|
||||
:profiles {:dev {:dependencies [[ring/ring-mock "0.4.0"]]}})
|
||||
|
|
|
|||
|
|
@ -137,6 +137,32 @@
|
|||
{:from "0003"
|
||||
:amount -6.5}]}})}}]
|
||||
|
||||
["/complex"
|
||||
{:post {:summary "Complex schema with :multi, :enum, :tuple etc."
|
||||
:request {:content
|
||||
{:default
|
||||
{:schema [:map
|
||||
[:vector-of-tuples [:vector [:tuple :string :int]]]
|
||||
[:regex [:re "[0-9]+"]]
|
||||
[:enum [:enum 1 3 5 42]]
|
||||
[:multi [:multi {:dispatch :type}
|
||||
[:literal [:map
|
||||
[:type [:= :literal]]
|
||||
[:value [:or :int :string]]]]
|
||||
[:reference [:map
|
||||
[:type [:= :reference]]
|
||||
[:description :string]
|
||||
[:ref :uuid]]]]]]
|
||||
:example {:vector-of-tuples [["a" 1] ["b" 2]]
|
||||
:regex "01234"
|
||||
:enum 5
|
||||
:multi {:type :literal
|
||||
:value "x"}}}}}
|
||||
:responses {200 {:content {:default {:schema [:map]}}}}
|
||||
:handler (fn [request]
|
||||
{:status 200
|
||||
:body (:body request)})}}]
|
||||
|
||||
["/secure"
|
||||
{:tags #{"secure"}
|
||||
:openapi {:security [{"auth" []}]}}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[io.pedestal/pedestal.service "0.6.3"]
|
||||
[io.pedestal/pedestal.jetty "0.6.3"]
|
||||
[metosin/reitit-malli "0.8.0"]
|
||||
[metosin/reitit-pedestal "0.8.0"]
|
||||
[metosin/reitit "0.8.0"]]
|
||||
[metosin/reitit-malli "0.9.1"]
|
||||
[metosin/reitit-pedestal "0.9.1"]
|
||||
[metosin/reitit "0.9.1"]]
|
||||
:repl-options {:init-ns server})
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[io.pedestal/pedestal.service "0.6.3"]
|
||||
[io.pedestal/pedestal.jetty "0.6.3"]
|
||||
[metosin/reitit-pedestal "0.8.0"]
|
||||
[metosin/reitit "0.8.0"]]
|
||||
[metosin/reitit-pedestal "0.9.1"]
|
||||
[metosin/reitit "0.9.1"]]
|
||||
:repl-options {:init-ns example.server})
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[io.pedestal/pedestal.service "0.6.3"]
|
||||
[io.pedestal/pedestal.jetty "0.6.3"]
|
||||
[metosin/reitit-pedestal "0.8.0"]
|
||||
[metosin/reitit "0.8.0"]]
|
||||
[metosin/reitit-pedestal "0.9.1"]
|
||||
[metosin/reitit "0.9.1"]]
|
||||
:repl-options {:init-ns example.server})
|
||||
|
|
|
|||
|
|
@ -2,5 +2,5 @@
|
|||
:description "Reitit Ring App"
|
||||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]]
|
||||
[metosin/reitit "0.9.1"]]
|
||||
:repl-options {:init-ns example.server})
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
:description "Reitit Ring App with Integrant"
|
||||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[integrant "0.8.1"]]
|
||||
:main example.server
|
||||
:repl-options {:init-ns user}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[metosin/jsonista "0.3.8"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]]
|
||||
[metosin/reitit "0.9.1"]]
|
||||
:repl-options {:init-ns example.server}
|
||||
:profiles {:dev {:dependencies [[ring/ring-mock "0.4.0"]]}})
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[metosin/jsonista "0.3.8"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/ring-swagger-ui "5.9.0"]]
|
||||
:repl-options {:init-ns example.server}
|
||||
:profiles {:dev {:dependencies [[ring/ring-mock "0.4.0"]]}})
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
:description "Reitit Ring App with Swagger"
|
||||
:dependencies [[org.clojure/clojure "1.11.2"]
|
||||
[ring/ring-jetty-adapter "1.12.1"]
|
||||
[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit "0.9.1"]
|
||||
[metosin/ring-swagger-ui "5.9.0"]]
|
||||
:repl-options {:init-ns example.server}
|
||||
:profiles {:dev {:dependencies [[ring/ring-mock "0.4.0"]]}})
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-core "0.8.0"
|
||||
(defproject metosin/reitit-core "0.9.1"
|
||||
:description "Snappy data-driven router for Clojure(Script)"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -178,8 +178,9 @@
|
|||
(let [format->coercer (or (status->format->coercer (:status response))
|
||||
(status->format->coercer :default))
|
||||
format (extract-response-format request response)
|
||||
coercer (or (format->coercer format)
|
||||
(format->coercer :default))]
|
||||
coercer (when format->coercer
|
||||
(or (format->coercer format)
|
||||
(format->coercer :default)))]
|
||||
(if-not coercer
|
||||
response
|
||||
(let [value (:body response)
|
||||
|
|
|
|||
|
|
@ -37,8 +37,11 @@
|
|||
;; Default data
|
||||
;;
|
||||
|
||||
(defn -multi? [x]
|
||||
(instance? #?(:clj clojure.lang.MultiFn :cljs cljs.core.MultiFn) x))
|
||||
|
||||
(s/def ::name keyword?)
|
||||
(s/def ::handler (s/or :fn fn? :var var?))
|
||||
(s/def ::handler (s/or :fn fn? :var var? :multi -multi?))
|
||||
(s/def ::no-doc boolean?)
|
||||
(s/def ::conflicting boolean?)
|
||||
(s/def ::default-data
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-dev "0.8.0"
|
||||
(defproject metosin/reitit-dev "0.9.1"
|
||||
:description "Snappy data-driven router for Clojure(Script)"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-frontend "0.8.0"
|
||||
(defproject metosin/reitit-frontend "0.9.1"
|
||||
:description "Reitit: Clojurescript frontend routing core"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-http "0.8.0"
|
||||
(defproject metosin/reitit-http "0.9.1"
|
||||
:description "Reitit: HTTP routing with interceptors"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-interceptors "0.8.0"
|
||||
(defproject metosin/reitit-interceptors "0.9.1"
|
||||
:description "Reitit, common interceptors bundled"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-malli "0.8.0"
|
||||
(defproject metosin/reitit-malli "0.9.1"
|
||||
:description "Reitit: Malli coercion"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-middleware "0.8.0"
|
||||
(defproject metosin/reitit-middleware "0.9.1"
|
||||
:description "Reitit, common middleware bundled"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject fi.metosin/reitit-openapi "0.8.0"
|
||||
(defproject fi.metosin/reitit-openapi "0.9.1"
|
||||
:description "Reitit: OpenAPI-support"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -206,20 +206,23 @@
|
|||
accept-route (fn [route]
|
||||
(-> route second :openapi :id (or ::default) (trie/into-set) (set/intersection ids) seq))
|
||||
definitions (volatile! {})
|
||||
transform-endpoint (fn [[method {{:keys [coercion no-doc openapi] :as data} :data
|
||||
middleware :middleware
|
||||
interceptors :interceptors}]]
|
||||
(if (and data (not no-doc))
|
||||
[method
|
||||
(meta-merge
|
||||
(apply meta-merge (keep (comp :openapi :data) middleware))
|
||||
(apply meta-merge (keep (comp :openapi :data) interceptors))
|
||||
(if coercion
|
||||
(-get-apidocs-openapi coercion data definitions))
|
||||
(select-keys data [:tags :summary :description])
|
||||
(strip-top-level-keys openapi))]))
|
||||
transform-endpoint (fn [path [method {{:keys [coercion no-doc openapi] :as data} :data
|
||||
middleware :middleware
|
||||
interceptors :interceptors}]]
|
||||
(try
|
||||
(if (and data (not no-doc))
|
||||
[method
|
||||
(meta-merge
|
||||
(apply meta-merge (keep (comp :openapi :data) middleware))
|
||||
(apply meta-merge (keep (comp :openapi :data) interceptors))
|
||||
(if coercion
|
||||
(-get-apidocs-openapi coercion data definitions))
|
||||
(select-keys data [:tags :summary :description])
|
||||
(strip-top-level-keys openapi))])
|
||||
(catch Throwable t
|
||||
(throw (ex-info "While building openapi docs" {:path path :method method} t)))))
|
||||
transform-path (fn [[p _ c]]
|
||||
(if-let [endpoint (some->> c (keep transform-endpoint) (seq) (into {}))]
|
||||
(if-let [endpoint (some->> c (keep (partial transform-endpoint p)) (seq) (into {}))]
|
||||
[(openapi-path p (r/options router)) endpoint]))
|
||||
map-in-order #(->> % (apply concat) (apply array-map))
|
||||
paths (->> router (r/compiled-routes) (filter accept-route) (map transform-path) map-in-order)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-pedestal "0.8.0"
|
||||
(defproject metosin/reitit-pedestal "0.9.1"
|
||||
:description "Reitit + Pedestal Integration"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-ring "0.8.0"
|
||||
(defproject metosin/reitit-ring "0.9.1"
|
||||
:description "Reitit: Ring routing"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-schema "0.8.0"
|
||||
(defproject metosin/reitit-schema "0.9.1"
|
||||
:description "Reitit: Plumatic Schema coercion"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-sieppari "0.8.0"
|
||||
(defproject metosin/reitit-sieppari "0.9.1"
|
||||
:description "Reitit: Sieppari Interceptors"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-spec "0.8.0"
|
||||
(defproject metosin/reitit-spec "0.9.1"
|
||||
:description "Reitit: clojure.spec coercion"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-swagger-ui "0.8.0"
|
||||
(defproject metosin/reitit-swagger-ui "0.9.1"
|
||||
:description "Reitit: Swagger-ui support"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-swagger "0.8.0"
|
||||
(defproject metosin/reitit-swagger "0.9.1"
|
||||
:description "Reitit: Swagger-support"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit "0.8.0"
|
||||
(defproject metosin/reitit "0.9.1"
|
||||
:description "Snappy data-driven router for Clojure(Script)"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
|
|||
9
package-lock.json
generated
9
package-lock.json
generated
|
|
@ -9,7 +9,7 @@
|
|||
"shadow-cljs": "^2.28.22"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@seriousme/openapi-schema-validator": "^2.3.1",
|
||||
"@seriousme/openapi-schema-validator": "^2.4.0",
|
||||
"karma": "^6.4.4",
|
||||
"karma-chrome-launcher": "^3.2.0",
|
||||
"karma-cli": "^2.0.0",
|
||||
|
|
@ -27,11 +27,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@seriousme/openapi-schema-validator": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@seriousme/openapi-schema-validator/-/openapi-schema-validator-2.3.1.tgz",
|
||||
"integrity": "sha512-szUXBZJUhq+Yw+vUro2QeltSIoZvMDQi3MLqJhIKcRcRYyFt9B6dyjMD1RVf3nFvNAHkWqa48NJA46ti2P8smA==",
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@seriousme/openapi-schema-validator/-/openapi-schema-validator-2.4.0.tgz",
|
||||
"integrity": "sha512-2PWq2QbDMu+CANpBLZ2Uch9PgTIiftLpiLH4lcaykjV463f4Vt9eD61EeaVI++D0HII4JKnptX46391pII1XZA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^8.17.1",
|
||||
"ajv-draft-04": "^1.0.0",
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"name": "reitit",
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@seriousme/openapi-schema-validator": "^2.3.1",
|
||||
"@seriousme/openapi-schema-validator": "^2.4.0",
|
||||
"karma": "^6.4.4",
|
||||
"karma-chrome-launcher": "^3.2.0",
|
||||
"karma-cli": "^2.0.0",
|
||||
|
|
|
|||
38
project.clj
38
project.clj
|
|
@ -1,4 +1,4 @@
|
|||
(defproject metosin/reitit-parent "0.8.0"
|
||||
(defproject metosin/reitit-parent "0.9.1"
|
||||
:description "Snappy data-driven router for Clojure(Script)"
|
||||
:url "https://github.com/metosin/reitit"
|
||||
:license {:name "Eclipse Public License"
|
||||
|
|
@ -18,29 +18,29 @@
|
|||
;; TODO: need to verify that the code actually worked with Java1.8, see #242
|
||||
;; Ring 1.13.1 drops support for Java 1.8 so lets target 11
|
||||
:javac-options ["-Xlint:unchecked" "-target" "11" "-source" "11"]
|
||||
:managed-dependencies [[metosin/reitit "0.8.0"]
|
||||
[metosin/reitit-core "0.8.0"]
|
||||
[metosin/reitit-dev "0.8.0"]
|
||||
[metosin/reitit-spec "0.8.0"]
|
||||
[metosin/reitit-malli "0.8.0"]
|
||||
[metosin/reitit-schema "0.8.0"]
|
||||
[metosin/reitit-ring "0.8.0"]
|
||||
[metosin/reitit-middleware "0.8.0"]
|
||||
[metosin/reitit-http "0.8.0"]
|
||||
[metosin/reitit-interceptors "0.8.0"]
|
||||
[metosin/reitit-swagger "0.8.0"]
|
||||
[fi.metosin/reitit-openapi "0.8.0"]
|
||||
[metosin/reitit-swagger-ui "0.8.0"]
|
||||
[metosin/reitit-frontend "0.8.0"]
|
||||
[metosin/reitit-sieppari "0.8.0"]
|
||||
[metosin/reitit-pedestal "0.8.0"]
|
||||
:managed-dependencies [[metosin/reitit "0.9.1"]
|
||||
[metosin/reitit-core "0.9.1"]
|
||||
[metosin/reitit-dev "0.9.1"]
|
||||
[metosin/reitit-spec "0.9.1"]
|
||||
[metosin/reitit-malli "0.9.1"]
|
||||
[metosin/reitit-schema "0.9.1"]
|
||||
[metosin/reitit-ring "0.9.1"]
|
||||
[metosin/reitit-middleware "0.9.1"]
|
||||
[metosin/reitit-http "0.9.1"]
|
||||
[metosin/reitit-interceptors "0.9.1"]
|
||||
[metosin/reitit-swagger "0.9.1"]
|
||||
[fi.metosin/reitit-openapi "0.9.1"]
|
||||
[metosin/reitit-swagger-ui "0.9.1"]
|
||||
[metosin/reitit-frontend "0.9.1"]
|
||||
[metosin/reitit-sieppari "0.9.1"]
|
||||
[metosin/reitit-pedestal "0.9.1"]
|
||||
[metosin/ring-swagger-ui "5.20.0"]
|
||||
[metosin/spec-tools "0.10.7"]
|
||||
[metosin/schema-tools "0.13.1"]
|
||||
[metosin/muuntaja "0.6.11"]
|
||||
[metosin/jsonista "0.3.13"]
|
||||
[metosin/sieppari "0.0.0-alpha13"]
|
||||
[metosin/malli "0.17.0"]
|
||||
[metosin/malli "0.18.0"]
|
||||
|
||||
;; https://clojureverse.org/t/depending-on-the-right-versions-of-jackson-libraries/5111
|
||||
[com.fasterxml.jackson.core/jackson-core "2.18.2"]
|
||||
|
|
@ -99,7 +99,7 @@
|
|||
[metosin/muuntaja "0.6.11"]
|
||||
[metosin/sieppari "0.0.0-alpha13"]
|
||||
[metosin/jsonista "0.3.13"]
|
||||
[metosin/malli "0.17.0"]
|
||||
[metosin/malli "0.18.0"]
|
||||
[lambdaisland/deep-diff "0.0-47"]
|
||||
[meta-merge "1.0.0"]
|
||||
[com.bhauman/spell-spec "0.1.2"]
|
||||
|
|
|
|||
|
|
@ -1009,7 +1009,7 @@
|
|||
{:content
|
||||
{"application/json"
|
||||
{:schema
|
||||
{:$ref "#/components/schemas/reitit.openapi-test~1Plus"}}}}}}
|
||||
{:$ref "#/components/schemas/reitit.openapi-test.Plus"}}}}}}
|
||||
"/get"
|
||||
{:get
|
||||
{:parameters
|
||||
|
|
@ -1019,19 +1019,15 @@
|
|||
{:in "query"
|
||||
:name :y
|
||||
:required true
|
||||
:schema {:$ref "#/components/schemas/reitit.openapi-test~1Y"}}]}}}
|
||||
:schema {:$ref "#/components/schemas/reitit.openapi-test.Y"}}]}}}
|
||||
:components
|
||||
{:schemas
|
||||
{"reitit.openapi-test/Plus"
|
||||
{"reitit.openapi-test.Plus"
|
||||
{:type "object"
|
||||
:properties
|
||||
{:x {:type "integer"}
|
||||
:y {:$ref "#/components/schemas/reitit.openapi-test~1Y"}}
|
||||
:y {:$ref "#/components/schemas/reitit.openapi-test.Y"}}
|
||||
:required [:x :y]}
|
||||
"reitit.openapi-test/Y" {:type "integer"}}}}
|
||||
"reitit.openapi-test.Y" {:type "integer"}}}}
|
||||
spec))
|
||||
;; TODO: the OAS 3.1 json schema disallows "/" in :components :schemas keys,
|
||||
;; even though the text of the spec allows it. See:
|
||||
;; https://github.com/seriousme/openapi-schema-validator/blob/772375bf4895f0e641d103c27140cdd1d2afc34e/schemas/v3.1/schema.json#L282
|
||||
#_
|
||||
(is (nil? (validate spec))))))
|
||||
|
|
|
|||
|
|
@ -695,15 +695,22 @@
|
|||
(testing (str coercion)
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/foo" {:post {:responses {200 {:content {:default {:schema schema-200}}}
|
||||
201 {:content {"application/edn" {:schema schema-200}}}
|
||||
202 {:description "status code and content-type explicitly mentioned, but no :schema"
|
||||
:content {"application/edn" {}
|
||||
"application/json" {}}}
|
||||
:default {:content {"application/json" {:schema schema-default}}}}
|
||||
:handler (fn [req]
|
||||
{:status (-> req :body-params :status)
|
||||
:body (-> req :body-params :response)})}}]
|
||||
[["/foo" {:post {:responses {200 {:content {:default {:schema schema-200}}}
|
||||
201 {:content {"application/edn" {:schema schema-200}}}
|
||||
202 {:description "status code and content-type explicitly mentioned, but no :schema"
|
||||
:content {"application/edn" {}
|
||||
"application/json" {}}}
|
||||
:default {:content {"application/json" {:schema schema-default}}}}
|
||||
:handler (fn [req]
|
||||
{:status (-> req :body-params :status)
|
||||
:body (-> req :body-params :response)})}}]
|
||||
["/bar" {:post {:responses {200 {:content {:default {:schema schema-200}}}}
|
||||
:handler (fn [req]
|
||||
{:status (-> req :body-params :status)
|
||||
:body (-> req :body-params :response)})}}]
|
||||
["/quux" {:post {:handler (fn [req]
|
||||
{:status (-> req :body-params :status)
|
||||
:body (-> req :body-params :response)})}}]]
|
||||
{:validate reitit.ring.spec/validate
|
||||
:data {:middleware [rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
|
|
@ -713,40 +720,52 @@
|
|||
(app request)
|
||||
(catch ExceptionInfo e
|
||||
(select-keys (ex-data e) [:type :in]))))
|
||||
request (fn [body]
|
||||
request (fn [uri body]
|
||||
{:request-method :post
|
||||
:uri "/foo"
|
||||
:uri uri
|
||||
:muuntaja/request {:format "application/json"}
|
||||
:muuntaja/response {:format (:format body "application/json")}
|
||||
:body-params body})]
|
||||
(testing "explicit response schema"
|
||||
(is (= {:status 200 :body {:a 1}}
|
||||
(call (request {:status 200 :response {:a 1}})))
|
||||
(call (request "/foo" {:status 200 :response {:a 1}})))
|
||||
"valid response")
|
||||
(is (= {:type :reitit.coercion/response-coercion, :in [:response :body]}
|
||||
(call (request {:status 200 :response {:b 1}})))
|
||||
(call (request "/foo" {:status 200 :response {:b 1}})))
|
||||
"invalid response")
|
||||
(is (= {:type :reitit.coercion/response-coercion, :in [:response :body]}
|
||||
(call (request {:status 200 :response {:b 1} :format "application/edn"})))
|
||||
(call (request "/foo" {:status 200 :response {:b 1} :format "application/edn"})))
|
||||
"invalid response, different content-type"))
|
||||
(testing "explicit response schema, but for the wrong content-type"
|
||||
(is (= {:status 201 :body "anything goes!"}
|
||||
(call (request {:status 201 :response "anything goes!"})))
|
||||
(call (request "/foo" {:status 201 :response "anything goes!"})))
|
||||
"no coercion applied"))
|
||||
(testing "response config without :schema"
|
||||
(is (= {:status 202 :body "anything goes!"}
|
||||
(call (request {:status 202 :response "anything goes!"})))
|
||||
(call (request "/foo" {:status 202 :response "anything goes!"})))
|
||||
"no coercion applied"))
|
||||
(testing "default response schema"
|
||||
(is (= {:status 300 :body {:b 2}}
|
||||
(call (request {:status 300 :response {:b 2}})))
|
||||
(call (request "/foo" {:status 300 :response {:b 2}})))
|
||||
"valid response")
|
||||
(is (= {:type :reitit.coercion/response-coercion, :in [:response :body]}
|
||||
(call (request {:status 300 :response {:a 2}})))
|
||||
(call (request "/foo" {:status 300 :response {:a 2}})))
|
||||
"invalid response")
|
||||
(is (= {:status 300 :body "anything goes!"}
|
||||
(call (request {:status 300 :response "anything goes!" :format "application/edn"})))
|
||||
"no coercion applied due to content-type")))))))
|
||||
(call (request "/foo" {:status 300 :response "anything goes!" :format "application/edn"})))
|
||||
"no coercion applied due to content-type"))
|
||||
(testing "no default"
|
||||
(is (= {:status 200 :body {:a 1}}
|
||||
(call (request "/bar" {:status 200 :response {:a 1}})))
|
||||
"valid response")
|
||||
(testing "unlisted response code"
|
||||
(is (= {:status 202 :body "anything goes!"}
|
||||
(call (request "/bar" {:status 202 :response "anything goes!"})))
|
||||
"no coercion applied")))
|
||||
(testing "no response coercion"
|
||||
(is (= {:status 200 :body "anything goes!"}
|
||||
(call (request "/quux" {:status 200 :response "anything goes!"})))
|
||||
"no coercion applied")))))))
|
||||
|
||||
#?(:clj
|
||||
(deftest muuntaja-test
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
(s/def ::role #{:admin :user})
|
||||
(s/def ::roles (s/and (s/coll-of ::role :into #{}) set?))
|
||||
|
||||
(defmulti my-multi (constantly :default))
|
||||
(defmethod my-multi :default [x] x)
|
||||
|
||||
(deftest route-data-validation-test
|
||||
(testing "validation is turned off by default"
|
||||
(is (r/router?
|
||||
|
|
@ -85,6 +88,12 @@
|
|||
(ring/router
|
||||
["/api" {:handler identity
|
||||
:middleware '()}]
|
||||
{:validate rrs/validate}))))
|
||||
|
||||
(testing "handler can be a multimethod"
|
||||
(is (r/router?
|
||||
(ring/router
|
||||
["/api" {:get {:handler my-multi}}]
|
||||
{:validate rrs/validate})))))
|
||||
|
||||
(deftest coercion-spec-test
|
||||
|
|
|
|||
|
|
@ -161,14 +161,14 @@
|
|||
expected {:x-id #{::math}
|
||||
:swagger "2.0"
|
||||
:info {:title "my-api"}
|
||||
:definitions {"reitit.swagger-test/req-key" {:type "string"
|
||||
:definitions {"reitit.swagger-test.req-key" {:type "string"
|
||||
:x-anyOf [{:type "string"}
|
||||
{:type "string"}]}
|
||||
"reitit.swagger-test/req-val" {:type "object"
|
||||
"reitit.swagger-test.req-val" {:type "object"
|
||||
:x-anyOf [{:type "object"}
|
||||
{:type "string"}]}
|
||||
"reitit.swagger-test/resp-map" {:type "object"},
|
||||
"reitit.swagger-test/resp-string" {:type "string"
|
||||
"reitit.swagger-test.resp-map" {:type "object"},
|
||||
"reitit.swagger-test.resp-string" {:type "string"
|
||||
:minLength 1}}
|
||||
:paths {"/api/spec/plus/{z}" {:patch {:parameters []
|
||||
:summary "patch"
|
||||
|
|
@ -287,12 +287,12 @@
|
|||
:schema
|
||||
{:type "object"
|
||||
:additionalProperties
|
||||
{:$ref "#/definitions/reitit.swagger-test~1req-val"}}}]
|
||||
{:$ref "#/definitions/reitit.swagger-test.req-val"}}}]
|
||||
:responses {200
|
||||
{:schema
|
||||
{:$ref "#/definitions/reitit.swagger-test~1resp-map"
|
||||
:x-anyOf [{:$ref "#/definitions/reitit.swagger-test~1resp-map"}
|
||||
{:$ref "#/definitions/reitit.swagger-test~1resp-string"}]}
|
||||
{:$ref "#/definitions/reitit.swagger-test.resp-map"
|
||||
:x-anyOf [{:$ref "#/definitions/reitit.swagger-test.resp-map"}
|
||||
{:$ref "#/definitions/reitit.swagger-test.resp-string"}]}
|
||||
:description ""}
|
||||
500 {:description "fail"}}
|
||||
:summary "plus put with definitions"}}
|
||||
|
|
@ -532,24 +532,24 @@
|
|||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))
|
||||
spec (:body (app {:request-method :get, :uri "/swagger.json"}))]
|
||||
(is (= {:definitions {"reitit.swagger-test/Plus" {:properties {:x {:$ref "#/definitions/reitit.swagger-test~1X"},
|
||||
:y {:$ref "#/definitions/reitit.swagger-test~1Y"}},
|
||||
(is (= {:definitions {"reitit.swagger-test.Plus" {:properties {:x {:$ref "#/definitions/reitit.swagger-test.X"},
|
||||
:y {:$ref "#/definitions/reitit.swagger-test.Y"}},
|
||||
:required [:x :y],
|
||||
:type "object"},
|
||||
"reitit.swagger-test/X" {:format "int64",
|
||||
"reitit.swagger-test.X" {:format "int64",
|
||||
:type "integer"},
|
||||
"reitit.swagger-test/Y" {:format "int64",
|
||||
"reitit.swagger-test.Y" {:format "int64",
|
||||
:type "integer"},
|
||||
"reitit.swagger-test/Result" {:type "object",
|
||||
"reitit.swagger-test.Result" {:type "object",
|
||||
:properties {:result {:type "integer", :format "int64"}},
|
||||
:required [:result]}},
|
||||
:paths {"/post" {:post {:parameters [{:description "",
|
||||
:in "body",
|
||||
:name "body",
|
||||
:required true,
|
||||
:schema {:$ref "#/definitions/reitit.swagger-test~1Plus"}}]
|
||||
:schema {:$ref "#/definitions/reitit.swagger-test.Plus"}}]
|
||||
:responses {200 {:description ""
|
||||
:schema {:$ref "#/definitions/reitit.swagger-test~1Result"}}}}}
|
||||
:schema {:$ref "#/definitions/reitit.swagger-test.Result"}}}}}
|
||||
"/get" {:get {:parameters [{:in "query"
|
||||
:name :x
|
||||
:description ""
|
||||
|
|
@ -563,7 +563,7 @@
|
|||
:required true
|
||||
:format "int64"}]
|
||||
:responses {200 {:description ""
|
||||
:schema {:$ref "#/definitions/reitit.swagger-test~1Result"}}}}}}
|
||||
:schema {:$ref "#/definitions/reitit.swagger-test.Result"}}}}}}
|
||||
:swagger "2.0",
|
||||
:x-id #{:reitit.swagger/default}}
|
||||
spec))))
|
||||
|
|
|
|||
Loading…
Reference in a new issue