reitit

https://cljdoc.org/d/metosin/reitit/ https://github.com/metosin/reitit/
2020-10-30T12:21:03.217300Z

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.

Eric Ihli 2020-10-30T14:03:14.218Z

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?

2020-10-30T14:09:10.218200Z

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

Eric Ihli 2020-10-30T14:10:19.218400Z

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]}}))

Eric Ihli 2020-10-30T14:10:54.218700Z

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

Eric Ihli 2020-10-30T14:11:39.218900Z

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

Eric Ihli 2020-10-30T14:15:20.219300Z

Ugh... Ok.

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

Eric Ihli 2020-10-30T14:16:01.219600Z

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.

ikitommi 2020-10-30T16:23:41.222200Z

sounds resolved? great!

2020-10-30T17:14:14.222500Z

@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 ?

ikitommi 2020-10-30T17:42:27.222700Z

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

👍 1
Eric Ihli 2020-10-30T17:50:04.222900Z

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

2020-10-30T19:14:44.224100Z

(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.

2020-10-30T20:01:20.225700Z

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

2020-10-30T20:02:16.226Z

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}]])

Eric Ihli 2020-10-30T20:20:58.226200Z

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`.

Eric Ihli 2020-10-30T20:21:29.226400Z

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

2020-10-30T20:22:23.226700Z

ohhhhhhhhhhhh

2020-10-30T20:23:21.226900Z

the routes are defined in client.api

2020-10-30T20:23:25.227100Z

(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}]])

2020-10-30T20:23:42.227300Z

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

Eric Ihli 2020-10-30T20:24:24.227500Z

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 Ihli 2020-10-30T20:24:37.227700Z

Or maybe de-namespace it everywhere.

2020-10-30T20:26:49.227900Z

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.

2020-10-30T20:27:29.228100Z

Or you can be explicit like @ericihli is suggesting

2020-10-30T20:27:54.228400Z

ah i got it!

2020-10-30T20:28:03.228600Z

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}]])

2020-10-30T20:28:15.228800Z

my call for the route is

2020-10-30T20:28:16.229Z

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

2020-10-30T20:28:28.229200Z

prior i had

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

2020-10-30T20:28:42.229400Z

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

2020-10-30T20:28:52.229600Z

thanks everyone for the help and rubber ducking!

Eric Ihli 2020-10-30T23:51:07.230100Z

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 Ihli 2020-10-30T23:52:24.230300Z

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 Ihli 2020-10-30T23:53:07.230500Z

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