Support ring-route-data validation

This commit is contained in:
Tommi Reiman 2017-12-26 22:41:17 +02:00
parent 0dbb75ad44
commit 1a9583b31b
2 changed files with 85 additions and 0 deletions

View file

@ -0,0 +1,33 @@
(ns reitit.ring.spec
(:require [clojure.spec.alpha :as s]
[reitit.middleware #?@(:cljs [:refer [Middleware]])]
[reitit.spec :as rs])
#?(:clj
(:import (reitit.middleware Middleware))))
;;
;; Specs
;;
(s/def ::middleware (s/coll-of (partial instance? Middleware)))
(s/def ::data
(s/keys :req-un [::rs/handler]
:opt-un [::rs/name ::middleware]))
;;
;; Validator
;;
(defn- validate-ring-route-data [routes spec]
(->> (for [[p _ c] routes
[method {:keys [data] :as endpoint}] c
:when endpoint]
(when-let [problems (and spec (s/explain-data spec data))]
(rs/->Problem p method data spec problems)))
(keep identity) (seq)))
(defn validate-spec!
[routes {:keys [spec ::rs/explain] :or {explain s/explain-str, spec ::data}}]
(when-let [problems (validate-ring-route-data routes spec)]
(rs/throw-on-problems! problems explain)))

View file

@ -0,0 +1,52 @@
(ns reitit.ring-spec-test
(:require [clojure.test :refer [deftest testing is]]
[reitit.ring :as ring]
[reitit.ring.spec :as rrs]
[reitit.core :as r]
[reitit.spec :as rs])
#?(:clj
(:import (clojure.lang ExceptionInfo))))
(deftest route-data-validation-test
(testing "validation is turned off by default"
(is (true? (r/router?
(r/router
["/api" {:handler "identity"}])))))
(testing "with default spec validates :name, :handler and :middleware"
(is (thrown-with-msg?
ExceptionInfo
#"Invalid route data"
(ring/router
["/api" {:handler "identity"}]
{:validate rrs/validate-spec!})))
(is (thrown-with-msg?
ExceptionInfo
#"Invalid route data"
(ring/router
["/api" {:handler identity
:name "kikka"}]
{:validate rrs/validate-spec!})))
(is (thrown-with-msg?
ExceptionInfo
#"Invalid route data"
(ring/router
["/api" {:handler identity
:middleware [{}]}]
{:validate rrs/validate-spec!}))))
(testing "all endpoints are validated"
(is (thrown-with-msg?
ExceptionInfo
#"Invalid route data"
(ring/router
["/api" {:patch {:handler "identity"}}]
{:validate rrs/validate-spec!}))))
(testing "spec can be overridden"
(is (true? (r/router?
(ring/router
["/api" {:handler "identity"}]
{:spec any?
:validate rrs/validate-spec!}))))))