Fork me on GitHub
#reitit
<
2020-11-01
>
ikitommi08:11:16

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

ikitommi08:11:10

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.

ikitommi08:11:30

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

ikitommi08:11:27

also, nils are removed automatically, so you can:

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

ikitommi08:11:00

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

ikitommi08:11:04

hope this helps.

Dave Russell08:11:16

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!!

teodorlu11:11:08

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

teodorlu12:11:26

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

ikitommi12:11:36

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

teodorlu15:11:12

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

ikitommi12:11:14

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

👍 3
teodorlu12:11:32

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:

Schmoho16:11:21

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

ikitommi17:11:42

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