reitit

https://cljdoc.org/d/metosin/reitit/ https://github.com/metosin/reitit/
ikitommi 2020-11-01T08:22:16.251100Z

@david.russell if you donโ€™t need dynamic routers, just use data. Something like:

(defn generic-routes [args]
  ["/baz" {:get (handler-to-do-something-with args)}])

(defn foo-routes [args]
  ["/foo" 
    ["/foo" (constantly {:status 200, :body "foo"})]
    (generic-routes args)]])

(defn bar-routes [args]
  ["/bar" 
    ["/bar" (constantly {:status 200, :body "bar"})]
    (generic-routes args)]])

(defn all-routes [args]
  [(foo-routes args)
   (bar-routes args)])

ikitommi 2020-11-01T08:24:10.253200Z

reitit automatically flattens sequential routes, so you can return partial routes either as singular:

(defn routes [_]ย ["/ping" handle-ping])
or as list of routes:
(defn routes [_]ย [["/ping" handle-ping]])
or even:
(defn routes [_]ย [[[[["/ping" handle-ping]]]]])
all work the same.

ikitommi 2020-11-01T08:26:30.254200Z

some smarter people might say https://stuartsierra.com/2015/06/10/clojure-donts-heisenparameter, but makes programming with routes much easier.

ikitommi 2020-11-01T08:27:27.255500Z

also, nils are removed automatically, so you can:

["/admin"
 (if (dev-mode) ["/remove-db" remove-db-handler])]

ikitommi 2020-11-01T08:28:00.256200Z

everything is done at router creation time, so the end-result is an optimized route tree.

ikitommi 2020-11-01T08:28:04.256400Z

hope this helps.

Dave Russell 2020-11-02T08:34:16.277800Z

It definitely does -- I just tested the data-based approach you suggest and it works perfectly. I'm not sure why I reached first for a macro ๐Ÿ™‚ The nil and flattening is also super helpful because I was previously wrapping routes so that a single tree was returned, but a list of routes is more ergonomic. Thanks very much!!

teodorlu 2020-11-01T11:57:08.257500Z

Hey! Quick barrage of Reitit questions. 1. Reading Reitit's Cljdoc on coercion[1], I was surprised that Malli was not mentioned. Yet, Malli seems to come as a dependency to Reitit. On the other hand, the ring-swagger example[2] uses Malli. I assume there's plans to make Reitit and Malli play nice together; and that docs for using Malli for reitit coercion will be added as Malli approaches a stable release? 2. I want request coercion. I like Reitit and Malli's data-driven approach. Are there reasons to pick Plumatic Schema, Sclojure.spec or Data-specs over Malli? 3. Is the ring-swagger example a good way to get started with Reitit and Malli? [1]: https://cljdoc.org/d/metosin/reitit/0.5.10/doc/coercion [2]: https://github.com/metosin/reitit/blob/master/examples/ring-swagger/src/example/server.clj

teodorlu 2020-11-01T12:31:26.259200Z

The ring-swagger example might not be using malli after all. With an invalid JSON request, I'm getting a spec tools error message:

"(spec-tools.core/spec {:spec (clojure.spec.alpha/keys :req-un [:spec$8818/x :spec$8818/y]), :type :map, :leaf? false})"

ikitommi 2020-11-01T12:32:36.260800Z

@teodorlu please PR Malli for the docs! Just forgot those.

ikitommi 2020-11-01T12:33:29.261300Z

https://github.com/metosin/reitit/tree/master/examples/ring-malli-swagger is the malli-variant

1๐Ÿ‘
ikitommi 2020-11-01T12:37:14.266700Z

currently porting a schema-based project to use malli, fixing the rough edges on the process. E.g. the date-support is not as good yet and there is a design bug in accumulating schemas in reitit, most visible with malli: https://github.com/metosin/reitit/issues/422

1๐Ÿ‘
teodorlu 2020-11-01T12:42:32.268700Z

Thanks for the correction (ring-malli-swagger) & the link to the issue. It was useful to see a smaller example (issue). I'm not promising a PR for Malli coercion docs, but it would be a good excercise to build a proper understanding :thumbsup:

teodorlu 2020-11-01T15:55:12.268800Z

@ikitommi PR: https://github.com/metosin/reitit/pull/448/files I wasn't able to test with cljdoc locally, but the change is quite simple.

ikitommi 2020-11-01T15:56:20.269100Z

thanks!

Schmoho 2020-11-01T16:43:21.272400Z

Why does this fail?

(def routes
  ["/"
   {:get {:handler    ok
          :middleware [#(wrap-resource % "public")]}}])

(def router
  (ring/router routes))

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

(jetty/run-jetty (wrap-reload #'app) {:port  3000 :join? false}))
ok is (constantly {:status 200 :body "ok"}) - ring is reitit.ring There is an index.html in public, it's served alright when I just wrap the ok handler directly in wrap-resource and put it in jetty. This way I get HTTP ERROR 500 java.lang.NullPointerException: Response map is nil

ikitommi 2020-11-01T17:01:42.277700Z

@d.eltzner reitit is route-first, you are only mapping an exact "/" match. You should either 1) use a wildcard route 2) use the ring-router default-handler argument or 3) add the middleware into ring/ring-handler with :middleware option. 2 is the best imo, docs should cover how to do that.