evaluating routing libs for a project. so much choice now... a lot of good stuff out there
feel free to suggest good options/experiences
@mpenet just cooking up metosin/reitit
as was not happy with any of the existing ones. Main features: route syntax for humans, best part of existing libs, supports cljs, middleware & interceptors, pluggable coercion (clojure.spec) & designed perf in mind. First release out soon, would appreciate feedback. https://metosin.github.io/reitit/ & some reasoning https://www.slideshare.net/metosin/performance-and-abstraction#30
I noticed it, looks interesting but it was too much in alpha state for my needs.
are you using it already?
I am leaning towards bidi atm
I mostly want a simple but extensible data format to describe routing and associated metadata then what it compiles to has little importance for now. I need to port a fairly large legacy app that uses compojure to that format
@ikitommi first impression, it seems to do too much. Should coercion/middleware'ing be part of a routing lib?
seems nice otherwise. Another nitpick would be the route params encoded in urls strings is not very friendly to generate stuff from it
> "/api/orders/:id"
@ikitommi some links 404 in the intro ex: https://metosin.github.io/reitit/routing/parameter-coercion.md
@mpenet thanks for the feedback! Idea was to deploy as separate artifacts, one could only depend on the core, which is tiny.
not in prod yet, but going there in a ~month.
about the path-params... generate stuff from, could you explain a bit?
"/api/orders/:id" hardcodes the id presence into the url
it's not really "data" in the sense if I want to document it or its presence I might have to parse the route
could be a vector instead
["/api/orders/" :id]
There is a parser withing reitit. I’ll paste an example.
oh well, it’s not exposed 😮 internally, the routes are parsed into just that form. I’ll add those to r/routes
result too.
Ataraxy and Bidi both separate parameters and path fragments. It’s a matter of taste.
(def routes
["/" [["auth/login" :auth/login]
[["auth/recovery/token/" :token] :auth/recovery]
["workspace/" [[[:project-uuid "/" :page-uuid] :workspace/page]]]]])
(def routes
[["/auth/login" :auth/login]
["/auth/recovery/token/:token" :auth/recovery]
["/workspace/:project-uuid/:page-uuid" :workspace/page]])
those were btw from bide, which has a rationale for the syntax too: https://github.com/funcool/bide#why-another-routing-library
@mpenet added route-info
, which provides the parsed route too:
(def router
(r/router
["/api" {:middleware [::body-params]}
["/ping" ::ping]
["/admin" {::roles #{:admin}}
["/db/:db" {:summary "delete a post"
:middleware [::db]
:name ::delete-db}]
["/ping" ::pong]]]))
(r/routes router)
;[["/api/ping" {:middleware [::body-params]
; :name ::ping}]
; ["/api/admin/db/:db" {:middleware [::body-params ::db],
; ::roles #{:admin},
; :summary "delete a post",
; :name ::delete-db}]
; ["/api/admin/ping" {:middleware [::body-params]
; ::roles #{:admin}, :name ::pong}]]
(mapv r/route-info (r/routes router))
;[{:path "/api/ping",
; :parts ["api" "ping"],
; :params #{},
; :result nil,
; :meta {:middleware [::body-params]
; :name ::ping}}
; {:path "/api/admin/db/:fb",
; :parts ["api" "admin" "db" :db],
; :params #{:db},
; :result nil,
; :meta {:middleware [::body-params ::db],
; ::roles #{:admin},
; :summary "delete a post",
; :name ::delete-db}}
; {:path "/api/admin/ping",
; :parts ["api" "admin" "ping"],
; :params #{},
; :result nil,
; :meta {:middleware [::body-params]
; ::roles #{:admin}
; :name ::pong}}]
I ll have a look tomorrow, thanks!