mirror of
https://github.com/metosin/reitit.git
synced 2026-02-25 10:32:24 +00:00
Merge branch 'master' into into-interceptor-for-multimethods
This commit is contained in:
commit
f80271fac1
138 changed files with 2827 additions and 2170 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
{;;:skip-comments true
|
{;;:skip-comments true
|
||||||
:lint-as {potemkin/def-derived-map clojure.core/defrecord}
|
:lint-as {potemkin/def-derived-map clojure.core/defrecord}
|
||||||
:linters {:if {:level :off}
|
:linters {:missing-else-branch {:level :off}
|
||||||
:unused-binding {:level :off}
|
:unused-binding {:level :off}
|
||||||
:unused-referred-var {:exclude {clojure.test [deftest testing is are]
|
:unused-referred-var {:exclude {clojure.test [deftest testing is are]
|
||||||
cljs.test [deftest testing is are]}}}}
|
cljs.test [deftest testing is are]}}}}
|
||||||
|
|
|
||||||
1
.clj-kondo/module_config.edn
Normal file
1
.clj-kondo/module_config.edn
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{:config-paths ["../../../.clj-kondo"]}
|
||||||
3
.lsp/config.edn
Normal file
3
.lsp/config.edn
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{:cljfmt {:indents {for-all [[:inner 0]]
|
||||||
|
are [[:inner 0]]}}
|
||||||
|
:clean {:ns-inner-blocks-indentation :same-line}}
|
||||||
41
CHANGELOG.md
41
CHANGELOG.md
|
|
@ -12,13 +12,50 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
|
||||||
|
|
||||||
[breakver]: https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md
|
[breakver]: https://github.com/ptaoussanis/encore/blob/master/BREAK-VERSIONING.md
|
||||||
|
|
||||||
## Unreleased
|
## 0.5.18 (2022-04-05)
|
||||||
|
|
||||||
**[compare](https://github.com/metosin/reitit/compare/0.5.15...master)**
|
* FIX [#334](https://github.com/metosin/reitit/pull/334) - Frontend: there is no way to catch the exception if coercion fails (via [#549](https://github.com/metosin/reitit/pull/549))
|
||||||
|
* Save three seq constructions [#537](https://github.com/metosin/reitit/pull/537)
|
||||||
|
* update jackson-databind for CVE-2020-36518 [#544](https://github.com/metosin/reitit/pull/544)
|
||||||
|
* Balance parenthesis in docs [#547](https://github.com/metosin/reitit/pull/547)
|
||||||
|
|
||||||
|
## 0.5.17 (2022-03-10)
|
||||||
|
|
||||||
|
* FIX match-by-path is broken if there are no non-conflicting wildcard routes [#538](https://github.com/metosin/reitit/issues/538)
|
||||||
|
|
||||||
|
|
||||||
|
## 0.5.16 (2022-02-15)
|
||||||
|
|
||||||
|
**[compare](https://github.com/metosin/reitit/compare/0.5.15...0.5.16)**
|
||||||
|
|
||||||
|
* Support for [Malli Lite Syntax](https://github.com/metosin/malli#lite) in coercion (enabled by default):
|
||||||
|
|
||||||
|
```clj
|
||||||
|
["/add/:id" {:post {:parameters {:path {:id int?}
|
||||||
|
:query {:a (l/optional int?)}
|
||||||
|
:body {:id int?
|
||||||
|
:data {:id (l/maybe int?)
|
||||||
|
:orders (l/map-of uuid? {:name string?})}}}
|
||||||
|
:responses {200 {:body {:total pos-int?}}
|
||||||
|
500 {:description "fail"}}}}]
|
||||||
|
```
|
||||||
|
|
||||||
* Improved Reitit-frontend function docstrings
|
* Improved Reitit-frontend function docstrings
|
||||||
* Allow multimethods to be interpreted as interceptors
|
* Allow multimethods to be interpreted as interceptors
|
||||||
|
|
||||||
|
* Updated deps:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
[metosin/ring-swagger-ui "4.3.0"] is available but we use "3.46.0"
|
||||||
|
[metosin/jsonista "0.3.5"] is available but we use "0.3.3"
|
||||||
|
[metosin/malli "0.8.2"] is available but we use "0.5.1"
|
||||||
|
[com.fasterxml.jackson.core/jackson-core "2.13.1"] is available but we use "2.12.4"
|
||||||
|
[com.fasterxml.jackson.core/jackson-databind "2.13.1"] is available but we use "2.12.4"
|
||||||
|
[fipp "0.6.25"] is available but we use "0.6.24"
|
||||||
|
[expound "0.9.0"] is available but we use "0.8.9"
|
||||||
|
[ring/ring-core "1.9.5"] is available but we use "1.9.4"
|
||||||
|
```
|
||||||
|
|
||||||
## 0.5.15 (2021-08-05)
|
## 0.5.15 (2021-08-05)
|
||||||
|
|
||||||
**[compare](https://github.com/metosin/reitit/compare/0.5.14...0.5.15)**
|
**[compare](https://github.com/metosin/reitit/compare/0.5.14...0.5.15)**
|
||||||
|
|
|
||||||
12
README.md
12
README.md
|
|
@ -52,7 +52,7 @@ There is [#reitit](https://clojurians.slack.com/messages/reitit/) in [Clojurians
|
||||||
All main modules bundled:
|
All main modules bundled:
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Optionally, the parts can be required separately.
|
Optionally, the parts can be required separately.
|
||||||
|
|
@ -153,9 +153,13 @@ All examples are in https://github.com/metosin/reitit/tree/master/examples
|
||||||
|
|
||||||
## External resources
|
## External resources
|
||||||
* Simple web application using Ring/Reitit and Integrant: https://github.com/PrestanceDesign/usermanager-reitit-integrant-example
|
* Simple web application using Ring/Reitit and Integrant: https://github.com/PrestanceDesign/usermanager-reitit-integrant-example
|
||||||
* A simple [ClojureScript](https://clojurescript.org/) frontend and Clojure backend using Reitit, [JUXT Clip](https://github.com/juxt/clip), [next.jdbc](https://github.com/seancorfield/next-jdbc) and other bits and bobs...
|
* A simple Clojure backend using Reitit to serve up a RESTful API: [startrek](https://github.com/dharrigan/startrek). Technologies include:
|
||||||
* [startrek](https://git.sr.ht/~dharrigan/startrek)
|
* [Donut System](https://github.com/donut-party/system)
|
||||||
* [startrek-ui](https://git.sr.ht/~dharrigan/startrek-ui)
|
* [next-jdbc](https://github.com/seancorfield/next-jdbc)
|
||||||
|
* [JUXT Clip](https://github.com/juxt/clip)
|
||||||
|
* [Flyway](https://github.com/flyway/flyway)
|
||||||
|
* [HoneySQL](https://github.com/seancorfield/honeysql)
|
||||||
|
* [Babashka](https://babashka.org)
|
||||||
* https://www.learnreitit.com/
|
* https://www.learnreitit.com/
|
||||||
* Lipas, liikuntapalvelut: https://github.com/lipas-liikuntapaikat/lipas
|
* Lipas, liikuntapalvelut: https://github.com/lipas-liikuntapaikat/lipas
|
||||||
* Implementation of the Todo-Backend API spec, using Clojure, Ring/Reitit and next-jdbc: https://github.com/PrestanceDesign/todo-backend-clojure-reitit
|
* Implementation of the Todo-Backend API spec, using Clojure, Ring/Reitit and next-jdbc: https://github.com/PrestanceDesign/todo-backend-clojure-reitit
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ There is [#reitit](https://clojurians.slack.com/messages/reitit/) in [Clojurians
|
||||||
All bundled:
|
All bundled:
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Optionally, the parts can be required separately.
|
Optionally, the parts can be required separately.
|
||||||
|
|
@ -139,7 +139,7 @@ Routing:
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
(app {:request-method :get, :uri "/api/admin/users"})
|
(app {:request-method :get, :uri "/api/admin/users"})
|
||||||
; {:status 200, :body "ok", :wrap (:api :admin}
|
; {:status 200, :body "ok", :wrap (:api :admin)}
|
||||||
|
|
||||||
(app {:request-method :put, :uri "/api/admin/users"})
|
(app {:request-method :put, :uri "/api/admin/users"})
|
||||||
; nil
|
; nil
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ Routers can be configured via options. The following options are available for t
|
||||||
| `:syntax` | Path-parameter syntax as keyword or set of keywords (default #{:bracket :colon})
|
| `:syntax` | Path-parameter syntax as keyword or set of keywords (default #{:bracket :colon})
|
||||||
| `:expand` | Function of `arg opts => data` to expand route arg to route data (default `reitit.core/expand`)
|
| `:expand` | Function of `arg opts => data` to expand route arg to route data (default `reitit.core/expand`)
|
||||||
| `:coerce` | Function of `route opts => route` to coerce resolved route, can throw or return `nil`
|
| `:coerce` | Function of `route opts => route` to coerce resolved route, can throw or return `nil`
|
||||||
|
| `:meta-merge-fn` | Function which follows the signature of `meta-merge.core/meta-merge`, useful for when you want to have more control over the meta merging
|
||||||
| `:compile` | Function of `route opts => result` to compile a route handler
|
| `:compile` | Function of `route opts => result` to compile a route handler
|
||||||
| `:validate` | Function of `routes opts => ()` to validate route (data) via side-effects
|
| `:validate` | Function of `routes opts => ()` to validate route (data) via side-effects
|
||||||
| `:conflicts` | Function of `{route #{route}} => ()` to handle conflicting routes
|
| `:conflicts` | Function of `{route #{route}} => ()` to handle conflicting routes
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ The default exception formatting uses `reitit.exception/exception`. It produces
|
||||||
## Pretty Errors
|
## Pretty Errors
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-dev "0.5.15"]
|
[metosin/reitit-dev "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
[Malli](https://github.com/metosin/malli) is data-driven Schema library for Clojure/Script.
|
[Malli](https://github.com/metosin/malli) is data-driven Schema library for Clojure/Script.
|
||||||
|
|
||||||
|
## Default Syntax
|
||||||
|
|
||||||
|
By default, [Vector Syntax](https://github.com/metosin/malli#vector-syntax) is used:
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
(require '[reitit.coercion.malli])
|
(require '[reitit.coercion.malli])
|
||||||
(require '[reitit.coercion :as coercion])
|
(require '[reitit.coercion :as coercion])
|
||||||
|
|
@ -44,6 +48,20 @@ Failing coercion:
|
||||||
; => ExceptionInfo Request coercion failed...
|
; => ExceptionInfo Request coercion failed...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Lite Syntax
|
||||||
|
|
||||||
|
Same using [Lite Syntax](https://github.com/metosin/malli#lite):
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(def router
|
||||||
|
(r/router
|
||||||
|
["/:company/users/:user-id" {:name ::user-view
|
||||||
|
:coercion reitit.coercion.malli/coercion
|
||||||
|
:parameters {:path {:company string?
|
||||||
|
:user-id int?}}}]
|
||||||
|
{:compile coercion/compile-request-coercers}))
|
||||||
|
```
|
||||||
|
|
||||||
## Configuring coercion
|
## Configuring coercion
|
||||||
|
|
||||||
Using `create` with options to create the coercion instead of `coercion`:
|
Using `create` with options to create the coercion instead of `coercion`:
|
||||||
|
|
@ -58,6 +76,8 @@ Using `create` with options to create the coercion instead of `coercion`:
|
||||||
:response {:default reitit.coercion.malli/default-transformer-provider}}
|
:response {:default reitit.coercion.malli/default-transformer-provider}}
|
||||||
;; set of keys to include in error messages
|
;; set of keys to include in error messages
|
||||||
:error-keys #{:type :coercion :in :schema :value :errors :humanized #_:transformed}
|
:error-keys #{:type :coercion :in :schema :value :errors :humanized #_:transformed}
|
||||||
|
;; support lite syntax?
|
||||||
|
:lite true
|
||||||
;; schema identity function (default: close all map schemas)
|
;; schema identity function (default: close all map schemas)
|
||||||
:compile mu/closed-schema
|
:compile mu/closed-schema
|
||||||
;; validate request & response
|
;; validate request & response
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,13 @@
|
||||||
./scripts/test.sh cljs
|
./scripts/test.sh cljs
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Formatting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
clojure-lsp format
|
||||||
|
clojure-lsp clean-ns
|
||||||
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
The documentation lives under `doc` and it is hosted on [cljdoc](https://cljdoc.org). See their
|
The documentation lives under `doc` and it is hosted on [cljdoc](https://cljdoc.org). See their
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Default Interceptors
|
# Default Interceptors
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-interceptors "0.5.15"]
|
[metosin/reitit-interceptors "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Just like the [ring default middleware](../ring/default_middleware.md), but for interceptors.
|
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
|
## Reitit-http
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-http "0.5.15"]
|
[metosin/reitit-http "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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.
|
[Pedestal](http://pedestal.io/) is a backend web framework for Clojure. `reitit-pedestal` provides an alternative routing engine for Pedestal.
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-pedestal "0.5.15"]
|
[metosin/reitit-pedestal "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
Why should one use reitit instead of the Pedestal [default routing](http://pedestal.io/reference/routing-quick-reference)?
|
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
|
```clj
|
||||||
; [io.pedestal/pedestal.service "0.5.5"]
|
; [io.pedestal/pedestal.service "0.5.5"]
|
||||||
; [io.pedestal/pedestal.jetty "0.5.5"]
|
; [io.pedestal/pedestal.jetty "0.5.5"]
|
||||||
; [metosin/reitit-pedestal "0.5.15"]
|
; [metosin/reitit-pedestal "0.5.18"]
|
||||||
; [metosin/reitit "0.5.15"]
|
; [metosin/reitit "0.5.18"]
|
||||||
|
|
||||||
(require '[io.pedestal.http :as server])
|
(require '[io.pedestal.http :as server])
|
||||||
(require '[reitit.pedestal :as pedestal])
|
(require '[reitit.pedestal :as pedestal])
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Sieppari
|
# Sieppari
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-sieppari "0.5.15"]
|
[metosin/reitit-sieppari "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
[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).
|
[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
|
### Printing Context Diffs
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-interceptors "0.5.15"]
|
[metosin/reitit-interceptors "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
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:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Default Middleware
|
# Default Middleware
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-middleware "0.5.15"]
|
[metosin/reitit-middleware "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Exception Handling with Ring
|
# Exception Handling with Ring
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-middleware "0.5.15"]
|
[metosin/reitit-middleware "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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).
|
Read more about the [Ring Concepts](https://github.com/ring-clojure/ring/wiki/Concepts).
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-ring "0.5.15"]
|
[metosin/reitit-ring "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
## `reitit.ring/ring-router`
|
## `reitit.ring/ring-router`
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# Swagger Support
|
# Swagger Support
|
||||||
|
|
||||||
```
|
```
|
||||||
[metosin/reitit-swagger "0.5.15"]
|
[metosin/reitit-swagger "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
@ -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
|
| :tags | optional set of string or keyword tags for an endpoint api docs
|
||||||
| :summary | optional short string summary of an endpoint
|
| :summary | optional short string summary of an endpoint
|
||||||
| :description | optional long description of an endpoint. Supports http://spec.commonmark.org/
|
| :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:
|
Coercion keys also contribute to the docs:
|
||||||
|
|
||||||
|
|
@ -44,7 +45,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.
|
[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.5.15"]
|
[metosin/reitit-swagger-ui "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
`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:
|
`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 ring-router (actually, in the underlying middleware-
|
||||||
### Printing Request Diffs
|
### Printing Request Diffs
|
||||||
|
|
||||||
```clj
|
```clj
|
||||||
[metosin/reitit-middleware "0.5.15"]
|
[metosin/reitit-middleware "0.5.18"]
|
||||||
```
|
```
|
||||||
|
|
||||||
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:
|
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"
|
:description "Reitit Buddy Auth App"
|
||||||
:dependencies [[org.clojure/clojure "1.10.1"]
|
:dependencies [[org.clojure/clojure "1.10.1"]
|
||||||
[ring/ring-jetty-adapter "1.8.1"]
|
[ring/ring-jetty-adapter "1.8.1"]
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
[buddy "2.0.0"]]
|
[buddy "2.0.0"]]
|
||||||
:repl-options {:init-ns example.server})
|
:repl-options {:init-ns example.server})
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@
|
||||||
[ring "1.7.1"]
|
[ring "1.7.1"]
|
||||||
[hiccup "1.0.5"]
|
[hiccup "1.0.5"]
|
||||||
[org.clojure/clojurescript "1.10.439"]
|
[org.clojure/clojurescript "1.10.439"]
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
[metosin/reitit-schema "0.5.15"]
|
[metosin/reitit-schema "0.5.18"]
|
||||||
[metosin/reitit-frontend "0.5.15"]
|
[metosin/reitit-frontend "0.5.18"]
|
||||||
;; Just for pretty printting the match
|
;; Just for pretty printting the match
|
||||||
[fipp "0.6.14"]]
|
[fipp "0.6.14"]]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@
|
||||||
[ring "1.7.1"]
|
[ring "1.7.1"]
|
||||||
[hiccup "1.0.5"]
|
[hiccup "1.0.5"]
|
||||||
[org.clojure/clojurescript "1.10.439"]
|
[org.clojure/clojurescript "1.10.439"]
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
[metosin/reitit-schema "0.5.15"]
|
[metosin/reitit-schema "0.5.18"]
|
||||||
[metosin/reitit-frontend "0.5.15"]
|
[metosin/reitit-frontend "0.5.18"]
|
||||||
;; Just for pretty printting the match
|
;; Just for pretty printting the match
|
||||||
[fipp "0.6.14"]]
|
[fipp "0.6.14"]]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@
|
||||||
[ring "1.7.1"]
|
[ring "1.7.1"]
|
||||||
[hiccup "1.0.5"]
|
[hiccup "1.0.5"]
|
||||||
[org.clojure/clojurescript "1.10.520"]
|
[org.clojure/clojurescript "1.10.520"]
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
[metosin/reitit-spec "0.5.15"]
|
[metosin/reitit-spec "0.5.18"]
|
||||||
[metosin/reitit-frontend "0.5.15"]
|
[metosin/reitit-frontend "0.5.18"]
|
||||||
;; Just for pretty printting the match
|
;; Just for pretty printting the match
|
||||||
[fipp "0.6.14"]]
|
[fipp "0.6.14"]]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@
|
||||||
[ring "1.7.1"]
|
[ring "1.7.1"]
|
||||||
[hiccup "1.0.5"]
|
[hiccup "1.0.5"]
|
||||||
[org.clojure/clojurescript "1.10.520"]
|
[org.clojure/clojurescript "1.10.520"]
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
[metosin/reitit-spec "0.5.15"]
|
[metosin/reitit-spec "0.5.18"]
|
||||||
[metosin/reitit-frontend "0.5.15"]
|
[metosin/reitit-frontend "0.5.18"]
|
||||||
;; Just for pretty printting the match
|
;; Just for pretty printting the match
|
||||||
[fipp "0.6.14"]]
|
[fipp "0.6.14"]]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
(defproject frontend-re-frame "0.1.0-SNAPSHOT"
|
(defproject frontend-re-frame "0.1.0-SNAPSHOT"
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[org.clojure/clojurescript "1.10.520"]
|
[org.clojure/clojurescript "1.10.520"]
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
[reagent "0.8.1"]
|
[reagent "0.8.1"]
|
||||||
[re-frame "0.10.6"]]
|
[re-frame "0.10.6"]]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,9 @@
|
||||||
[ring "1.8.1"]
|
[ring "1.8.1"]
|
||||||
[hiccup "1.0.5"]
|
[hiccup "1.0.5"]
|
||||||
[org.clojure/clojurescript "1.10.773"]
|
[org.clojure/clojurescript "1.10.773"]
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
[metosin/reitit-spec "0.5.15"]
|
[metosin/reitit-spec "0.5.18"]
|
||||||
[metosin/reitit-frontend "0.5.15"]
|
[metosin/reitit-frontend "0.5.18"]
|
||||||
;; Just for pretty printting the match
|
;; Just for pretty printting the match
|
||||||
[fipp "0.6.23"]]
|
[fipp "0.6.23"]]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,5 @@
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[aleph "0.4.7-alpha5"]
|
[aleph "0.4.7-alpha5"]
|
||||||
[metosin/reitit "0.5.15"]]
|
[metosin/reitit "0.5.18"]]
|
||||||
:repl-options {:init-ns example.server})
|
:repl-options {:init-ns example.server})
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,5 @@
|
||||||
[funcool/promesa "1.9.0"]
|
[funcool/promesa "1.9.0"]
|
||||||
[manifold "0.1.8"]
|
[manifold "0.1.8"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[metosin/reitit "0.5.15"]]
|
[metosin/reitit "0.5.18"]]
|
||||||
:repl-options {:init-ns example.server})
|
:repl-options {:init-ns example.server})
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@
|
||||||
:description "Reitit coercion with vanilla ring"
|
:description "Reitit coercion with vanilla ring"
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[metosin/reitit "0.5.15"]])
|
[metosin/reitit "0.5.18"]])
|
||||||
|
|
|
||||||
11
examples/pedestal-malli-swagger/.gitignore
vendored
Normal file
11
examples/pedestal-malli-swagger/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
/target
|
||||||
|
/classes
|
||||||
|
/checkouts
|
||||||
|
pom.xml
|
||||||
|
pom.xml.asc
|
||||||
|
*.jar
|
||||||
|
*.class
|
||||||
|
/.lein-*
|
||||||
|
/.nrepl-port
|
||||||
|
.hgignore
|
||||||
|
.hg/
|
||||||
9
examples/pedestal-malli-swagger/project.clj
Normal file
9
examples/pedestal-malli-swagger/project.clj
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
(defproject pedestal-malli-swagger-example "0.1.0-SNAPSHOT"
|
||||||
|
:description "Reitit-http with pedestal"
|
||||||
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
|
[io.pedestal/pedestal.service "0.5.5"]
|
||||||
|
[io.pedestal/pedestal.jetty "0.5.5"]
|
||||||
|
[metosin/reitit-malli "0.5.18"]
|
||||||
|
[metosin/reitit-pedestal "0.5.18"]
|
||||||
|
[metosin/reitit "0.5.18"]]
|
||||||
|
:repl-options {:init-ns server})
|
||||||
164
examples/pedestal-malli-swagger/src/server.clj
Normal file
164
examples/pedestal-malli-swagger/src/server.clj
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
(ns example.server
|
||||||
|
(:require [clojure.java.io :as io]
|
||||||
|
[io.pedestal.http.route]
|
||||||
|
[reitit.interceptor]
|
||||||
|
[reitit.dev.pretty :as pretty]
|
||||||
|
[reitit.coercion.malli]
|
||||||
|
[io.pedestal.http]
|
||||||
|
[reitit.ring]
|
||||||
|
[reitit.ring.malli]
|
||||||
|
[reitit.http]
|
||||||
|
[reitit.pedestal]
|
||||||
|
[reitit.swagger :as swagger]
|
||||||
|
[reitit.swagger-ui :as swagger-ui]
|
||||||
|
[reitit.http.coercion :as coercion]
|
||||||
|
[reitit.http.interceptors.parameters :as parameters]
|
||||||
|
[reitit.http.interceptors.muuntaja :as muuntaja]
|
||||||
|
[reitit.http.interceptors.multipart :as multipart]
|
||||||
|
[muuntaja.core]
|
||||||
|
[malli.util :as mu]))
|
||||||
|
|
||||||
|
(defn reitit-routes
|
||||||
|
[_config]
|
||||||
|
[["/swagger.json" {:get {:no-doc true
|
||||||
|
:swagger {:info {:title "my-api"
|
||||||
|
:description "with [malli](https://github.com/metosin/malli) and reitit-ring"}
|
||||||
|
:tags [{:name "files",
|
||||||
|
:description "file api"}
|
||||||
|
{:name "math",
|
||||||
|
:description "math api"}]}
|
||||||
|
:handler (swagger/create-swagger-handler)}}]
|
||||||
|
["/files" {:swagger {:tags ["files"]}}
|
||||||
|
["/upload"
|
||||||
|
{:post {:summary "upload a file"
|
||||||
|
:parameters {:multipart [:map [:file reitit.ring.malli/temp-file-part]]}
|
||||||
|
:responses {200 {:body [:map
|
||||||
|
[:name string?]
|
||||||
|
[:size int?]]}}
|
||||||
|
:handler (fn [{{{{:keys [filename
|
||||||
|
size]} :file}
|
||||||
|
:multipart}
|
||||||
|
:parameters}]
|
||||||
|
{:status 200
|
||||||
|
:body {:name filename
|
||||||
|
:size size}})}}]
|
||||||
|
["/download" {:get {:summary "downloads a file"
|
||||||
|
:swagger {:produces ["image/png"]}
|
||||||
|
:handler (fn [_]
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "image/png"}
|
||||||
|
:body (-> "reitit.png"
|
||||||
|
(io/resource)
|
||||||
|
(io/input-stream))})}}]]
|
||||||
|
["/math" {:swagger {:tags ["math"]}}
|
||||||
|
["/plus"
|
||||||
|
{:get {:summary "plus with malli query parameters"
|
||||||
|
:parameters {:query [:map
|
||||||
|
[:x
|
||||||
|
{:title "X parameter"
|
||||||
|
:description "Description for X parameter"
|
||||||
|
:json-schema/default 42}
|
||||||
|
int?]
|
||||||
|
[:y int?]]}
|
||||||
|
:responses {200 {:body [:map [:total int?]]}}
|
||||||
|
:handler (fn [{{{:keys [x
|
||||||
|
y]}
|
||||||
|
:query}
|
||||||
|
:parameters}]
|
||||||
|
{:status 200
|
||||||
|
:body {:total (+ x y)}})}
|
||||||
|
:post {:summary "plus with malli body parameters"
|
||||||
|
:parameters {:body [:map
|
||||||
|
[:x
|
||||||
|
{:title "X parameter"
|
||||||
|
:description "Description for X parameter"
|
||||||
|
:json-schema/default 42}
|
||||||
|
int?]
|
||||||
|
[:y int?]]}
|
||||||
|
:responses {200 {:body [:map [:total int?]]}}
|
||||||
|
:handler (fn [{{{:keys [x
|
||||||
|
y]}
|
||||||
|
:body}
|
||||||
|
:parameters}]
|
||||||
|
{:status 200
|
||||||
|
:body {:total (+ x y)}})}}]]])
|
||||||
|
|
||||||
|
(defn reitit-ring-routes
|
||||||
|
[_config]
|
||||||
|
[(swagger-ui/create-swagger-ui-handler
|
||||||
|
{:path "/"
|
||||||
|
:config {:validatorUrl nil
|
||||||
|
:operationsSorter "alpha"}})
|
||||||
|
(reitit.ring/create-resource-handler)
|
||||||
|
(reitit.ring/create-default-handler)])
|
||||||
|
|
||||||
|
|
||||||
|
(defn reitit-router-config
|
||||||
|
[_config]
|
||||||
|
{:exception pretty/exception
|
||||||
|
:data {:coercion (reitit.coercion.malli/create
|
||||||
|
{:error-keys #{:coercion
|
||||||
|
:in
|
||||||
|
:schema
|
||||||
|
:value
|
||||||
|
:errors
|
||||||
|
:humanized}
|
||||||
|
:compile mu/closed-schema
|
||||||
|
:strip-extra-keys true
|
||||||
|
:default-values true
|
||||||
|
:options nil})
|
||||||
|
:muuntaja muuntaja.core/instance
|
||||||
|
:interceptors [swagger/swagger-feature
|
||||||
|
(parameters/parameters-interceptor)
|
||||||
|
(muuntaja/format-negotiate-interceptor)
|
||||||
|
(muuntaja/format-response-interceptor)
|
||||||
|
(muuntaja/format-request-interceptor)
|
||||||
|
(coercion/coerce-response-interceptor)
|
||||||
|
(coercion/coerce-request-interceptor)
|
||||||
|
(multipart/multipart-interceptor)]}})
|
||||||
|
|
||||||
|
(def config
|
||||||
|
{:env :dev
|
||||||
|
:io.pedestal.http/routes []
|
||||||
|
:io.pedestal.http/type :jetty
|
||||||
|
:io.pedestal.http/port 3000
|
||||||
|
:io.pedestal.http/join? false
|
||||||
|
:io.pedestal.http/secure-headers {:content-security-policy-settings
|
||||||
|
{:default-src "'self'"
|
||||||
|
:style-src "'self' 'unsafe-inline'"
|
||||||
|
:script-src "'self' 'unsafe-inline'"}}
|
||||||
|
::reitit-routes reitit-routes
|
||||||
|
::reitit-ring-routes reitit-ring-routes
|
||||||
|
::reitit-router-config reitit-router-config})
|
||||||
|
|
||||||
|
(defn reitit-http-router
|
||||||
|
[{::keys [reitit-routes
|
||||||
|
reitit-ring-routes
|
||||||
|
reitit-router-config]
|
||||||
|
:as config}]
|
||||||
|
(reitit.pedestal/routing-interceptor
|
||||||
|
(reitit.http/router
|
||||||
|
(reitit-routes config)
|
||||||
|
(reitit-router-config config))
|
||||||
|
(->> config
|
||||||
|
reitit-ring-routes
|
||||||
|
(apply reitit.ring/routes))))
|
||||||
|
|
||||||
|
(defonce server (atom nil))
|
||||||
|
|
||||||
|
(defn start
|
||||||
|
[server
|
||||||
|
config]
|
||||||
|
(when @server
|
||||||
|
(io.pedestal.http/stop @server)
|
||||||
|
(println "server stopped"))
|
||||||
|
(-> config
|
||||||
|
io.pedestal.http/default-interceptors
|
||||||
|
(reitit.pedestal/replace-last-interceptor (reitit-http-router config))
|
||||||
|
io.pedestal.http/dev-interceptors
|
||||||
|
io.pedestal.http/create-server
|
||||||
|
io.pedestal.http/start
|
||||||
|
(->> (reset! server)))
|
||||||
|
(println "server running in port 3000"))
|
||||||
|
|
||||||
|
#_(start server config)
|
||||||
|
|
@ -3,6 +3,6 @@
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[io.pedestal/pedestal.service "0.5.5"]
|
[io.pedestal/pedestal.service "0.5.5"]
|
||||||
[io.pedestal/pedestal.jetty "0.5.5"]
|
[io.pedestal/pedestal.jetty "0.5.5"]
|
||||||
[metosin/reitit-pedestal "0.5.15"]
|
[metosin/reitit-pedestal "0.5.18"]
|
||||||
[metosin/reitit "0.5.15"]]
|
[metosin/reitit "0.5.18"]]
|
||||||
:repl-options {:init-ns example.server})
|
:repl-options {:init-ns example.server})
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,6 @@
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[io.pedestal/pedestal.service "0.5.5"]
|
[io.pedestal/pedestal.service "0.5.5"]
|
||||||
[io.pedestal/pedestal.jetty "0.5.5"]
|
[io.pedestal/pedestal.jetty "0.5.5"]
|
||||||
[metosin/reitit-pedestal "0.5.15"]
|
[metosin/reitit-pedestal "0.5.18"]
|
||||||
[metosin/reitit "0.5.15"]]
|
[metosin/reitit "0.5.18"]]
|
||||||
:repl-options {:init-ns example.server})
|
:repl-options {:init-ns example.server})
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@
|
||||||
:description "Reitit Ring App"
|
:description "Reitit Ring App"
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[metosin/reitit "0.5.15"]]
|
[metosin/reitit "0.5.18"]]
|
||||||
:repl-options {:init-ns example.server})
|
:repl-options {:init-ns example.server})
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
:description "Reitit Ring App with Integrant"
|
:description "Reitit Ring App with Integrant"
|
||||||
:dependencies [[org.clojure/clojure "1.10.1"]
|
:dependencies [[org.clojure/clojure "1.10.1"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[metosin/reitit "0.5.15"]
|
[metosin/reitit "0.5.18"]
|
||||||
[integrant "0.7.0"]]
|
[integrant "0.7.0"]]
|
||||||
:main example.server
|
:main example.server
|
||||||
:repl-options {:init-ns user}
|
:repl-options {:init-ns user}
|
||||||
|
|
|
||||||
11
examples/ring-malli-lite-swagger/.gitignore
vendored
Normal file
11
examples/ring-malli-lite-swagger/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
/target
|
||||||
|
/classes
|
||||||
|
/checkouts
|
||||||
|
pom.xml
|
||||||
|
pom.xml.asc
|
||||||
|
*.jar
|
||||||
|
*.class
|
||||||
|
/.lein-*
|
||||||
|
/.nrepl-port
|
||||||
|
.hgignore
|
||||||
|
.hg/
|
||||||
23
examples/ring-malli-lite-swagger/README.md
Normal file
23
examples/ring-malli-lite-swagger/README.md
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
# reitit-ring, malli, swagger
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```clj
|
||||||
|
> lein repl
|
||||||
|
(start)
|
||||||
|
```
|
||||||
|
|
||||||
|
To test the endpoints using [httpie](https://httpie.org/):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
http GET :3000/math/plus x==1 y==20
|
||||||
|
http POST :3000/math/plus x:=1 y:=20
|
||||||
|
|
||||||
|
http GET :3000/swagger.json
|
||||||
|
```
|
||||||
|
|
||||||
|
<img src="https://raw.githubusercontent.com/metosin/reitit/master/examples/ring-spec-swagger/swagger.png" />
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright © 2017-2019 Metosin Oy
|
||||||
8
examples/ring-malli-lite-swagger/project.clj
Normal file
8
examples/ring-malli-lite-swagger/project.clj
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
(defproject ring-example "0.1.0-SNAPSHOT"
|
||||||
|
:description "Reitit Ring App with Swagger"
|
||||||
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
|
[metosin/jsonista "0.2.6"]
|
||||||
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
|
[metosin/reitit "0.5.18"]]
|
||||||
|
:repl-options {:init-ns example.server}
|
||||||
|
:profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}})
|
||||||
BIN
examples/ring-malli-lite-swagger/resources/reitit.png
Normal file
BIN
examples/ring-malli-lite-swagger/resources/reitit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 494 KiB |
123
examples/ring-malli-lite-swagger/src/example/server.clj
Normal file
123
examples/ring-malli-lite-swagger/src/example/server.clj
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
(ns example.server
|
||||||
|
(:require [reitit.ring :as ring]
|
||||||
|
[reitit.coercion.malli]
|
||||||
|
[reitit.ring.malli]
|
||||||
|
[reitit.swagger :as swagger]
|
||||||
|
[reitit.swagger-ui :as swagger-ui]
|
||||||
|
[reitit.ring.coercion :as coercion]
|
||||||
|
[reitit.dev.pretty :as pretty]
|
||||||
|
[reitit.ring.middleware.muuntaja :as muuntaja]
|
||||||
|
[reitit.ring.middleware.exception :as exception]
|
||||||
|
[reitit.ring.middleware.multipart :as multipart]
|
||||||
|
[reitit.ring.middleware.parameters :as parameters]
|
||||||
|
; [reitit.ring.middleware.dev :as dev]
|
||||||
|
; [reitit.ring.spec :as spec]
|
||||||
|
; [spec-tools.spell :as spell]
|
||||||
|
[ring.adapter.jetty :as jetty]
|
||||||
|
[muuntaja.core :as m]
|
||||||
|
[clojure.java.io :as io]
|
||||||
|
[malli.util :as mu]))
|
||||||
|
|
||||||
|
(def app
|
||||||
|
(ring/ring-handler
|
||||||
|
(ring/router
|
||||||
|
[["/swagger.json"
|
||||||
|
{:get {:no-doc true
|
||||||
|
:swagger {:info {:title "my-api"
|
||||||
|
:description "with [malli](https://github.com/metosin/malli) and reitit-ring"}
|
||||||
|
:tags [{:name "files", :description "file api"}
|
||||||
|
{:name "math", :description "math api"}]}
|
||||||
|
:handler (swagger/create-swagger-handler)}}]
|
||||||
|
|
||||||
|
["/files"
|
||||||
|
{:swagger {:tags ["files"]}}
|
||||||
|
|
||||||
|
["/upload"
|
||||||
|
{:post {:summary "upload a file"
|
||||||
|
:parameters {:multipart {:file reitit.ring.malli/temp-file-part}}
|
||||||
|
:responses {200 {:body {:name :string, :size :int}}}
|
||||||
|
:handler (fn [{{{:keys [file]} :multipart} :parameters}]
|
||||||
|
{:status 200
|
||||||
|
:body {:name (:filename file)
|
||||||
|
:size (:size file)}})}}]
|
||||||
|
|
||||||
|
["/download"
|
||||||
|
{:get {:summary "downloads a file"
|
||||||
|
:swagger {:produces ["image/png"]}
|
||||||
|
:handler (fn [_]
|
||||||
|
{:status 200
|
||||||
|
:headers {"Content-Type" "image/png"}
|
||||||
|
:body (-> "reitit.png"
|
||||||
|
(io/resource)
|
||||||
|
(io/input-stream))})}}]]
|
||||||
|
|
||||||
|
["/math"
|
||||||
|
{:swagger {:tags ["math"]}}
|
||||||
|
|
||||||
|
["/plus"
|
||||||
|
{:get {:summary "plus with malli query parameters"
|
||||||
|
:parameters {:query {:x [:int {:title "X parameter"
|
||||||
|
:description "Description for X parameter"
|
||||||
|
:json-schema/default 42}]
|
||||||
|
:y :int}}
|
||||||
|
:responses {200 {:body {:total :int}}}
|
||||||
|
:handler (fn [{{{:keys [x y]} :query} :parameters}]
|
||||||
|
{:status 200
|
||||||
|
:body {:total (+ x y)}})}
|
||||||
|
:post {:summary "plus with malli body parameters"
|
||||||
|
:parameters {:body {:x [:int {:title "X parameter"
|
||||||
|
:description "Description for X parameter"
|
||||||
|
:json-schema/default 42}]
|
||||||
|
:y :int}}
|
||||||
|
:responses {200 {:body {:total :int}}}
|
||||||
|
:handler (fn [{{{:keys [x y]} :body} :parameters}]
|
||||||
|
{:status 200
|
||||||
|
:body {:total (+ x y)}})}}]]]
|
||||||
|
|
||||||
|
{;;:reitit.middleware/transform dev/print-request-diffs ;; pretty diffs
|
||||||
|
;;:validate spec/validate ;; enable spec validation for route data
|
||||||
|
;;:reitit.spec/wrap spell/closed ;; strict top-level validation
|
||||||
|
:exception pretty/exception
|
||||||
|
:data {:coercion (reitit.coercion.malli/create
|
||||||
|
{;; set of keys to include in error messages
|
||||||
|
:error-keys #{#_:type :coercion :in :schema :value :errors :humanized #_:transformed}
|
||||||
|
;; schema identity function (default: close all map schemas)
|
||||||
|
:compile mu/closed-schema
|
||||||
|
;; strip-extra-keys (effects only predefined transformers)
|
||||||
|
:strip-extra-keys true
|
||||||
|
;; add/set default values
|
||||||
|
:default-values true
|
||||||
|
;; malli options
|
||||||
|
:options nil})
|
||||||
|
:muuntaja m/instance
|
||||||
|
:middleware [;; swagger feature
|
||||||
|
swagger/swagger-feature
|
||||||
|
;; query-params & form-params
|
||||||
|
parameters/parameters-middleware
|
||||||
|
;; content-negotiation
|
||||||
|
muuntaja/format-negotiate-middleware
|
||||||
|
;; encoding response body
|
||||||
|
muuntaja/format-response-middleware
|
||||||
|
;; exception handling
|
||||||
|
exception/exception-middleware
|
||||||
|
;; decoding request body
|
||||||
|
muuntaja/format-request-middleware
|
||||||
|
;; coercing response bodys
|
||||||
|
coercion/coerce-response-middleware
|
||||||
|
;; coercing request parameters
|
||||||
|
coercion/coerce-request-middleware
|
||||||
|
;; multipart
|
||||||
|
multipart/multipart-middleware]}})
|
||||||
|
(ring/routes
|
||||||
|
(swagger-ui/create-swagger-ui-handler
|
||||||
|
{:path "/"
|
||||||
|
:config {:validatorUrl nil
|
||||||
|
:operationsSorter "alpha"}})
|
||||||
|
(ring/create-default-handler))))
|
||||||
|
|
||||||
|
(defn start []
|
||||||
|
(jetty/run-jetty #'app {:port 3000, :join? false})
|
||||||
|
(println "server running in port 3000"))
|
||||||
|
|
||||||
|
(comment
|
||||||
|
(start))
|
||||||
BIN
examples/ring-malli-lite-swagger/swagger.png
Normal file
BIN
examples/ring-malli-lite-swagger/swagger.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 228 KiB |
|
|
@ -0,0 +1,38 @@
|
||||||
|
(ns example.server-test
|
||||||
|
(:require [clojure.test :refer [deftest testing is]]
|
||||||
|
[example.server :refer [app]]
|
||||||
|
[ring.mock.request :refer [request json-body]]))
|
||||||
|
|
||||||
|
(deftest example-server
|
||||||
|
|
||||||
|
(testing "GET"
|
||||||
|
(is (= (-> (request :get "/math/plus?x=20&y=3")
|
||||||
|
app :body slurp)
|
||||||
|
(-> {:request-method :get :uri "/math/plus" :query-string "x=20&y=3"}
|
||||||
|
app :body slurp)
|
||||||
|
(-> {:request-method :get :uri "/math/plus" :query-params {:x 20 :y 3}}
|
||||||
|
app :body slurp)
|
||||||
|
"{\"total\":23}")))
|
||||||
|
|
||||||
|
(testing "POST"
|
||||||
|
(is (= (-> (request :post "/math/plus") (json-body {:x 40 :y 2})
|
||||||
|
app :body slurp)
|
||||||
|
(-> {:request-method :post :uri "/math/plus" :body-params {:x 40 :y 2}}
|
||||||
|
app :body slurp)
|
||||||
|
"{\"total\":42}")))
|
||||||
|
|
||||||
|
(testing "Download"
|
||||||
|
(is (= (-> {:request-method :get :uri "/files/download"}
|
||||||
|
app :body (#(slurp % :encoding "ascii")) count) ;; binary
|
||||||
|
(.length (clojure.java.io/file "resources/reitit.png"))
|
||||||
|
506325)))
|
||||||
|
|
||||||
|
(testing "Upload"
|
||||||
|
(let [file (clojure.java.io/file "resources/reitit.png")
|
||||||
|
multipart-temp-file-part {:tempfile file
|
||||||
|
:size (.length file)
|
||||||
|
:filename (.getName file)
|
||||||
|
:content-type "image/png;"}]
|
||||||
|
(is (= (-> {:request-method :post :uri "/files/upload" :multipart-params {:file multipart-temp-file-part}}
|
||||||
|
app :body slurp)
|
||||||
|
"{\"name\":\"reitit.png\",\"size\":506325}")))))
|
||||||
|
|
@ -3,6 +3,6 @@
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[metosin/jsonista "0.2.6"]
|
[metosin/jsonista "0.2.6"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[metosin/reitit "0.5.15"]]
|
[metosin/reitit "0.5.18"]]
|
||||||
:repl-options {:init-ns example.server}
|
:repl-options {:init-ns example.server}
|
||||||
:profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}})
|
:profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}})
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,6 @@
|
||||||
:description "Reitit Ring App with Swagger"
|
:description "Reitit Ring App with Swagger"
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[metosin/reitit "0.5.15"]]
|
[metosin/reitit "0.5.18"]]
|
||||||
:repl-options {:init-ns example.server}
|
:repl-options {:init-ns example.server}
|
||||||
:profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}})
|
:profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]}})
|
||||||
|
|
|
||||||
|
|
@ -2,5 +2,5 @@
|
||||||
:description "Reitit Ring App with Swagger"
|
:description "Reitit Ring App with Swagger"
|
||||||
:dependencies [[org.clojure/clojure "1.10.0"]
|
:dependencies [[org.clojure/clojure "1.10.0"]
|
||||||
[ring/ring-jetty-adapter "1.7.1"]
|
[ring/ring-jetty-adapter "1.7.1"]
|
||||||
[metosin/reitit "0.5.15"]]
|
[metosin/reitit "0.5.18"]]
|
||||||
:repl-options {:init-ns example.server})
|
:repl-options {:init-ns example.server})
|
||||||
|
|
|
||||||
1
modules/reitit-core/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-core/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-core "0.5.15"
|
(defproject metosin/reitit-core "0.5.18"
|
||||||
:description "Snappy data-driven router for Clojure(Script)"
|
:description "Snappy data-driven router for Clojure(Script)"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -39,38 +39,47 @@
|
||||||
:body (->ParameterCoercion :body-params :body false false)
|
:body (->ParameterCoercion :body-params :body false false)
|
||||||
:form (->ParameterCoercion :form-params :string true true)
|
:form (->ParameterCoercion :form-params :string true true)
|
||||||
:header (->ParameterCoercion :headers :string true true)
|
:header (->ParameterCoercion :headers :string true true)
|
||||||
:path (->ParameterCoercion :path-params :string true true)})
|
:path (->ParameterCoercion :path-params :string true true)
|
||||||
|
:fragment (->ParameterCoercion :fragment-params :string true true)})
|
||||||
|
|
||||||
(defn ^:no-doc request-coercion-failed! [result coercion value in request]
|
(defn ^:no-doc request-coercion-failed! [result coercion value in request serialize-failed-result]
|
||||||
(throw
|
(throw
|
||||||
(ex-info
|
(ex-info
|
||||||
|
(if serialize-failed-result
|
||||||
(str "Request coercion failed: " (pr-str result))
|
(str "Request coercion failed: " (pr-str result))
|
||||||
(merge
|
"Request coercion failed")
|
||||||
(into {} result)
|
(-> {}
|
||||||
{:type ::request-coercion
|
transient
|
||||||
:coercion coercion
|
(as-> $ (reduce conj! $ result))
|
||||||
:value value
|
(assoc! :type ::request-coercion)
|
||||||
:in [:request in]
|
(assoc! :coercion coercion)
|
||||||
:request request}))))
|
(assoc! :value value)
|
||||||
|
(assoc! :in [:request in])
|
||||||
|
(assoc! :request request)
|
||||||
|
persistent!))))
|
||||||
|
|
||||||
(defn ^:no-doc response-coercion-failed! [result coercion value request response]
|
(defn ^:no-doc response-coercion-failed! [result coercion value request response serialize-failed-result]
|
||||||
(throw
|
(throw
|
||||||
(ex-info
|
(ex-info
|
||||||
|
(if serialize-failed-result
|
||||||
(str "Response coercion failed: " (pr-str result))
|
(str "Response coercion failed: " (pr-str result))
|
||||||
(merge
|
"Response coercion failed")
|
||||||
(into {} result)
|
(-> {}
|
||||||
{:type ::response-coercion
|
transient
|
||||||
:coercion coercion
|
(as-> $ (reduce conj! $ result))
|
||||||
:value value
|
(assoc! :type ::response-coercion)
|
||||||
:in [:response :body]
|
(assoc! :coercion coercion)
|
||||||
:request request
|
(assoc! :value value)
|
||||||
:response response}))))
|
(assoc! :in [:response :body])
|
||||||
|
(assoc! :request request)
|
||||||
|
(assoc! :response response)
|
||||||
|
persistent!))))
|
||||||
|
|
||||||
(defn extract-request-format-default [request]
|
(defn extract-request-format-default [request]
|
||||||
(-> request :muuntaja/request :format))
|
(-> request :muuntaja/request :format))
|
||||||
|
|
||||||
;; TODO: support faster key walking, walk/keywordize-keys is quite slow...
|
;; TODO: support faster key walking, walk/keywordize-keys is quite slow...
|
||||||
(defn request-coercer [coercion type model {::keys [extract-request-format parameter-coercion]
|
(defn request-coercer [coercion type model {::keys [extract-request-format parameter-coercion serialize-failed-result]
|
||||||
:or {extract-request-format extract-request-format-default
|
:or {extract-request-format extract-request-format-default
|
||||||
parameter-coercion default-parameter-coercion}}]
|
parameter-coercion default-parameter-coercion}}]
|
||||||
(if coercion
|
(if coercion
|
||||||
|
|
@ -83,13 +92,13 @@
|
||||||
format (extract-request-format request)
|
format (extract-request-format request)
|
||||||
result (coercer value format)]
|
result (coercer value format)]
|
||||||
(if (error? result)
|
(if (error? result)
|
||||||
(request-coercion-failed! result coercion value in request)
|
(request-coercion-failed! result coercion value in request serialize-failed-result)
|
||||||
result))))))))
|
result))))))))
|
||||||
|
|
||||||
(defn extract-response-format-default [request _]
|
(defn extract-response-format-default [request _]
|
||||||
(-> request :muuntaja/response :format))
|
(-> request :muuntaja/response :format))
|
||||||
|
|
||||||
(defn response-coercer [coercion body {:keys [extract-response-format]
|
(defn response-coercer [coercion body {:keys [extract-response-format serialize-failed-result]
|
||||||
:or {extract-response-format extract-response-format-default}}]
|
:or {extract-response-format extract-response-format-default}}]
|
||||||
(if coercion
|
(if coercion
|
||||||
(if-let [coercer (-response-coercer coercion body)]
|
(if-let [coercer (-response-coercer coercion body)]
|
||||||
|
|
@ -98,7 +107,7 @@
|
||||||
value (:body response)
|
value (:body response)
|
||||||
result (coercer value format)]
|
result (coercer value format)]
|
||||||
(if (error? result)
|
(if (error? result)
|
||||||
(response-coercion-failed! result coercion value request response)
|
(response-coercion-failed! result coercion value request response serialize-failed-result)
|
||||||
result))))))
|
result))))))
|
||||||
|
|
||||||
(defn encode-error [data]
|
(defn encode-error [data]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
(ns reitit.core
|
(ns reitit.core
|
||||||
(:require [reitit.impl :as impl]
|
(:require [reitit.exception :as exception]
|
||||||
[reitit.exception :as exception]
|
[reitit.impl :as impl]
|
||||||
[reitit.trie :as trie]))
|
[reitit.trie :as trie]))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
|
@ -103,16 +103,11 @@
|
||||||
^{:type ::router}
|
^{:type ::router}
|
||||||
(reify
|
(reify
|
||||||
Router
|
Router
|
||||||
(router-name [_]
|
(router-name [_] :linear-router)
|
||||||
:linear-router)
|
(routes [_] routes)
|
||||||
(routes [_]
|
(compiled-routes [_] compiled-routes)
|
||||||
routes)
|
(options [_] opts)
|
||||||
(compiled-routes [_]
|
(route-names [_] names)
|
||||||
compiled-routes)
|
|
||||||
(options [_]
|
|
||||||
opts)
|
|
||||||
(route-names [_]
|
|
||||||
names)
|
|
||||||
(match-by-path [_ path]
|
(match-by-path [_ path]
|
||||||
(if-let [match (match-by-path path)]
|
(if-let [match (match-by-path path)]
|
||||||
(-> (:data match)
|
(-> (:data match)
|
||||||
|
|
@ -150,16 +145,11 @@
|
||||||
routes (impl/uncompile-routes compiled-routes)]
|
routes (impl/uncompile-routes compiled-routes)]
|
||||||
^{:type ::router}
|
^{:type ::router}
|
||||||
(reify Router
|
(reify Router
|
||||||
(router-name [_]
|
(router-name [_] :lookup-router)
|
||||||
:lookup-router)
|
(routes [_] routes)
|
||||||
(routes [_]
|
(compiled-routes [_] compiled-routes)
|
||||||
routes)
|
(options [_] opts)
|
||||||
(compiled-routes [_]
|
(route-names [_] names)
|
||||||
compiled-routes)
|
|
||||||
(options [_]
|
|
||||||
opts)
|
|
||||||
(route-names [_]
|
|
||||||
names)
|
|
||||||
(match-by-path [_ path]
|
(match-by-path [_ path]
|
||||||
(impl/fast-get data path))
|
(impl/fast-get data path))
|
||||||
(match-by-name [_ name]
|
(match-by-name [_ name]
|
||||||
|
|
@ -193,24 +183,19 @@
|
||||||
[nil {}]
|
[nil {}]
|
||||||
compiled-routes)
|
compiled-routes)
|
||||||
matcher (trie/compile pl compiler)
|
matcher (trie/compile pl compiler)
|
||||||
match-by-path (trie/path-matcher matcher compiler)
|
match-by-path (if matcher (trie/path-matcher matcher compiler))
|
||||||
lookup (impl/fast-map nl)
|
lookup (impl/fast-map nl)
|
||||||
routes (impl/uncompile-routes compiled-routes)]
|
routes (impl/uncompile-routes compiled-routes)]
|
||||||
^{:type ::router}
|
^{:type ::router}
|
||||||
(reify
|
(reify
|
||||||
Router
|
Router
|
||||||
(router-name [_]
|
(router-name [_] :trie-router)
|
||||||
:trie-router)
|
(routes [_] routes)
|
||||||
(routes [_]
|
(compiled-routes [_] compiled-routes)
|
||||||
routes)
|
(options [_] opts)
|
||||||
(compiled-routes [_]
|
(route-names [_] names)
|
||||||
compiled-routes)
|
|
||||||
(options [_]
|
|
||||||
opts)
|
|
||||||
(route-names [_]
|
|
||||||
names)
|
|
||||||
(match-by-path [_ path]
|
(match-by-path [_ path]
|
||||||
(if-let [match (match-by-path path)]
|
(if-let [match (and match-by-path (match-by-path path))]
|
||||||
(-> (:data match)
|
(-> (:data match)
|
||||||
(assoc :path-params (:params match))
|
(assoc :path-params (:params match))
|
||||||
(assoc :path path))))
|
(assoc :path path))))
|
||||||
|
|
@ -238,25 +223,17 @@
|
||||||
routes (impl/uncompile-routes compiled-routes)]
|
routes (impl/uncompile-routes compiled-routes)]
|
||||||
^{:type ::router}
|
^{:type ::router}
|
||||||
(reify Router
|
(reify Router
|
||||||
(router-name [_]
|
(router-name [_] :single-static-path-router)
|
||||||
:single-static-path-router)
|
(routes [_] routes)
|
||||||
(routes [_]
|
(compiled-routes [_] compiled-routes)
|
||||||
routes)
|
(options [_] opts)
|
||||||
(compiled-routes [_]
|
(route-names [_] names)
|
||||||
compiled-routes)
|
|
||||||
(options [_]
|
|
||||||
opts)
|
|
||||||
(route-names [_]
|
|
||||||
names)
|
|
||||||
(match-by-path [_ path]
|
(match-by-path [_ path]
|
||||||
(if (#?(:clj .equals :cljs =) p path)
|
(if (#?(:clj .equals :cljs =) p path) match))
|
||||||
match))
|
|
||||||
(match-by-name [_ name]
|
(match-by-name [_ name]
|
||||||
(if (= n name)
|
(if (= n name) match))
|
||||||
match))
|
|
||||||
(match-by-name [_ name path-params]
|
(match-by-name [_ name path-params]
|
||||||
(if (= n name)
|
(if (= n name) (impl/fast-assoc match :path-params (impl/path-params path-params))))))))
|
||||||
(impl/fast-assoc match :path-params (impl/path-params path-params))))))))
|
|
||||||
|
|
||||||
(defn mixed-router
|
(defn mixed-router
|
||||||
"Creates two routers: [[lookup-router]] or [[single-static-path-router]] for
|
"Creates two routers: [[lookup-router]] or [[single-static-path-router]] for
|
||||||
|
|
@ -274,16 +251,11 @@
|
||||||
routes (impl/uncompile-routes compiled-routes)]
|
routes (impl/uncompile-routes compiled-routes)]
|
||||||
^{:type ::router}
|
^{:type ::router}
|
||||||
(reify Router
|
(reify Router
|
||||||
(router-name [_]
|
(router-name [_] :mixed-router)
|
||||||
:mixed-router)
|
(routes [_] routes)
|
||||||
(routes [_]
|
(compiled-routes [_] compiled-routes)
|
||||||
routes)
|
(options [_] opts)
|
||||||
(compiled-routes [_]
|
(route-names [_] names)
|
||||||
compiled-routes)
|
|
||||||
(options [_]
|
|
||||||
opts)
|
|
||||||
(route-names [_]
|
|
||||||
names)
|
|
||||||
(match-by-path [_ path]
|
(match-by-path [_ path]
|
||||||
(or (match-by-path static-router path)
|
(or (match-by-path static-router path)
|
||||||
(match-by-path wildcard-router path)))
|
(match-by-path wildcard-router path)))
|
||||||
|
|
@ -310,16 +282,11 @@
|
||||||
routes (impl/uncompile-routes compiled-routes)]
|
routes (impl/uncompile-routes compiled-routes)]
|
||||||
^{:type ::router}
|
^{:type ::router}
|
||||||
(reify Router
|
(reify Router
|
||||||
(router-name [_]
|
(router-name [_] :quarantine-router)
|
||||||
:quarantine-router)
|
(routes [_] routes)
|
||||||
(routes [_]
|
(compiled-routes [_] compiled-routes)
|
||||||
routes)
|
(options [_] opts)
|
||||||
(compiled-routes [_]
|
(route-names [_] names)
|
||||||
compiled-routes)
|
|
||||||
(options [_]
|
|
||||||
opts)
|
|
||||||
(route-names [_]
|
|
||||||
names)
|
|
||||||
(match-by-path [_ path]
|
(match-by-path [_ path]
|
||||||
(or (match-by-path mixed-router path)
|
(or (match-by-path mixed-router path)
|
||||||
(match-by-path linear-router path)))
|
(match-by-path linear-router path)))
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
(ns ^:no-doc reitit.impl
|
(ns ^:no-doc reitit.impl
|
||||||
#?(:cljs (:require-macros [reitit.impl]))
|
#?(:cljs (:require-macros [reitit.impl]))
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.set :as set]
|
||||||
[clojure.set :as set]
|
[clojure.string :as str]
|
||||||
[meta-merge.core :as mm]
|
[meta-merge.core :as mm]
|
||||||
[reitit.trie :as trie]
|
[reitit.exception :as ex]
|
||||||
[reitit.exception :as ex])
|
[reitit.trie :as trie])
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(:import (java.util HashMap Map)
|
(:import (java.net URLEncoder URLDecoder)
|
||||||
(java.net URLEncoder URLDecoder))))
|
(java.util HashMap Map))))
|
||||||
|
|
||||||
(defn parse [path opts]
|
(defn parse [path opts]
|
||||||
(let [path #?(:clj (.intern ^String (trie/normalize path opts)) :cljs (trie/normalize path opts))
|
(let [path #?(:clj (.intern ^String (trie/normalize path opts)) :cljs (trie/normalize path opts))
|
||||||
|
|
@ -60,17 +60,17 @@
|
||||||
(defn map-data [f routes]
|
(defn map-data [f routes]
|
||||||
(mapv (fn [[p ds]] [p (f p ds)]) routes))
|
(mapv (fn [[p ds]] [p (f p ds)]) routes))
|
||||||
|
|
||||||
(defn merge-data [p x]
|
(defn merge-data [{:keys [meta-merge-fn] :as g} p x]
|
||||||
(reduce
|
(reduce
|
||||||
(fn [acc [k v]]
|
(fn [acc [k v]]
|
||||||
(try
|
(try
|
||||||
(mm/meta-merge acc {k v})
|
((or meta-merge-fn mm/meta-merge) acc {k v})
|
||||||
(catch #?(:clj Exception, :cljs js/Error) e
|
(catch #?(:clj Exception, :cljs js/Error) e
|
||||||
(ex/fail! ::merge-data {:path p, :left acc, :right {k v}, :exception e}))))
|
(ex/fail! ::merge-data {:path p, :left acc, :right {k v}, :exception e}))))
|
||||||
{} x))
|
{} x))
|
||||||
|
|
||||||
(defn resolve-routes [raw-routes {:keys [coerce] :as opts}]
|
(defn resolve-routes [raw-routes {:keys [coerce] :as opts}]
|
||||||
(cond->> (->> (walk raw-routes opts) (map-data merge-data))
|
(cond->> (->> (walk raw-routes opts) (map-data #(merge-data opts %1 %2)))
|
||||||
coerce (into [] (keep #(coerce % opts)))))
|
coerce (into [] (keep #(coerce % opts)))))
|
||||||
|
|
||||||
(defn path-conflicting-routes [routes opts]
|
(defn path-conflicting-routes [routes opts]
|
||||||
|
|
@ -249,6 +249,10 @@
|
||||||
(->> params
|
(->> params
|
||||||
(map (fn [[k v]]
|
(map (fn [[k v]]
|
||||||
(if (or (sequential? v) (set? v))
|
(if (or (sequential? v) (set? v))
|
||||||
|
(if (seq v)
|
||||||
(str/join "&" (map query-parameter (repeat k) v))
|
(str/join "&" (map query-parameter (repeat k) v))
|
||||||
|
;; Empty seq results in single & character in the query string.
|
||||||
|
;; Handle as empty string to behave similarly as when the value is nil.
|
||||||
|
(query-parameter k ""))
|
||||||
(query-parameter k v))))
|
(query-parameter k v))))
|
||||||
(str/join "&")))
|
(str/join "&")))
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
(ns reitit.interceptor
|
(ns reitit.interceptor
|
||||||
(:require [meta-merge.core :refer [meta-merge]]
|
(:require [clojure.pprint :as pprint]
|
||||||
[clojure.pprint :as pprint]
|
[meta-merge.core :refer [meta-merge]]
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[reitit.impl :as impl]
|
[reitit.exception :as exception]
|
||||||
[reitit.exception :as exception]))
|
[reitit.impl :as impl]))
|
||||||
|
|
||||||
(defprotocol IntoInterceptor
|
(defprotocol IntoInterceptor
|
||||||
(into-interceptor [this data opts]))
|
(into-interceptor [this data opts]))
|
||||||
|
|
@ -160,8 +160,8 @@
|
||||||
:handler get-user}]])"
|
:handler get-user}]])"
|
||||||
([data]
|
([data]
|
||||||
(router data nil))
|
(router data nil))
|
||||||
([data opts]
|
([data {:keys [meta-merge-fn] :as opts}]
|
||||||
(let [opts (meta-merge {:compile compile-result} opts)]
|
(let [opts ((or meta-merge-fn meta-merge) {:compile compile-result} opts)]
|
||||||
(r/router data opts))))
|
(r/router data opts))))
|
||||||
|
|
||||||
(defn interceptor-handler [router]
|
(defn interceptor-handler [router]
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
(ns reitit.middleware
|
(ns reitit.middleware
|
||||||
(:require [meta-merge.core :refer [meta-merge]]
|
(:require [clojure.pprint :as pprint]
|
||||||
[clojure.pprint :as pprint]
|
[meta-merge.core :refer [meta-merge]]
|
||||||
[reitit.core :as r]
|
[reitit.core :as r]
|
||||||
[reitit.impl :as impl]
|
[reitit.exception :as exception]
|
||||||
[reitit.exception :as exception]))
|
[reitit.impl :as impl]))
|
||||||
|
|
||||||
(defprotocol IntoMiddleware
|
(defprotocol IntoMiddleware
|
||||||
(into-middleware [this data opts]))
|
(into-middleware [this data opts]))
|
||||||
|
|
@ -138,8 +138,8 @@
|
||||||
:handler get-user}]])"
|
:handler get-user}]])"
|
||||||
([data]
|
([data]
|
||||||
(router data nil))
|
(router data nil))
|
||||||
([data opts]
|
([data {:keys [meta-merge-fn] :as opts}]
|
||||||
(let [opts (meta-merge {:compile compile-result} opts)]
|
(let [opts ((or meta-merge-fn meta-merge) {:compile compile-result} opts)]
|
||||||
(r/router data opts))))
|
(r/router data opts))))
|
||||||
|
|
||||||
(defn middleware-handler [router]
|
(defn middleware-handler [router]
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
(ns reitit.spec
|
(ns reitit.spec
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[clojure.spec.gen.alpha :as gen]
|
[clojure.spec.gen.alpha :as gen]
|
||||||
[reitit.exception :as exception]
|
[reitit.core :as r]
|
||||||
[reitit.core :as r]))
|
[reitit.exception :as exception]))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; routes
|
;; routes
|
||||||
|
|
@ -119,11 +119,12 @@
|
||||||
(defrecord Problem [path scope data spec problems])
|
(defrecord Problem [path scope data spec problems])
|
||||||
|
|
||||||
(defn validate-route-data [routes wrap spec]
|
(defn validate-route-data [routes wrap spec]
|
||||||
(let [spec (wrap spec)]
|
(let [spec (wrap spec)
|
||||||
(some->> (for [[p d _] routes]
|
spec-explain (fn [[p d _]]
|
||||||
(when-let [problems (and spec (s/explain-data spec d))]
|
(when-let [problems (and spec (s/explain-data spec d))]
|
||||||
(->Problem p nil d spec problems)))
|
(->Problem p nil d spec problems)))
|
||||||
(keep identity) (seq) (vec))))
|
errors (into [] (keep spec-explain) routes)]
|
||||||
|
(when (pos? (count errors)) errors)))
|
||||||
|
|
||||||
(defn validate [routes {:keys [spec] ::keys [wrap] :or {spec ::default-data, wrap identity}}]
|
(defn validate [routes {:keys [spec] ::keys [wrap] :or {spec ::default-data, wrap identity}}]
|
||||||
(when-let [problems (validate-route-data routes wrap spec)]
|
(when-let [problems (validate-route-data routes wrap spec)]
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
(:refer-clojure :exclude [compile])
|
(:refer-clojure :exclude [compile])
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
[reitit.exception :as ex])
|
[reitit.exception :as ex])
|
||||||
#?(:clj (:import [reitit Trie Trie$Match Trie$Matcher]
|
#?(:clj (:import (java.net URLDecoder)
|
||||||
(java.net URLDecoder))))
|
[reitit Trie Trie$Match Trie$Matcher])))
|
||||||
|
|
||||||
(defn ^:no-doc into-set [x]
|
(defn ^:no-doc into-set [x]
|
||||||
(cond
|
(cond
|
||||||
|
|
@ -364,8 +364,7 @@
|
||||||
(into (for [[p c] catch-all] (catch-all-matcher compiler (:value p) params (:data c)))))]
|
(into (for [[p c] catch-all] (catch-all-matcher compiler (:value p) params (:data c)))))]
|
||||||
(cond
|
(cond
|
||||||
(> (count matchers) 1) (linear-matcher compiler matchers false)
|
(> (count matchers) 1) (linear-matcher compiler matchers false)
|
||||||
(= (count matchers) 1) (first matchers)
|
(= (count matchers) 1) (first matchers)))))
|
||||||
:else (data-matcher compiler {} nil)))))
|
|
||||||
|
|
||||||
(defn pretty
|
(defn pretty
|
||||||
"Returns a simplified EDN structure of a compiled trie for printing purposes."
|
"Returns a simplified EDN structure of a compiled trie for printing purposes."
|
||||||
|
|
|
||||||
1
modules/reitit-dev/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-dev/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-dev "0.5.15"
|
(defproject metosin/reitit-dev "0.5.18"
|
||||||
:description "Snappy data-driven router for Clojure(Script)"
|
:description "Snappy data-driven router for Clojure(Script)"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,16 @@
|
||||||
(ns reitit.dev.pretty
|
(ns reitit.dev.pretty
|
||||||
(:require [clojure.string :as str]
|
(:require [arrangement.core] ;; spell-spec
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[reitit.exception :as exception]
|
[clojure.string :as str]
|
||||||
[arrangement.core]
|
[expound.alpha] ;; fipp
|
||||||
;; spell-spec
|
|
||||||
[spell-spec.expound]
|
|
||||||
;; expound
|
|
||||||
[expound.ansi]
|
[expound.ansi]
|
||||||
[expound.alpha]
|
|
||||||
;; fipp
|
|
||||||
[fipp.visit]
|
|
||||||
[fipp.edn]
|
[fipp.edn]
|
||||||
[fipp.ednize]
|
[fipp.ednize]
|
||||||
[fipp.engine]))
|
[fipp.engine]
|
||||||
|
[fipp.visit]
|
||||||
|
[reitit.exception :as exception]
|
||||||
|
[spell-spec.expound] ;; expound
|
||||||
|
))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; colors
|
;; colors
|
||||||
|
|
|
||||||
1
modules/reitit-frontend/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-frontend/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-frontend "0.5.15"
|
(defproject metosin/reitit-frontend "0.5.18"
|
||||||
:description "Reitit: Clojurescript frontend routing core"
|
:description "Reitit: Clojurescript frontend routing core"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
(ns reitit.frontend
|
(ns reitit.frontend
|
||||||
(:require [clojure.set :as set]
|
(:require [clojure.set :as set]
|
||||||
|
[clojure.string :as str]
|
||||||
[reitit.coercion :as coercion]
|
[reitit.coercion :as coercion]
|
||||||
[reitit.core :as r])
|
[reitit.core :as r])
|
||||||
(:import goog.Uri
|
(:import goog.Uri
|
||||||
|
|
@ -20,20 +21,45 @@
|
||||||
(map (juxt keyword #(query-param q %)))
|
(map (juxt keyword #(query-param q %)))
|
||||||
(into {}))))
|
(into {}))))
|
||||||
|
|
||||||
|
(defn fragment-params
|
||||||
|
"Given goog.Uri, read fragment parameters into Clojure map."
|
||||||
|
[^Uri uri]
|
||||||
|
(let [fp (.getFragment uri)]
|
||||||
|
(if-not (seq fp)
|
||||||
|
{}
|
||||||
|
(into {}
|
||||||
|
(comp
|
||||||
|
(map #(str/split % #"="))
|
||||||
|
(map (fn [[k v]]
|
||||||
|
[(keyword k) v])))
|
||||||
|
(str/split fp #"&")))))
|
||||||
|
|
||||||
(defn match-by-path
|
(defn match-by-path
|
||||||
"Given routing tree and current path, return match with possibly
|
"Given routing tree and current path, return match with possibly
|
||||||
coerced parameters. Return nil if no match found."
|
coerced parameters. Return nil if no match found.
|
||||||
[router path]
|
|
||||||
(let [uri (.parse Uri path)]
|
:on-coercion-error - a sideeffecting fn of `match exception -> nil`"
|
||||||
|
([router path] (match-by-path router path nil))
|
||||||
|
([router path {:keys [on-coercion-error]}]
|
||||||
|
(let [uri (.parse Uri path)
|
||||||
|
coerce! (if on-coercion-error
|
||||||
|
(fn [match]
|
||||||
|
(try (coercion/coerce! match)
|
||||||
|
(catch js/Error e
|
||||||
|
(on-coercion-error match e)
|
||||||
|
(throw e))))
|
||||||
|
coercion/coerce!)]
|
||||||
(if-let [match (r/match-by-path router (.getPath uri))]
|
(if-let [match (r/match-by-path router (.getPath uri))]
|
||||||
(let [q (query-params uri)
|
(let [q (query-params uri)
|
||||||
match (assoc match :query-params q)
|
fp (fragment-params uri)
|
||||||
|
match (assoc match :query-params q :fragment-params fp)
|
||||||
;; Return uncoerced values if coercion is not enabled - so
|
;; Return uncoerced values if coercion is not enabled - so
|
||||||
;; that tha parameters are always accessible from same property.
|
;; that tha parameters are always accessible from same property.
|
||||||
parameters (or (coercion/coerce! match)
|
parameters (or (coerce! match)
|
||||||
{:path (:path-params match)
|
{:path (:path-params match)
|
||||||
:query q})]
|
:query q
|
||||||
(assoc match :parameters parameters)))))
|
:fragment fp})]
|
||||||
|
(assoc match :parameters parameters))))))
|
||||||
|
|
||||||
(defn match-by-name
|
(defn match-by-name
|
||||||
"Given a router, route name and optionally path-parameters,
|
"Given a router, route name and optionally path-parameters,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
(ns reitit.frontend.history
|
(ns reitit.frontend.history
|
||||||
"Provides integration to hash-change or HTML5 History
|
"Provides integration to hash-change or HTML5 History
|
||||||
events."
|
events."
|
||||||
(:require [reitit.core :as reitit]
|
(:require [goog.events :as gevents]
|
||||||
[reitit.frontend :as rf]
|
[reitit.core :as reitit]
|
||||||
[goog.events :as gevents])
|
[reitit.frontend :as rf])
|
||||||
(:import goog.Uri))
|
(:import goog.Uri))
|
||||||
|
|
||||||
(defprotocol History
|
(defprotocol History
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
nil)
|
nil)
|
||||||
(-on-navigate [this path]
|
(-on-navigate [this path]
|
||||||
(reset! last-fragment path)
|
(reset! last-fragment path)
|
||||||
(on-navigate (rf/match-by-path router path) this))
|
(on-navigate (rf/match-by-path router path this) this))
|
||||||
(-get-path [this]
|
(-get-path [this]
|
||||||
;; Remove #
|
;; Remove #
|
||||||
;; "" or "#" should be same as "#/"
|
;; "" or "#" should be same as "#/"
|
||||||
|
|
@ -125,7 +125,7 @@
|
||||||
(-on-navigate this (-get-path this))
|
(-on-navigate this (-get-path this))
|
||||||
this))
|
this))
|
||||||
(-on-navigate [this path]
|
(-on-navigate [this path]
|
||||||
(on-navigate (rf/match-by-path router path) this))
|
(on-navigate (rf/match-by-path router path this) this))
|
||||||
(-stop [this]
|
(-stop [this]
|
||||||
(gevents/unlistenByKey listen-key)
|
(gevents/unlistenByKey listen-key)
|
||||||
(gevents/unlistenByKey click-listen-key)
|
(gevents/unlistenByKey click-listen-key)
|
||||||
|
|
|
||||||
1
modules/reitit-http/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-http/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-http "0.5.15"
|
(defproject metosin/reitit-http "0.5.18"
|
||||||
:description "Reitit: HTTP routing with interceptors"
|
:description "Reitit: HTTP routing with interceptors"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
(ns reitit.http
|
(ns reitit.http
|
||||||
(:require [meta-merge.core :refer [meta-merge]]
|
(:require [meta-merge.core :refer [meta-merge]]
|
||||||
[reitit.interceptor :as interceptor]
|
[reitit.core :as r]
|
||||||
[reitit.exception :as ex]
|
[reitit.exception :as ex]
|
||||||
[reitit.ring :as ring]
|
[reitit.interceptor :as interceptor]
|
||||||
[reitit.core :as r]))
|
[reitit.ring :as ring]))
|
||||||
|
|
||||||
(defrecord Endpoint [data interceptors queue handler path method])
|
(defrecord Endpoint [data interceptors queue handler path method])
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
(update acc method expand opts)
|
(update acc method expand opts)
|
||||||
acc)) data ring/http-methods)])
|
acc)) data ring/http-methods)])
|
||||||
|
|
||||||
(defn compile-result [[path data] {:keys [::default-options-endpoint expand] :as opts}]
|
(defn compile-result [[path data] {:keys [::default-options-endpoint expand meta-merge-fn] :as opts}]
|
||||||
(let [[top childs] (ring/group-keys data)
|
(let [[top childs] (ring/group-keys data)
|
||||||
childs (cond-> childs
|
childs (cond-> childs
|
||||||
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
||||||
|
|
@ -38,7 +38,7 @@
|
||||||
(->methods true top)
|
(->methods true top)
|
||||||
(reduce-kv
|
(reduce-kv
|
||||||
(fn [acc method data]
|
(fn [acc method data]
|
||||||
(let [data (meta-merge top data)]
|
(let [data ((or meta-merge-fn meta-merge) top data)]
|
||||||
(assoc acc method (->endpoint path data method method))))
|
(assoc acc method (->endpoint path data method method))))
|
||||||
(->methods (:handler top) data)
|
(->methods (:handler top) data)
|
||||||
childs))))
|
childs))))
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
(ns reitit.http.coercion
|
(ns reitit.http.coercion
|
||||||
(:require [reitit.coercion :as coercion]
|
(:require [reitit.coercion :as coercion]
|
||||||
[reitit.spec :as rs]
|
[reitit.impl :as impl]
|
||||||
[reitit.impl :as impl]))
|
[reitit.spec :as rs]))
|
||||||
|
|
||||||
(defn coerce-request-interceptor
|
(defn coerce-request-interceptor
|
||||||
"Interceptor for pluggable request coercion.
|
"Interceptor for pluggable request coercion.
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
(ns reitit.http.spec
|
(ns reitit.http.spec
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[reitit.ring.spec :as rrs]
|
|
||||||
[reitit.interceptor :as interceptor]
|
|
||||||
[reitit.exception :as exception]
|
[reitit.exception :as exception]
|
||||||
|
[reitit.interceptor :as interceptor]
|
||||||
|
[reitit.ring.spec :as rrs]
|
||||||
[reitit.spec :as rs]))
|
[reitit.spec :as rs]))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
|
|
|
||||||
1
modules/reitit-interceptors/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-interceptors/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-interceptors "0.5.15"
|
(defproject metosin/reitit-interceptors "0.5.18"
|
||||||
:description "Reitit, common interceptors bundled"
|
:description "Reitit, common interceptors bundled"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,9 @@
|
||||||
|
|
||||||
(defn- polish [ctx]
|
(defn- polish [ctx]
|
||||||
(-> ctx
|
(-> ctx
|
||||||
(dissoc ::original ::previous :stack :queue)
|
(dissoc ::original ::previous :stack :queue
|
||||||
|
:io.pedestal.interceptor.chain/stack
|
||||||
|
:io.pedestal.interceptor.chain/queue)
|
||||||
(update :request dissoc ::r/match ::r/router)))
|
(update :request dissoc ::r/match ::r/router)))
|
||||||
|
|
||||||
(defn- handle [name stage]
|
(defn- handle [name stage]
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
(ns reitit.http.interceptors.exception
|
(ns reitit.http.interceptors.exception
|
||||||
(:require [reitit.coercion :as coercion]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[reitit.ring :as ring]
|
[clojure.string :as str]
|
||||||
[clojure.spec.alpha :as s]
|
[reitit.coercion :as coercion]
|
||||||
[clojure.string :as str])
|
[reitit.ring :as ring])
|
||||||
(:import (java.time Instant)
|
(:import (java.io PrintWriter Writer)
|
||||||
(java.io PrintWriter Writer)))
|
(java.time Instant)))
|
||||||
|
|
||||||
(s/def ::handlers (s/map-of any? fn?))
|
(s/def ::handlers (s/map-of any? fn?))
|
||||||
(s/def ::spec (s/keys :opt-un [::handlers]))
|
(s/def ::spec (s/keys :opt-un [::handlers]))
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
(ns reitit.http.interceptors.multipart
|
(ns reitit.http.interceptors.multipart
|
||||||
(:require [reitit.coercion :as coercion]
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[reitit.coercion :as coercion]
|
||||||
[reitit.spec]
|
[reitit.spec]
|
||||||
[ring.middleware.multipart-params :as multipart-params]
|
[ring.middleware.multipart-params :as multipart-params]
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[spec-tools.core :as st])
|
[spec-tools.core :as st])
|
||||||
(:import (java.io File)))
|
(:import (java.io File)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
(ns reitit.http.interceptors.muuntaja
|
(ns reitit.http.interceptors.muuntaja
|
||||||
(:require [muuntaja.core :as m]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[muuntaja.interceptor]
|
[muuntaja.core :as m]
|
||||||
[clojure.spec.alpha :as s]))
|
[muuntaja.interceptor]))
|
||||||
|
|
||||||
(s/def ::muuntaja m/muuntaja?)
|
(s/def ::muuntaja m/muuntaja?)
|
||||||
(s/def ::spec (s/keys :opt-un [::muuntaja]))
|
(s/def ::spec (s/keys :opt-un [::muuntaja]))
|
||||||
|
|
|
||||||
1
modules/reitit-malli/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-malli/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-malli "0.5.15"
|
(defproject metosin/reitit-malli "0.5.18"
|
||||||
:description "Reitit: Malli coercion"
|
:description "Reitit: Malli coercion"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
(ns reitit.coercion.malli
|
(ns reitit.coercion.malli
|
||||||
(:require [reitit.coercion :as coercion]
|
(:require [clojure.set :as set]
|
||||||
[malli.transform :as mt]
|
[clojure.walk :as walk]
|
||||||
|
[malli.core :as m]
|
||||||
[malli.edn :as edn]
|
[malli.edn :as edn]
|
||||||
[malli.error :as me]
|
[malli.error :as me]
|
||||||
[malli.util :as mu]
|
[malli.experimental.lite :as l]
|
||||||
[malli.swagger :as swagger]
|
[malli.swagger :as swagger]
|
||||||
[malli.core :as m]
|
[malli.transform :as mt]
|
||||||
[clojure.set :as set]
|
[malli.util :as mu]
|
||||||
[clojure.walk :as walk]))
|
[reitit.coercion :as coercion]))
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; coercion
|
;; coercion
|
||||||
|
|
@ -113,7 +114,9 @@
|
||||||
:response {:default default-transformer-provider
|
:response {:default default-transformer-provider
|
||||||
:formats {"application/json" json-transformer-provider}}}
|
:formats {"application/json" json-transformer-provider}}}
|
||||||
;; set of keys to include in error messages
|
;; set of keys to include in error messages
|
||||||
:error-keys #{:type :coercion :in :schema :value :errors :humanized #_:transformed}
|
:error-keys #{:type :coercion :in #_:schema :value #_:errors :humanized #_:transformed}
|
||||||
|
;; support lite syntax?
|
||||||
|
:lite true
|
||||||
;; schema identity function (default: close all map schemas)
|
;; schema identity function (default: close all map schemas)
|
||||||
:compile mu/closed-schema
|
:compile mu/closed-schema
|
||||||
;; validate request & response
|
;; validate request & response
|
||||||
|
|
@ -133,9 +136,11 @@
|
||||||
([]
|
([]
|
||||||
(create nil))
|
(create nil))
|
||||||
([opts]
|
([opts]
|
||||||
(let [{:keys [transformers compile options error-keys encode-error] :as opts} (merge default-options opts)
|
(let [{:keys [transformers lite compile options error-keys encode-error] :as opts} (merge default-options opts)
|
||||||
show? (fn [key] (contains? error-keys key))
|
show? (fn [key] (contains? error-keys key))
|
||||||
transformers (walk/prewalk #(if (satisfies? TransformationProvider %) (-transformer % opts) %) transformers)]
|
transformers (walk/prewalk #(if (satisfies? TransformationProvider %) (-transformer % opts) %) transformers)
|
||||||
|
compile (if lite (fn [schema options] (compile (binding [l/*options* options] (l/schema schema)) options))
|
||||||
|
compile)]
|
||||||
^{:type ::coercion/coercion}
|
^{:type ::coercion/coercion}
|
||||||
(reify coercion/Coercion
|
(reify coercion/Coercion
|
||||||
(-get-name [_] :malli)
|
(-get-name [_] :malli)
|
||||||
|
|
|
||||||
1
modules/reitit-middleware/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-middleware/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-middleware "0.5.15"
|
(defproject metosin/reitit-middleware "0.5.18"
|
||||||
:description "Reitit, common middleware bundled"
|
:description "Reitit, common middleware bundled"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
(ns reitit.ring.middleware.exception
|
(ns reitit.ring.middleware.exception
|
||||||
(:require [reitit.coercion :as coercion]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[reitit.ring :as ring]
|
[clojure.string :as str]
|
||||||
[clojure.spec.alpha :as s]
|
[reitit.coercion :as coercion]
|
||||||
[clojure.string :as str])
|
[reitit.ring :as ring])
|
||||||
(:import (java.time Instant)
|
(:import (java.io Writer PrintWriter)
|
||||||
(java.io Writer PrintWriter)))
|
(java.time Instant)))
|
||||||
|
|
||||||
(s/def ::handlers (s/map-of any? fn?))
|
(s/def ::handlers (s/map-of any? fn?))
|
||||||
(s/def ::spec (s/keys :opt-un [::handlers]))
|
(s/def ::spec (s/keys :opt-un [::handlers]))
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
(ns reitit.ring.middleware.multipart
|
(ns reitit.ring.middleware.multipart
|
||||||
(:refer-clojure :exclude [compile])
|
(:refer-clojure :exclude [compile])
|
||||||
(:require [reitit.coercion :as coercion]
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[reitit.coercion :as coercion]
|
||||||
[ring.middleware.multipart-params :as multipart-params]
|
[ring.middleware.multipart-params :as multipart-params]
|
||||||
[clojure.spec.alpha :as s]
|
|
||||||
[spec-tools.core :as st])
|
[spec-tools.core :as st])
|
||||||
(:import (java.io File)))
|
(:import (java.io File)))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
(ns reitit.ring.middleware.muuntaja
|
(ns reitit.ring.middleware.muuntaja
|
||||||
(:require [muuntaja.core :as m]
|
(:require [clojure.spec.alpha :as s]
|
||||||
[muuntaja.middleware]
|
[muuntaja.core :as m]
|
||||||
[clojure.spec.alpha :as s]))
|
[muuntaja.middleware]))
|
||||||
|
|
||||||
(s/def ::muuntaja m/muuntaja?)
|
(s/def ::muuntaja m/muuntaja?)
|
||||||
(s/def ::spec (s/keys :opt-un [::muuntaja]))
|
(s/def ::spec (s/keys :opt-un [::muuntaja]))
|
||||||
|
|
|
||||||
1
modules/reitit-pedestal/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-pedestal/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-pedestal "0.5.15"
|
(defproject metosin/reitit-pedestal "0.5.18"
|
||||||
:description "Reitit + Pedestal Integration"
|
:description "Reitit + Pedestal Integration"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
(ns reitit.pedestal
|
(ns reitit.pedestal
|
||||||
(:require [io.pedestal.interceptor.chain :as chain]
|
(:require [io.pedestal.http :as http]
|
||||||
[io.pedestal.interceptor :as interceptor]
|
[io.pedestal.interceptor :as interceptor]
|
||||||
[io.pedestal.http :as http]
|
[io.pedestal.interceptor.chain :as chain]
|
||||||
[reitit.interceptor]
|
[reitit.http]
|
||||||
[reitit.http])
|
[reitit.interceptor])
|
||||||
(:import (reitit.interceptor Executor)
|
(:import (java.lang.reflect Method)
|
||||||
(java.lang.reflect Method)))
|
(reitit.interceptor Executor)))
|
||||||
|
|
||||||
;; TODO: variadic
|
;; TODO: variadic
|
||||||
(defn- arities [f]
|
(defn- arities [f]
|
||||||
|
|
|
||||||
1
modules/reitit-ring/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-ring/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-ring "0.5.15"
|
(defproject metosin/reitit-ring "0.5.18"
|
||||||
:description "Reitit: Ring routing"
|
:description "Reitit: Ring routing"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
(ns reitit.ring
|
(ns reitit.ring
|
||||||
(:require [meta-merge.core :refer [meta-merge]]
|
(:require [clojure.string :as str]
|
||||||
[reitit.middleware :as middleware]
|
[meta-merge.core :refer [meta-merge]]
|
||||||
[reitit.exception :as ex]
|
|
||||||
[reitit.core :as r]
|
|
||||||
[reitit.impl :as impl]
|
|
||||||
#?@(:clj [[ring.util.mime-type :as mime-type]
|
#?@(:clj [[ring.util.mime-type :as mime-type]
|
||||||
[ring.util.response :as response]])
|
[ring.util.response :as response]])
|
||||||
[clojure.string :as str]))
|
[reitit.core :as r]
|
||||||
|
[reitit.exception :as ex]
|
||||||
|
[reitit.impl :as impl]
|
||||||
|
[reitit.middleware :as middleware]))
|
||||||
|
|
||||||
(declare get-match)
|
(declare get-match)
|
||||||
(declare get-router)
|
(declare get-router)
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
(update acc method expand opts)
|
(update acc method expand opts)
|
||||||
acc)) data http-methods)])
|
acc)) data http-methods)])
|
||||||
|
|
||||||
(defn compile-result [[path data] {:keys [::default-options-endpoint expand] :as opts}]
|
(defn compile-result [[path data] {:keys [::default-options-endpoint expand meta-merge-fn] :as opts}]
|
||||||
(let [[top childs] (group-keys data)
|
(let [[top childs] (group-keys data)
|
||||||
childs (cond-> childs
|
childs (cond-> childs
|
||||||
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
||||||
|
|
@ -50,21 +50,21 @@
|
||||||
(->methods true top)
|
(->methods true top)
|
||||||
(reduce-kv
|
(reduce-kv
|
||||||
(fn [acc method data]
|
(fn [acc method data]
|
||||||
(let [data (meta-merge top data)]
|
(let [data ((or meta-merge-fn meta-merge) top data)]
|
||||||
(assoc acc method (->endpoint path data method method))))
|
(assoc acc method (->endpoint path data method method))))
|
||||||
(->methods (:handler top) data)
|
(->methods (:handler top) data)
|
||||||
childs))))
|
childs))))
|
||||||
|
|
||||||
(def default-options-handler
|
(def default-options-handler
|
||||||
(let [handle (fn [request]
|
(let [handler (fn [request]
|
||||||
(let [methods (->> request get-match :result (keep (fn [[k v]] (if v k))))
|
(let [methods (->> request get-match :result (keep (fn [[k v]] (if v k))))
|
||||||
allow (->> methods (map (comp str/upper-case name)) (str/join ","))]
|
allow (->> methods (map (comp str/upper-case name)) (str/join ","))]
|
||||||
{:status 200, :body "", :headers {"Allow" allow}}))]
|
{:status 200, :body "", :headers {"Allow" allow}}))]
|
||||||
(fn
|
(fn
|
||||||
([request]
|
([request]
|
||||||
(handle request))
|
(handler request))
|
||||||
([request respond _]
|
([request respond _]
|
||||||
(respond (handle request))))))
|
(respond (handler request))))))
|
||||||
|
|
||||||
(def default-options-endpoint
|
(def default-options-endpoint
|
||||||
{:no-doc true
|
{:no-doc true
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
(ns reitit.ring.coercion
|
(ns reitit.ring.coercion
|
||||||
(:require [reitit.coercion :as coercion]
|
(:require [reitit.coercion :as coercion]
|
||||||
[reitit.spec :as rs]
|
[reitit.impl :as impl]
|
||||||
[reitit.impl :as impl]))
|
[reitit.spec :as rs]))
|
||||||
|
|
||||||
(defn handle-coercion-exception [e respond raise]
|
(defn handle-coercion-exception [e respond raise]
|
||||||
(let [data (ex-data e)]
|
(let [data (ex-data e)]
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
(ns reitit.ring.spec
|
(ns reitit.ring.spec
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require [clojure.spec.alpha :as s]
|
||||||
|
[reitit.exception :as exception]
|
||||||
[reitit.middleware :as middleware]
|
[reitit.middleware :as middleware]
|
||||||
[reitit.spec :as rs]
|
[reitit.spec :as rs]))
|
||||||
[reitit.exception :as exception]))
|
|
||||||
|
|
||||||
;;
|
;;
|
||||||
;; Specs
|
;; Specs
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
(s/def ::trace map?)
|
(s/def ::trace map?)
|
||||||
(s/def ::patch map?)
|
(s/def ::patch map?)
|
||||||
|
|
||||||
|
|
||||||
(s/def ::data
|
(s/def ::data
|
||||||
(s/keys :opt-un [::rs/handler ::rs/name ::rs/no-doc ::middleware]))
|
(s/keys :opt-un [::rs/handler ::rs/name ::rs/no-doc ::middleware]))
|
||||||
|
|
||||||
|
|
|
||||||
1
modules/reitit-schema/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-schema/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-schema "0.5.15"
|
(defproject metosin/reitit-schema "0.5.18"
|
||||||
:description "Reitit: Plumatic Schema coercion"
|
:description "Reitit: Plumatic Schema coercion"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
(ns reitit.coercion.schema
|
(ns reitit.coercion.schema
|
||||||
(:require [clojure.walk :as walk]
|
(:require [clojure.set :as set]
|
||||||
[schema.core :as s]
|
[clojure.walk :as walk]
|
||||||
[schema-tools.core :as st]
|
|
||||||
[schema.coerce :as sc]
|
|
||||||
[schema.utils :as su]
|
|
||||||
[schema-tools.coerce :as stc]
|
|
||||||
[schema-tools.swagger.core :as swagger]
|
|
||||||
[reitit.coercion :as coercion]
|
[reitit.coercion :as coercion]
|
||||||
[clojure.set :as set]))
|
[schema-tools.coerce :as stc]
|
||||||
|
[schema-tools.core :as st]
|
||||||
|
[schema-tools.swagger.core :as swagger]
|
||||||
|
[schema.coerce :as sc]
|
||||||
|
[schema.core :as s]
|
||||||
|
[schema.utils :as su]))
|
||||||
|
|
||||||
(def string-coercion-matcher
|
(def string-coercion-matcher
|
||||||
stc/string-coercion-matcher)
|
stc/string-coercion-matcher)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
(ns reitit.ring.schema
|
(ns reitit.ring.schema
|
||||||
(:require [schema.core :as s]
|
(:require [schema-tools.swagger.core :as swagger]
|
||||||
[schema-tools.swagger.core :as swagger])
|
[schema.core :as s])
|
||||||
#?(:clj (:import (java.io File))))
|
#?(:clj (:import (java.io File))))
|
||||||
|
|
||||||
(defrecord Upload [m]
|
(defrecord Upload [m]
|
||||||
|
|
|
||||||
1
modules/reitit-sieppari/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-sieppari/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-sieppari "0.5.15"
|
(defproject metosin/reitit-sieppari "0.5.18"
|
||||||
:description "Reitit: Sieppari Interceptors"
|
:description "Reitit: Sieppari Interceptors"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
(ns reitit.interceptor.sieppari
|
(ns reitit.interceptor.sieppari
|
||||||
(:require [reitit.interceptor :as interceptor]
|
(:require [reitit.interceptor :as interceptor]
|
||||||
[sieppari.queue :as queue]
|
[sieppari.core :as sieppari]
|
||||||
[sieppari.core :as sieppari]))
|
[sieppari.queue :as queue]))
|
||||||
|
|
||||||
(def executor
|
(def executor
|
||||||
(reify
|
(reify
|
||||||
|
|
|
||||||
1
modules/reitit-spec/.clj-kondo/config.edn
Symbolic link
1
modules/reitit-spec/.clj-kondo/config.edn
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../../../.clj-kondo/module_config.edn
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
(defproject metosin/reitit-spec "0.5.15"
|
(defproject metosin/reitit-spec "0.5.18"
|
||||||
:description "Reitit: clojure.spec coercion"
|
:description "Reitit: clojure.spec coercion"
|
||||||
:url "https://github.com/metosin/reitit"
|
:url "https://github.com/metosin/reitit"
|
||||||
:license {:name "Eclipse Public License"
|
:license {:name "Eclipse Public License"
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
(ns reitit.coercion.spec
|
(ns reitit.coercion.spec
|
||||||
(:require [clojure.spec.alpha :as s]
|
(:require [clojure.set :as set]
|
||||||
|
[clojure.spec.alpha :as s]
|
||||||
|
[reitit.coercion :as coercion]
|
||||||
[spec-tools.core :as st #?@(:cljs [:refer [Spec]])]
|
[spec-tools.core :as st #?@(:cljs [:refer [Spec]])]
|
||||||
[spec-tools.data-spec :as ds #?@(:cljs [:refer [Maybe]])]
|
[spec-tools.data-spec :as ds #?@(:cljs [:refer [Maybe]])]
|
||||||
[spec-tools.swagger.core :as swagger]
|
[spec-tools.swagger.core :as swagger])
|
||||||
[reitit.coercion :as coercion]
|
|
||||||
[clojure.set :as set])
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(:import (spec_tools.core Spec)
|
(:import (spec_tools.core Spec)
|
||||||
(spec_tools.data_spec Maybe))))
|
(spec_tools.data_spec Maybe))))
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue