i'm mirroring https://github.com/metosin/reitit/blob/master/examples/ring-malli-swagger/src/example/server.clj as much as I can but I'm not getting coercion. I'm getting validation , but no coercion of request body.
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
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]
(ring/router
[["/" {:handler user-ctl/default}]
["/reset" {:handler user-ctl/reset-changes}]
["/user"
["/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
coerce-request-middleware
parameters/parameters-middleware
wrap-keyword-params
middleware-db]}}))
I can do match and coerce /user/form/3
for example. But /reset
and /
result in a 405.
It's like that compile key is causing routes with a :coercion
key to work but every other route to break.
Ugh... Ok.
["/list" {:get {:handler user-ctl/get-users}}]
Adding that Nope... dirty repl.: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?
sounds resolved? great!
@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
No. Thought it was resolved, but my REPL was in a state where the issue wouldn't present itself.
(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 https://github.com/metosin/reitit/issues/288 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
[:a.button.is-danger {: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}]
["/create"
{:name ::create-job
:view create-job-view/root}]])
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 :http://whatever.namespace.its.in/create-job`.
So if you use ::create-job
in two different files (i.e. namespaces (in general)) then it will be two different values.
ohhhhhhhhhhhh
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}]
["/create"
{:name :create-job
:view #'create-job-view/root}]])
(just changing things around rn per you comment and what im seeing on the web)
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
.
Or maybe de-namespace it everywhere.
I have http://app.ui.contratualizacao.menu on which I define : ::contrato which expands to http://app.ui.contratualizacao.menu/contrato. On other file i need to refer to that name. I require [http://app.ui.contratualizacao.menu :as menu-contr] and refer as ::menu-contr/contrato.
Or you can be explicit like @ericihli 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}]
["/create"
{:name ::create-job
:view create-job-view/root}]])
my call for the route is
[:a.button.is-danger {:href (rfe/href :create-job)} "Post a Job"]
prior i had
[:a.button.is-danger {:href (rfe/href ::create-job)} "Post a Job"]
::create-job
vs. :create-job
in the href
thanks everyone for the help and rubber ducking!
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.
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.
It's like a router that compiles coercion routes must ONLY include coerced routes. Other routes don't get matched against.