reitit

https://cljdoc.org/d/metosin/reitit/ https://github.com/metosin/reitit/
ikitommi 2020-09-18T07:10:05.001800Z

@benny you should declare a :coercion , e.g. :coercion reitit.coercion.spec/coercion into route data. It is used to transform the :parameters and :responses into JSON/Swagger Schema for api-docs.

ikitommi 2020-09-18T07:11:55.003200Z

@amarjeet do you handle the middleware chain as list/seq at some point? all declarations should be in vectors.

ikitommi 2020-09-18T07:15:49.005600Z

@rgm If I understood correctly, you want to filter out routes that don’t have a :handler / :name etc defined. there is a guide for composing routers here: https://cljdoc.org/d/metosin/reitit/0.5.5/doc/advanced/composing-routers - basically: create a router with expanded things, pull out the routes (they are now flattened, filter the data and create a new router.

🙏 1
ikitommi 2020-09-18T07:16:33.006400Z

you might be able to do that within a router using the route compiler, but the solution might be more complex.

ikitommi 2020-09-18T07:17:38.007600Z

the route tree merging and flattening utils are in reitit.impl , not part of the public api.

ikitommi 2020-09-18T07:34:03.016700Z

This is one of the sweet-spots of data-oriented route tables: you can add data like :dispatcher :nio and collect those routes into separate router, to be run nio the server NIO pool. Also tag routes with cluster info like :service/group "abc", and do multiple server provisioning with partial route tables. Monolithic Design, with micro deployments.

amarjeet 2020-09-18T07:39:44.016800Z

Hi @ikitommi, I tested with a small sample:

(ns cljservice.http.temp
  (:require [ring.middleware.json :refer [wrap-json-params wrap-json-response]]
            [ring.middleware.keyword-params :refer [wrap-keyword-params]]
            [reitit.ring :as ring]
            [aleph.http :as http]))

(defn get-handler [req]
  {:status 200
   :headers {"Content-Type" "application/json"}
   :body {:Response "Hello http-get world!"}})

(defn my-middleware [handler v]
  (fn [req]
    (let [response (handler req)]
      (assoc-in response [:body "middleware-val"] v))))

(def router
  (ring/router
   [["/" {:middleware [[wrap-json-response] [my-middleware 3] [my-middleware 2] [wrap-json-params] [wrap-keyword-params]]
          :get get-handler}]]))

(def app (ring/ring-handler
          router
          (ring/create-default-handler)))

(defn start-http-server []
  (http/start-server app {:port 3000}))
Now, if I make a get request, the middleware-val has value 3, not 2.

amarjeet 2020-09-18T07:43:49.017Z

Middlewares are in vec in this case.

ikitommi 2020-09-18T07:48:11.017200Z

middleware is a 2-way chain: here it’s json-response -> 3 -> 2 -> json-params -> wrap-keywords. For request, it’s processes in that order. For response it’s reverse (as it’s just a higher order function chain).

ikitommi 2020-09-18T07:48:31.017400Z

you are assoccing to response in the response pipeline.

ikitommi 2020-09-18T07:49:27.017600Z

there is a middleware chain diff printer which shows the order of things and the effects of each middleware, see examples.

ikitommi 2020-09-18T07:49:29.017800Z

hope this helps

amarjeet 2020-09-18T07:50:21.018Z

Aah, my bad - I realize now.

amarjeet 2020-09-18T07:50:28.018200Z

Thanks 🙂

ikitommi 2020-09-18T07:50:43.018400Z

You’re Welcome

Eyal H 2020-09-18T09:11:52.022500Z

Hey, I'm using the reitit.coercion.spec/coercion in reitit to validate the route, path and body of the request. I'm doing some benchmarking with non-valid requests (body params) and I noticed that the CPU is working very hard (4 CPU machine - 100% utilization when I fire 6000 req/sec). When the request is valid, CPU utilization is quite low (30-40%). Any idea what's causing the CPU to reach 100%?

Eyal H 2020-09-18T09:12:06.022600Z

{:exception pretty/exception
                 :data      {:coercion   rcs/coercion
                             :muuntaja   muuntaja/instance
                             :middleware [swagger/swagger-feature
                                          reitit-middleware-parameters/parameters-middleware
                                          muuntaja-middleware/format-negotiate-middleware
                                          muuntaja-middleware/format-response-middleware
                                          rrc/coerce-exceptions-middleware
                                          exception-middleware
                                          rrc/coerce-response-middleware
                                          muuntaja-middleware/format-request-middleware
                                          rrc/coerce-request-middleware
                                          app-data-middleware/add-app-data-middleware
                                          s2s-auth-middleware/auth-middleware]}}
Middlware configuration

Eyal H 2020-09-18T09:13:16.022800Z

The validation I'm doing is a simple one - validating strings

Eyal H 2020-09-18T09:29:59.023300Z

Snapshot of falmegraph of one thread

ikitommi 2020-09-18T09:52:32.025800Z

@eyaldocs could you run the same benchmark with malli coercion? On my tests, it's 1-3 orders of magnitude faster than spec

ikitommi 2020-09-18T09:55:53.028400Z

on a side-note: doing a spike on running the json->malli transformations within Jackson, removes one step (doing garbage) in the pipeline, should make things faster.

Eyal H 2020-09-18T10:06:40.029600Z

Thanks, @ikitommi I"ll give malli a try. Can you please elaborate on your side note, what exactly should I do

ikitommi 2020-09-18T10:12:13.029900Z

different :coercion , different way to describe the parameters and reaponses

Eyal H 2020-09-18T10:16:02.030100Z

Yes, thanks, I understood this part

Eyal H 2020-09-18T10:16:22.030300Z

I was talking about the second part of your answer

ikitommi 2020-09-18T12:53:38.030800Z

not implemented and don’t know how to integrate that in yet. I think we need to add a new protocols for muuntaja & reitit-coercion to negotiate that the coercion happens within json-decoding and the separate coercion is not needed. At code level, would like:

(require '[jsonista.malli :as jm])
(require '[malli.core :as m])

(def decode
  (m/decoder [:map [:x keyword?]] (jm/json-transformer {:strip-extra-keys true})))

(decode "{\"x\": \"kikka\", \"y\": 123}")
; => {:x :kikka}

ikitommi 2020-09-18T12:54:15.031Z

basically what the statically typed langs have had already for ages.

👍 1
2020-09-18T13:46:57.033300Z

Hi Reitit luvers! I want to share this GIT repository that might be useful. This is the useful usermanager example of @seancorfield (https://github.com/seancorfield/usermanager-example/) but for which for learning purposes, I started again from scratch by replacing the Compojure librarie by Reitit and Component by Integrant : https://github.com/PrestanceDesign/usermanager-reitit-integrant-example Cheers!

ikitommi 2020-09-18T13:51:33.034400Z

@admin055 thanks! could you do a PR and add it to reitit README so it’s found? there are some links there already.

2020-09-18T13:58:04.034500Z

Yes, for sure @ikitommi. Which section? "More examples" part?

rgm 2020-09-18T14:07:53.034700Z

Oh, that’s great! Thank you… I really like the idea that a router can be treated a coll of routes and all I need is good old (remove nil? ,,,) against the route data at start-up time. Right now I’m just gapping out the ignore-anchor-request? at run-time.

rgm 2020-09-18T14:10:03.035Z

I’ll read the composing routers page more closely … I’ve scanned it a couple of times but I’ve had that thing going on where I just needed a bit of help to recognize that I have a problem that it solves.

benny 2020-09-18T14:11:43.035200Z

thanks @ikitommi somehow reitit.coercion.spec/coercion is not being found when i have the uber reference, am i supposed to have something else pulled in for it to be recognized?

dharrigan 2020-09-18T14:14:48.035800Z

I should add my one, which is a simple startrek one + frontend/backend reitit with juxt clip

dharrigan 2020-09-18T14:14:52.036Z

I'll do a PR soon

👍 2
dharrigan 2020-09-20T09:14:39.039500Z

PR now available 🙂

ikitommi 2020-09-18T14:24:48.036100Z

sure, or a new section of external resources, or whatever feels good

ikitommi 2020-09-18T14:26:33.036400Z

what is an uber reference? you need reitit-spec module at least, or reitit , which contains all other modules

2020-09-18T14:45:14.036700Z

OK, another section is what I think is best since "More examples" are examples from the Reitit repo only. :thumbsup:

2020-09-18T15:02:11.036900Z

PR done.

Felipe Marques 2020-09-18T15:10:58.038100Z

Hello! I'm having problems with using Reitit in the Front-end. The coercion of path params works in dev but when I compile and serve the JS, it doesn't. Did anyone have a similar problem?

Felipe Marques 2020-09-19T14:13:53.038800Z

The problem disappears when I change the optmization from :simple to :advanced

ikitommi 2020-09-18T15:18:38.038200Z

Merged, thanks!

benny 2020-09-18T15:22:48.038400Z

i just meant the main reference to reitit (no specific references)

2020-09-18T16:17:11.038600Z

You're welcolme, thx to you!