reitit

2024-11-05T17:14:20.204659Z

I'm having a hard time getting the nested behavior with controller start/stop behavior described here: https://github.com/metosin/reitit/blob/master/doc/frontend/controllers.md#nested-controllers It makes it sound like when you have a hierarchy like /a/b/c that even loading c that you should expect to see the a and b controllers invoked first.

2024-11-05T17:14:32.604739Z

Is there something special I have to do in order to make this work?

2024-11-05T17:58:24.335799Z

I'm not even convinced about the nested routes with "/" and then "/item/:id" -- doesn't this result in double leading slashes?

opqdonut 2024-11-06T09:27:48.372829Z

have you tried the frontend-controllers example? it works for me, and the controllers fire as expected

opqdonut 2024-11-06T09:31:31.700689Z

e.g. navigating to http://localhost:3449/#/items/1 , I see the following in my browser console: • start root-controller • start items controller • start item controller 1

2024-11-06T11:44:00.759169Z

@joel.kaasinen Yes, the example works for me, but it all seems quite fragile.

2024-11-06T11:44:22.690149Z

I don't think the explanations in the documentation are adequate, and it's not easy to debug into this stuff to understand what it is doing.

2024-11-06T11:45:55.183359Z

In terms of a data specification, I don't understand the entries in the tree where you have a path like /, which then has a child "" - this really seems like implementation details dominating the structure of the data.

opqdonut 2024-11-06T12:11:51.121699Z

I don't disagree

opqdonut 2024-11-06T12:12:28.264769Z

the fact that you can only have handlers in leaf nodes in the tree is subtle

2024-11-06T12:27:13.140859Z

Well, it is obviously very well regarded in the community. I just struggle with it every time I make a change and the docs say relatively little about it.

2024-11-06T15:24:03.734539Z

@joel.kaasinen Do you happen to have any insight how to debug this ?

opqdonut 2024-11-06T15:25:38.209839Z

no, not really, I haven't used reitit on the frontend that much. the controllers have always "just worked" for me.

opqdonut 2024-11-06T15:25:59.085689Z

@juhoteperi might be able to help you more

2024-11-06T15:26:40.437409Z

I'm editing it side-by-side with the frontend example you mentioned, and I'm tryin to make it as similar as possible, although the URL scheme is slightly different.

2024-11-06T15:26:47.618569Z

Thank you for your help and effort in any case @joel.kaasinen!

🙏 1
roklenarcic 2024-11-05T17:41:24.775579Z

What is the difference between :compile function of middleware returning nil and {} ? What happens if both :compile and :wrap are defined in middleware?

opqdonut 2024-11-06T09:35:24.116969Z

my assumption would be that :compile overrides :wrap, and the docs & source support this

roklenarcic 2024-11-06T09:36:59.961309Z

ok, so what’s the difference between returning nil and {} from compile?

opqdonut 2024-11-06T09:37:01.232729Z

re: nil vs {}, the docs describe using {}, but I'll have to dig into the source to figure out if nil is the same

roklenarcic 2024-11-06T09:38:20.088149Z

if :compile overrrides :wrap then why is this namespace written like so:

(ns reitit.ring.middleware.parameters
  (:require [ring.middleware.params :as params]))

(def parameters-middleware
  "Middleware to parse urlencoded parameters from the query string and form
  body (if the request is a url-encoded form). Adds the following keys to
  the request map:

  :query-params - a map of parameters from the query string
  :form-params  - a map of parameters from the body
  :params       - a merged map of all types of parameter"
  {:name ::parameters
   :compile (fn [{:keys [parameters]} _]
              (if (and (some? (:form parameters)) (nil? (:body parameters)))
                {:data {:swagger {:consumes ["application/x-www-form-urlencoded"]}}}
                {}))
   :wrap params/wrap-params})

roklenarcic 2024-11-06T09:38:27.383019Z

has both compile and wrap

opqdonut 2024-11-06T09:38:56.428269Z

right, I was actually confused myself

opqdonut 2024-11-06T09:39:26.475429Z

what happens is that the thing returned by :compile is turned into a middleware map using IntoMiddleware and then merged with the original middleware map

roklenarcic 2024-11-06T09:39:43.318839Z

That’s what I thought

opqdonut 2024-11-06T09:39:49.722829Z

if :compile returns a function, that gets turned into {:wrap <function>} and thus overrides any :wrap in the original map

roklenarcic 2024-11-06T09:40:05.907359Z

I see

opqdonut 2024-11-06T09:40:05.987759Z

but if :compile returns nil or {}, the original :wrap gets used

roklenarcic 2024-11-06T09:40:35.259829Z

yeah that’s what I figued, but it’s nice to get a confirmation, thanks

opqdonut 2024-11-06T09:40:42.101759Z

no, wait, I still don't know what nil does, let me rephrase

roklenarcic 2024-11-06T09:41:01.165799Z

nil will eliminate middleware from the chain

opqdonut 2024-11-06T09:41:06.268599Z

if :compile returns {}, the original :wrap gets used

opqdonut 2024-11-06T09:41:18.818739Z

yeah, that's what the code looks like

opqdonut 2024-11-06T09:41:25.140049Z

nil means skip this

opqdonut 2024-11-06T09:41:47.361159Z

because into-middleware for the whole map will return nil if :compile returns nil

opqdonut 2024-11-06T09:42:06.531419Z

the docs could be a lot better...

opqdonut 2024-11-06T09:42:29.448699Z

ah, it is mentioned in compiling_middleware.md:

However, in this case the compile function returns nil when that key is missing, which means the middleware will not be mounted, the spec will not be considered, and the compiler will not enforce this requirement as intended.