mirror of
https://github.com/metosin/reitit.git
synced 2026-02-14 23:35:16 +00:00
Compare commits
8 commits
949bed6d10
...
d920795f8b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d920795f8b | ||
|
|
45951aa82e | ||
|
|
1cdca2e3d5 | ||
|
|
2f22838820 | ||
|
|
d809291553 | ||
|
|
4e572e86d6 | ||
|
|
f26dc1ab19 | ||
|
|
0454e8914f |
7 changed files with 70 additions and 9 deletions
|
|
@ -16,6 +16,7 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
|
|||
|
||||
* Allow multimethods as handlers when validating [#755](https://github.com/metosin/reitit/pull/755)
|
||||
* Improve error reporting when generating OpenAPI fails [#754](https://github.com/metosin/reitit/pull/754)
|
||||
* Allow middleware registry to be used when defining middleware in `ring-handler`. See [docs](./doc/ring/middleware_registry.md). [#739](https://github.com/metosin/reitit/pull/739)
|
||||
|
||||
## 0.9.1 (2025-05-27)
|
||||
|
||||
|
|
|
|||
|
|
@ -73,9 +73,10 @@ Using `create` with options to create the coercion instead of `coercion`:
|
|||
{:transformers {:body {:default reitit.coercion.malli/default-transformer-provider
|
||||
:formats {"application/json" reitit.coercion.malli/json-transformer-provider}}
|
||||
:string {:default reitit.coercion.malli/string-transformer-provider}
|
||||
:response {:default reitit.coercion.malli/default-transformer-provider}}
|
||||
:response {:default reitit.coercion.malli/default-transformer-provider
|
||||
:formats {"application/json" reitit.coercion.malli/json-transformer-provider}}}
|
||||
;; 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)
|
||||
|
|
@ -88,6 +89,10 @@ Using `create` with options to create the coercion instead of `coercion`:
|
|||
:strip-extra-keys true
|
||||
;; add/set default values
|
||||
:default-values true
|
||||
;; add/set defaults also for optional keys. Corresponds to :malli.transform/add-optional-keys
|
||||
:default-values-for-optional-keys false
|
||||
;; encode-error
|
||||
:encode-error nil
|
||||
;; malli options
|
||||
:options nil})
|
||||
```
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
The `:middleware` syntax in `reitit-ring` also supports Keywords. Keywords are looked up from the Middleware Registry, which is a map of `keyword => IntoMiddleware`. Middleware registry should be stored under key `:reitit.middleware/registry` in the router options. If a middleware keyword isn't found in the registry, router creation fails fast with a descriptive error message.
|
||||
|
||||
## Examples
|
||||
## Examples
|
||||
|
||||
Application using middleware defined in the Middleware Registry:
|
||||
|
||||
|
|
@ -52,6 +52,20 @@ Router creation fails fast if the registry doesn't contain the middleware:
|
|||
;| :bonus | reitit.ring_test$wrap_bonus@59fddabb |
|
||||
```
|
||||
|
||||
Middleware defined in the registry can also be used on the `ring-handler` level:
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/api"
|
||||
["/bonus" {:get (fn [{:keys [bonus]}]
|
||||
{:status 200, :body {:bonus bonus}})}]]
|
||||
{::middleware/registry {:bonus wrap-bonus}})
|
||||
nil
|
||||
{:middleware [[:bonus 15]]}))
|
||||
```
|
||||
|
||||
## When to use the registry?
|
||||
|
||||
Middleware as Keywords helps to keep the routes (all but handlers) as literal data (i.e. data that evaluates to itself), enabling the routes to be persisted in external formats like EDN-files and databases. Duct is a good example, where the [middleware can be referenced from EDN-files](https://github.com/duct-framework/duct/wiki/Configuration). It should be easy to make Duct configuration a Middleware Registry in `reitit-ring`.
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@
|
|||
[malli.swagger :as swagger]
|
||||
[malli.transform :as mt]
|
||||
[malli.util :as mu]
|
||||
[reitit.coercion :as coercion]
|
||||
[clojure.string :as string]))
|
||||
[reitit.coercion :as coercion]))
|
||||
|
||||
;;
|
||||
;; coercion
|
||||
|
|
@ -27,11 +26,11 @@
|
|||
|
||||
(defn- -provider [transformer]
|
||||
(reify TransformationProvider
|
||||
(-transformer [_ {:keys [strip-extra-keys default-values]}]
|
||||
(-transformer [_ {:keys [strip-extra-keys default-values default-values-for-optional-keys]}]
|
||||
(mt/transformer
|
||||
(if strip-extra-keys (mt/strip-extra-keys-transformer))
|
||||
transformer
|
||||
(if default-values (mt/default-value-transformer))))))
|
||||
(if default-values (mt/default-value-transformer {:malli.transform/add-optional-keys default-values-for-optional-keys}))))))
|
||||
|
||||
(def string-transformer-provider (-provider (mt/string-transformer)))
|
||||
(def json-transformer-provider (-provider (mt/json-transformer)))
|
||||
|
|
@ -118,6 +117,8 @@
|
|||
:strip-extra-keys true
|
||||
;; add/set default values
|
||||
:default-values true
|
||||
;; add/set defaults also for optional keys. Corresponds to :malli.transform/add-optional-keys
|
||||
:default-values-for-optional-keys false
|
||||
;; encode-error
|
||||
:encode-error nil
|
||||
;; malli options
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@
|
|||
([router default-handler {:keys [middleware inject-match? inject-router?]
|
||||
:or {inject-match? true, inject-router? true}}]
|
||||
(let [default-handler (or default-handler (fn ([_]) ([_ respond _] (respond nil))))
|
||||
wrap (if middleware (partial middleware/chain middleware) identity)
|
||||
wrap (if middleware #(middleware/chain middleware % nil (r/options router)) identity)
|
||||
enrich-request (create-enrich-request inject-match? inject-router?)
|
||||
enrich-default-request (create-enrich-default-request inject-router?)]
|
||||
(with-meta
|
||||
|
|
|
|||
|
|
@ -140,6 +140,27 @@
|
|||
(let [m (r/match-by-path r "/none/kikka/abba")]
|
||||
(is (= nil (coercion/coerce! m))))))))
|
||||
|
||||
(deftest malli-query-parameter-coercion-test
|
||||
(let [router (fn [coercion]
|
||||
(r/router ["/test"
|
||||
{:coercion coercion
|
||||
:parameters {:query [:map
|
||||
[:a [:string {:default "a"}]]
|
||||
[:x {:optional true} [:keyword {:default :a}]]]}}]
|
||||
{:compile coercion/compile-request-coercers}))]
|
||||
(testing "default values for :optional query keys do not get added"
|
||||
(is (= {:query {:a "a"}}
|
||||
(-> (r/match-by-path (router reitit.coercion.malli/coercion) "/test")
|
||||
(assoc :query-params {})
|
||||
(coercion/coerce!)))))
|
||||
(testing "default values for :optional query keys get added when :default-values-for-optional-keys is set"
|
||||
(is (= {:query {:a "a" :x :a}}
|
||||
(-> (r/match-by-path (router (reitit.coercion.malli/create
|
||||
(assoc reitit.coercion.malli/default-options
|
||||
:default-values-for-optional-keys true))) "/test")
|
||||
(assoc :query-params {})
|
||||
(coercion/coerce!)))))))
|
||||
|
||||
(defn match-by-path-and-coerce! [router path]
|
||||
(if-let [match (r/match-by-path router path)]
|
||||
(assoc match :parameters (coercion/coerce! match))))
|
||||
|
|
|
|||
|
|
@ -114,6 +114,25 @@
|
|||
(is (= {:status 200, :body [:top :api :ok]}
|
||||
(app {:uri "/api/get" :request-method :get}))))))
|
||||
|
||||
(testing "middleware from registry"
|
||||
(let [router (ring/router
|
||||
["/api" {:middleware [:mw-foo]}
|
||||
["/get" {:middleware [[:mw :inner]]
|
||||
:get handler}]]
|
||||
{::middleware/registry {:mw mw
|
||||
:mw-foo #(mw % :foo)}})
|
||||
app (ring/ring-handler router nil {:middleware [[:mw :top]]})]
|
||||
|
||||
(testing "router can be extracted"
|
||||
(is (= router (ring/get-router app))))
|
||||
|
||||
(testing "not found"
|
||||
(is (= nil (app {:uri "/favicon.ico"}))))
|
||||
|
||||
(testing "on match"
|
||||
(is (= {:status 200, :body [:top :foo :inner :ok]}
|
||||
(app {:uri "/api/get" :request-method :get}))))))
|
||||
|
||||
(testing "named routes"
|
||||
(let [router (ring/router
|
||||
[["/api"
|
||||
|
|
@ -743,7 +762,7 @@
|
|||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/foobar"))]
|
||||
(is (= 404 (:status response)))))))
|
||||
|
||||
|
||||
(testing "with additional mime types"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
|
|
|
|||
Loading…
Reference in a new issue