Fork me on GitHub

i'm mirroring as much as I can but I'm not getting coercion. I'm getting validation , but no coercion of request body.

Eric Ihli14:10:14

I don't know if this is related, but for that second argument to `ring/router`, if I pass `{:compile coercion/compile-request-coercers ,,,`, then I get coercion. If I pass it as `{:data {:compile coercion/compile-request-coercers ,,,` then I get an error that `reitit.ring.Endpoint cannot be cast to clojure.lang.IFn`. Every example I see has :compile nested under :data. So I'm trying to figure out why mine works when not nested and breaks when nested. Are both supposed to be supported? Was there an update and one is legacy?


I've tried that (compile on :data) but I've got 405 method not allowed on my requests

Eric Ihli14:10:19

Yeah I've run into that too. But only on requests that don't use coercion. Still trying to figure it out.

(defn router [db]
   [["/" {:handler user-ctl/default}]
    ["/reset" {:handler user-ctl/reset-changes}]
     ["/list" {:handler user-ctl/get-users}]
     ["/form" {:handler user-ctl/edit}]
     ["/form/:id" {:parameters {:path {:id int?}}
                   :coercion reitit.coercion.spec/coercion
                   :get {:handler user-ctl/edit}}]
     ["/save" {:post {:handler user-ctl/save}}]
     ["/delete/:id" {:get {:handler user-ctl/delete-by-id}
                     :coercion reitit.coercion.spec/coercion
                     :parameters {:path {:id int?}}}]]]
   {:compile coercion/compile-request-coercers
    :data {:db db
           :middleware [my-middleware

Eric Ihli14:10:54

I can do match and coerce /user/form/3 for example. But /reset and / result in a 405.

Eric Ihli14:10:39

It's like that compile key is causing routes with a :coercion key to work but every other route to break.

Eric Ihli14:10:20

Ugh... Ok.

["/list" {:get {:handler user-ctl/get-users}}]

Eric Ihli14:10:01

Adding that :get key to to the route got rid of the 405. So... I guess when your using coercion, you must manually specify methods for routes that don't have a :parameters and :coercion keys? Nope... dirty repl.


sounds resolved? great!

Eric Ihli17:10:04

No. Thought it was resolved, but my REPL was in a state where the issue wouldn't present itself.

Eric Ihli23:10:07

Ok. I haven't pinpointed exactly what part of the code causes this to be the case, but I have found a set of options that works.

Eric Ihli23:10:24

My understanding is that when a routers options includes a compile coercion/compile-request-coercers key/value, then any route that doesn't include a {:coercion reitit.coercion.spec/coercion :parameters {,,,}} will get excluded from the router.

Eric Ihli23:10:07

It's like a router that compiles coercion routes must ONLY include coerced routes. Other routes don't get matched against.


@ikitommi I've tried the example posting x: "1" y: "1" and it does to coerce body parameters to 1. What can I do to coerce body parameters ?


JSON coercion doen't coerce string->number, as JSON supports numbers. If you need that, you have to swap the json- body coercion to use String Coercion. Can be done by creating a coercion impl with options. There should be example out somewhere. Sorry, the docs could be better

👍 3

(def custom-coercion (reitit.coercion.malli/create { :transformers {:body {:default reitit.coercion.malli/string-transformer-provider :formats {"application/json" reitit.coercion.malli/string-transformer-provider}} :string {:default reitit.coercion.malli/string-transformer-provider} :response {:default reitit.coercion.malli/default-transformer-provider}} ;; 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 malli.util/closed-schema ;; strip-extra-keys (effects only predefined transformers) :strip-extra-keys true ;; add/set default values :default-values true ;; malli options :options nil}) ) @ikitommi with the information you provided I've found and with this custom-coercion it worked.


hey everyone i am new to clj + cljs. i am attempting to use reitit in a cljs project. i have my routes defined in a separate cljs file but i get this error when trying to refer to a route in another file


in my view file i am using this

[ {:href (rfe/href ::create-job)} "Post a Job"]
it says that it cannot find ::create-job but in my routes file i have this
(def routes
    {:name ::frontpage
     :view home-view/home-page}]

    {:name ::create-job
     :view create-job-view/root}]])

Eric Ihli20:10:58

I don't have high confidence that what I'm about to say is related to your issue, but I see you say "new to clj" and I see a namespaced keyword ::create-job and I remember the times I ran into problems due to namespace issues. Are those routes defined in client.home.view? I see the error message say that it can't find client.home.view/create-job. The double colon before a keyword namespaces it. so ::create-job becomes :`.

Eric Ihli20:10:29

So if you use ::create-job in two different files (i.e. namespaces (in general)) then it will be two different values.




the routes are defined in client.api


(ns client.api
  (:require [client.home.view :as home-view]
            [client.job.create.view :as create-job-view]))

(def routes
    {:name :frontpage
     :view #'home-view/home-page}]

    {:name :create-job
     :view #'create-job-view/root}]])


(just changing things around rn per you comment and what im seeing on the web)

Eric Ihli20:10:24

Oh. Well I see in that code you just pasted :create-job is not namespaced. Try namespacing it, ::create-job in client.api and then try accessing it from your view as :client.api/create-job.

Eric Ihli20:10:37

Or maybe de-namespace it everywhere.


I have on which I define : ::contrato which expands to On other file i need to refer to that name. I require [ :as menu-contr] and refer as ::menu-contr/contrato.


Or you can be explicit like @UJP37GW2K is suggesting


ah i got it!


i router is

(ns client.api
  (:require [client.home.view :as home-view]
            [client.job.create.view :as create-job-view]))

(def routes
    {:name ::frontpage
     :view home-view/home-page}]

    {:name ::create-job
     :view create-job-view/root}]])


my call for the route is


[ {:href (rfe/href :create-job)} "Post a Job"]


prior i had

[ {:href (rfe/href ::create-job)} "Post a Job"]


::create-job vs. :create-job in the href


thanks everyone for the help and rubber ducking!