reitit 2024-11-05

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.

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

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

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

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

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

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.

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.

I don't disagree

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

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.

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

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

@juhoteperi might be able to help you more

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.

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

🙏 1

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

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

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

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

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

has both compile and wrap

right, I was actually confused myself

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

That’s what I thought

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

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

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

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

nil will eliminate middleware from the chain

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

yeah, that's what the code looks like

nil means skip this

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

the docs could be a lot better...

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.