3.4 KiB
Coercion
Coercion is a process of transforming parameters from one format into another.
By default, all wildcard and catch-all parameters are parsed as Strings:
(require '[reitit.core :as r])
(def router
(r/router
["/:company/users/:user-id" ::user-view]))
Here's a match:
(r/match-by-path r "/metosin/users/123")
; #Match{:template "/:company/users/:user-id",
; :data {:name :user/user-view},
; :result nil,
; :params {:company "metosin", :user-id "123"},
; :path "/metosin/users/123"}
To enable parameter coercion, we need to do few things:
- Choose a
Coercionfor the routes - Defined types for the parameters
- Compile coercers for the types
- Apply the coercion
Coercion
Coercion is a protocol defining how types can be defined, coerced and inventoried.
Reitit ships with the following coercion modules:
reitit.coercion.schema/coercionfor plumatic schema.reitit.coercion.spec/coercionfor both clojure.spec and data-specs.
Coercion can be attached to routes using a :coercion key in the route data. There can be multiple Coercion implementation into a single router, normal scoping rules apply here too.
Defining types for parameters
Route parameters can be defined via route data :parameters. It can be submaps to define different types of parameters: :query, :body, :form, :header and :path. Syntax for the actual parameters is defined by the Coercion being used.
Schema
(require '[reitit.coercion.schema])
(require '[schema.core :as schema])
(def router
(r/router
["/:company/users/:user-id" {:name ::user-view
:coercion reitit.coercion.schema/coercion
:parameters {:path {:company schema/Str
:user-id schema/Int}]))
Clojure.spec
Currently, clojure.spec doesn't support runtime transformations via conforming, so one needs to wrap all specs with spec-tools.core/spec to get this working.
(require '[reitit.coercion.spec])
(require '[spec-tools.spec :as spec])
(require '[clojure.spec :as s])
(s/def ::company spec/string?
(s/def ::user-id spec/int?
(s/def ::path-params (s/keys :req-un [::company ::user-id]))
(def router
(r/router
["/:company/users/:user-id" {:name ::user-view
:coercion reitit.coercion.spec/coercion
:parameters {:path ::path-params]))
Data-specs
(require '[reitit.coercion.spec])
(def router
(r/router
["/:company/users/:user-id" {:name ::user-view
:coercion reitit.coercion.spec/coercion
:parameters {:path {:company str?
:user-id int?}]))
So, now we have our
Thanks to
Most of the thing are just redefined version of the original implementation. Big thanks to:
- compojure-api for the initial
Coercionprotocol - ring-swagger for the syntax for the
:paramters(and:responses).