Fork me on GitHub
#reitit
<
2019-04-16
>
conan11:04:28

Hi, I've set up a route which is complaining that there's no handler for :post. It's true, there isn't - this resource doesn't accept :post. What could be causing reitit to be checking this? I have other routes that don't accept :post.

["/sentinel-l1c/:date" {:name "The Sentinel-2 L1C scene for a field on a given date"
                        :get {:parameters {:path {:date inst?}}
                              :responses {200 {:body ::l1c/scene}}
                              :handler get-scene}}]

ikitommi11:04:22

hi. what component is complaining about the missing :post?

ikitommi11:04:36

do you have a stacktrace?

conan11:04:37

Execution error (ExceptionInfo) at reitit.middleware/ensure-handler! (middleware.cljc:79).
path "/api/v1/fields/:field-id/sentinel-l1c/:date" doesn't have a :handler defined for :post

conan11:04:51

oh actually i'm just spotting a 201 response in there, but that's from a higher path in the hierarchy

ikitommi11:04:59

that’s weird. Can’t quickly figure out why would it test such an endpoint.

ikitommi11:04:35

as there is no :post in the data. hmm. If you can do a minimal repro and an issue, I could check it out.

conan11:04:45

yeah, there's something weird, i've probably nested something wrong

conan11:04:51

i'll have a go

ikitommi11:04:23

ok. this seems to work ok:

(ns user
  (:require [reitit.ring :as ring]))

(ring/ring-handler
  (ring/router
    ["/sentinel-l1c/:date"
     {:name "The Sentinel-2 L1C scene for a field on a given date"
      :get {:parameters {:path {:date inst?}}
            :responses {200 {:body {:date inst?}}}
            :handler identity}}]))

conan11:04:24

this reproduces:

(defn app
  []
  (ring/ring-handler
    (ring/router
      ["/fruit" {:post {:handle (constantly "post")}}
       ["/banana" {:get {:handler (constantly "get")}}]])))

(org.httpkit.server/run-server (app) {:port 1234})

conan11:04:41

path "/fruit/banana" doesn't have a :handler defined for :post

conan11:04:37

aaaand i've just spotted the typo. sorry!

conan11:04:12

why does it identify the nested route that's missing the handler rather than the one that's actually broken?

ikitommi11:04:02

for nested routes, the paths are concatenated, and the route data merged. sp the :post gets also merged to the banana-route.

ikitommi11:04:08

(->
  (ring/router
    ["/fruit" {:post {:handler (constantly "post")}}
     ["/banana" {:get {:handler (constantly "get")}}]])
  (r/routes))
;[["/fruit/banana"
;  {:post {:handler #object[clojure.core$constantly]}
;   :get {:handler #object[clojure.core$constantly]}}]]

ikitommi11:04:17

if you want also the /fruit to match, you need to define it as an endpoint:

ikitommi11:04:19

(->
  (ring/router
    ["/fruit"
     ["" {:post {:handler (constantly "post")}}]
     ["/banana" {:get {:handler (constantly "get")}}]])
  (r/routes))
;[["/fruit"
;  {:post {:handler #object[clojure.core$constantly]}}]
; ["/fruit/banana"
;  {:get {:handler #object[clojure.core$constantly]}}]]

ikitommi11:04:22

there is https://github.com/metosin/reitit/issues/175 to make the first one work like it…. should?

ikitommi11:04:45

with it, it would be:

(->
  (ring/router
    ["/fruit" {:post {:handler (constantly "post")}}
     ["/banana" {:get {:handler (constantly "get")}}]])
  (r/routes))
;[["/fruit"
;  {:post {:handler #object[clojure.core$constantly]}}]
; ["/fruit/banana"
;  {:post {:handler #object[clojure.core$constantly]}
;   :get {:handler #object[clojure.core$constantly]}}]]

conan15:04:11

ah yes, so i think the trick is to think what my routes would look like flattened - i.e. anything that isn't a leaf in the tree doesn't exist as an independent route. thanks!

👍 4
Francesco17:04:53

Hello, any suggestion how to achieve nested routes in a frontend application with reitit? I am trying to achieve something provided by react-router or vue-router, but since I am at the beginning, I am a bit struggling with it. I checked the example https://github.com/metosin/reitit/blob/master/examples/frontend-controllers/src/frontend/core.cljs but I’d like to render sub-views instead of controlling dom with params/queries. any idea?

ikitommi17:04:03

@fvitullo do you mean nested views? Could you point to an example from react/vue?

Francesco18:04:54

yes exactly. this example is in vue for instance:

ikitommi18:04:42

The Match is also available in reitit, but unlike react-router, only one route is matched at a time. Good news is that the data accumulates from root to leaves and this can be done with a new route data key, which has vector or set value.. I think

👍 4
ikitommi18:04:07

@juhoteperi most likely knows five good ways to model that ;)

juhoteperi18:04:02

No built-in solution or examples currently. But it is possible to implement this nested route data and vectors, as ikitommi mentioned.

ikitommi18:04:55

(I'm supposed to mention differences of reitit & js-routers in few days in Clojure/North, so an example of this would be really awesome)

juhoteperi18:04:08

Hah, I'll try to find time to build an example tomorrow. I've already been thinking that the frontend router docs should somehow provide list of things that React-router supports and tell how they can be implemented in Reitit. If we can provide examples for all, or even most, cases, it is a good validation for Reitit.

👍 8
Francesco18:04:30

nice 🙂 that would be really amazing…I have been mostly doing FE apps with React and Vue (using those mentioned routers) and I think it’s great leaving nested-views composition to the router (instead of manually handling it). I’d really appreciate it

Francesco19:04:10

exactly, so the route is being evaluated and specified sub :view is rendered

Francesco20:04:58

thank you very much Juho, I have implemented that gist in the frontend easy example and it seems working great