Merge branch 'master' into into-interceptor-for-multimethods

This commit is contained in:
Tommi Reiman 2023-01-09 17:40:32 +02:00 committed by GitHub
commit f80271fac1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
138 changed files with 2827 additions and 2170 deletions

View file

@ -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]}}}}

View file

@ -0,0 +1 @@
{:config-paths ["../../../.clj-kondo"]}

3
.lsp/config.edn Normal file
View file

@ -0,0 +1,3 @@
{:cljfmt {:indents {for-all [[:inner 0]]
are [[:inner 0]]}}
:clean {:ns-inner-blocks-indentation :same-line}}

View file

@ -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)**

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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])

View file

@ -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).

View file

@ -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:

View file

@ -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.

View file

@ -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.

View file

@ -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`

View file

@ -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:

View file

@ -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:

View file

@ -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})

View file

@ -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"]]

View file

@ -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"]]

View file

@ -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"]]

View file

@ -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"]]

View file

@ -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"]]

View file

@ -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"]]

View file

@ -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})

View file

@ -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})

View file

@ -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"]])

View file

@ -0,0 +1,11 @@
/target
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
.hgignore
.hg/

View 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})

View 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)

View file

@ -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})

View file

@ -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})

View file

@ -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})

View file

@ -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}

View file

@ -0,0 +1,11 @@
/target
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
.hgignore
.hg/

View 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

View 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"]]}})

Binary file not shown.

After

Width:  |  Height:  |  Size: 494 KiB

View 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))

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

View file

@ -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}")))))

View file

@ -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"]]}})

View file

@ -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"]]}})

View file

@ -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})

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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]

View file

@ -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)))

View file

@ -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 "&")))

View file

@ -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]

View file

@ -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]

View file

@ -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)]

View file

@ -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."

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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,

View file

@ -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)

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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))))

View file

@ -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.

View file

@ -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]))
;; ;;

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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]

View file

@ -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]))

View file

@ -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)))

View 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]))

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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)

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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]))

View file

@ -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)))

View 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]))

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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]

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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

View file

@ -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)]

View file

@ -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]))

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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)

View file

@ -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]

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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

View file

@ -0,0 +1 @@
../../../.clj-kondo/module_config.edn

View file

@ -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"

View file

@ -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