mirror of
https://github.com/metosin/reitit.git
synced 2025-12-17 00:11:11 +00:00
Parameter & Response Coercion with specs
This commit is contained in:
parent
07bcd2ea59
commit
fb99b4f9fd
4 changed files with 113 additions and 1 deletions
|
|
@ -70,9 +70,42 @@
|
|||
:ret ::router)
|
||||
|
||||
;;
|
||||
;; Route data validator
|
||||
;; coercion
|
||||
;;
|
||||
|
||||
(s/def :reitit.core.coercion/kw-map (s/map-of keyword? any?))
|
||||
|
||||
(s/def :reitit.core.coercion/query :reitit.core.coercion/kw-map)
|
||||
(s/def :reitit.core.coercion/body :reitit.core.coercion/kw-map)
|
||||
(s/def :reitit.core.coercion/form :reitit.core.coercion/kw-map)
|
||||
(s/def :reitit.core.coercion/header :reitit.core.coercion/kw-map)
|
||||
(s/def :reitit.core.coercion/path :reitit.core.coercion/kw-map)
|
||||
(s/def :reitit.core.coercion/parameters
|
||||
(s/keys :opt-un [:reitit.core.coercion/query
|
||||
:reitit.core.coercion/body
|
||||
:reitit.core.coercion/form
|
||||
:reitit.core.coercion/header
|
||||
:reitit.core.coercion/path]))
|
||||
|
||||
(s/def ::parameters
|
||||
(s/keys :opt-un [:reitit.core.coercion/parameters]))
|
||||
|
||||
(s/def :reitit.core.coercion/status
|
||||
(s/or :number number? :default #{:default}))
|
||||
(s/def :reitit.core.coercion/schema any?)
|
||||
(s/def :reitit.core.coercion/description string?)
|
||||
(s/def :reitit.core.coercion/response
|
||||
(s/keys :opt-un [:reitit.core.coercion/schema
|
||||
:reitit.core.coercion/description]))
|
||||
(s/def :reitit.core.coercion/responses
|
||||
(s/map-of :reitit.core.coercion/status :reitit.core.coercion/response))
|
||||
|
||||
(s/def ::responses
|
||||
(s/keys :opt-un [:reitit.core.coercion/responses]))
|
||||
|
||||
;;
|
||||
;; Route data validator
|
||||
;;
|
||||
|
||||
(defrecord Problem [path scope data spec problems])
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
(ns reitit.ring.coercion
|
||||
(:require [reitit.coercion :as coercion]
|
||||
[reitit.spec :as rs]
|
||||
[reitit.impl :as impl]))
|
||||
|
||||
(defn handle-coercion-exception [e respond raise]
|
||||
|
|
@ -22,6 +23,7 @@
|
|||
Expects a :coercion of type `reitit.coercion/Coercion`
|
||||
and :parameters from route data, otherwise does not mount."
|
||||
{:name ::coerce-request
|
||||
:spec ::rs/parameters
|
||||
:compile (fn [{:keys [coercion parameters]} opts]
|
||||
(if (and coercion parameters)
|
||||
(let [coercers (coercion/request-coercers coercion parameters opts)]
|
||||
|
|
@ -39,6 +41,7 @@
|
|||
Expects a :coercion of type `reitit.coercion/Coercion`
|
||||
and :responses from route data, otherwise does not mount."
|
||||
{:name ::coerce-response
|
||||
:spec ::rs/responses
|
||||
:compile (fn [{:keys [coercion responses]} opts]
|
||||
(if (and coercion responses)
|
||||
(let [coercers (coercion/response-coercers coercion responses opts)]
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
(:require [clojure.test :refer [deftest testing is]]
|
||||
[reitit.ring :as ring]
|
||||
[reitit.ring.spec :as rrs]
|
||||
[reitit.ring.coercion :as rrc]
|
||||
[reitit.coercion.spec]
|
||||
[clojure.spec.alpha :as s]
|
||||
[reitit.core :as r])
|
||||
#?(:clj
|
||||
|
|
@ -76,3 +78,49 @@
|
|||
:wrap (fn [handler]
|
||||
(fn [request]
|
||||
(handler request)))}]}})))))
|
||||
|
||||
(deftest coercion-spec-test
|
||||
(is (r/router?
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {:a string?}
|
||||
:body {:b string?}
|
||||
:form {:c string?}
|
||||
:header {:d string?}
|
||||
:path {:e string?}}
|
||||
:responses {200 {:schema {:total pos-int?}}}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate-spec!})))
|
||||
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:parameters {:query {"a" string?}}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate-spec!})))
|
||||
|
||||
(is (thrown-with-msg?
|
||||
ExceptionInfo
|
||||
#"Invalid route data"
|
||||
(ring/router
|
||||
["/api"
|
||||
["/plus/:e"
|
||||
{:get {:responses {"200" {}}
|
||||
:handler identity}}]]
|
||||
{:data {:middleware [rrc/coerce-exceptions-middleware
|
||||
rrc/coerce-request-middleware
|
||||
rrc/coerce-response-middleware]
|
||||
:coercion reitit.coercion.spec/coercion}
|
||||
:validate rrs/validate-spec!}))))
|
||||
|
|
|
|||
|
|
@ -100,3 +100,31 @@
|
|||
["/api" {:handler "identity"}]
|
||||
{:spec any?
|
||||
:validate rs/validate-spec!})))))
|
||||
|
||||
(deftest parameters-test
|
||||
(is (s/valid?
|
||||
::rs/parameters
|
||||
{:parameters {:query {:a string?}
|
||||
:body {:b string?}
|
||||
:form {:c string?}
|
||||
:header {:d string?}
|
||||
:path {:e string?}}}))
|
||||
|
||||
(is (not (s/valid?
|
||||
::rs/parameters
|
||||
{:parameters {:header {"d" string?}}})))
|
||||
|
||||
(is (s/valid?
|
||||
::rs/responses
|
||||
{:responses {200 {:description "ok", :schema string?}
|
||||
400 {:description "fail"}
|
||||
500 {:schema string?}
|
||||
:default {}}}))
|
||||
|
||||
(is (not (s/valid?
|
||||
::rs/responses
|
||||
{:responses {"200" {:description "ok", :schema string?}}})))
|
||||
|
||||
(is (not (s/valid?
|
||||
::rs/responses
|
||||
{:responses {200 {:description :ok, :schema string?}}}))))
|
||||
|
|
|
|||
Loading…
Reference in a new issue