@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.
https://github.com/metosin/reitit/blob/master/examples/ring-spec-swagger/src/example/server.clj#L84
@amarjeet do you handle the middleware chain as list/seq at some point? all declarations should be in vectors.
@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.
you might be able to do that within a router using the route compiler, but the solution might be more complex.
the route tree merging and flattening utils are in reitit.impl
, not part of the public api.
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.
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
.Middlewares are in vec in this case.
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).
you are assoccing to response in the response pipeline.
there is a middleware chain diff printer which shows the order of things and the effects of each middleware, see examples.
hope this helps
Aah, my bad - I realize now.
Thanks 🙂
You’re Welcome
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%?
{: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 configurationThe validation I'm doing is a simple one - validating strings
Snapshot of falmegraph of one thread
@eyaldocs could you run the same benchmark with malli coercion? On my tests, it's 1-3 orders of magnitude faster than spec
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.
Thanks, @ikitommi I"ll give malli a try. Can you please elaborate on your side note, what exactly should I do
here's with spec: https://github.com/metosin/reitit/tree/master/examples/ring-spec-swagger/src/example with malli: https://github.com/metosin/reitit/tree/master/examples/ring-malli-swagger/src/example
different :coercion
, different way to describe the parameters and reaponses
Yes, thanks, I understood this part
I was talking about the second part of your answer
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}
basically what the statically typed langs have had already for ages.
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!
@admin055 thanks! could you do a PR and add it to reitit README so it’s found? there are some links there already.
Yes, for sure @ikitommi. Which section? "More examples" part?
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.
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.
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?
I should add my one, which is a simple startrek one + frontend/backend reitit with juxt clip
I'll do a PR soon
PR now available 🙂
sure, or a new section of external resources, or whatever feels good
what is an uber reference? you need reitit-spec
module at least, or reitit
, which contains all other modules
OK, another section is what I think is best since "More examples" are examples from the Reitit repo only. :thumbsup:
PR done.
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?
The problem disappears when I change the optmization from :simple
to :advanced
Merged, thanks!
i just meant the main reference to reitit (no specific references)
You're welcolme, thx to you!