Closed telekid closed 1 year ago
Excellent feedback @telekid,
I think you're right that we should use a better name than middleware for the reason you state. The key idea is that we might want to transform the request before we bind request parameters to the function argument. We only want to do that when the function is being updated, not on the initial render. That's why its different from regular ring middleware. For the case where you want to transform the response object that should be handled by regular ring middleware.
For the case when you want to update e.g. headers simply use the req
middleware (name soon to be changed) as it receives the entire request object. I think prebind
might be a better name than middleware, do you agree?
The key idea is that we might want to transform the request before we bind request parameters to the function argument
Makes sense.
We only want to do that when the function is being updated, not on the initial render.
Makes sense, though (I think?) I can imagine a different implementation that conditionally applies a traditional ring middleware within the standard ring middleware chain (but included via your current req
metadata strategy) when the component is serving as an endpoint root, but not when it is participating as a child component of a different render.
For the case when you want to update e.g. headers simply use the req middleware (name soon to be changed) as it receives the entire request object
In my case I'm interested in updating response headers, not request headers, so this won't quite do. I am still having trouble imaging how I might modify response headers as part of the same request that is returning an HTML fragment as part of a ctmx component re-render. Where would I put that traditional middleware? Should I modify the routes returned by ctmx's make-routes
function, manually appending middleware to the route that corresponds to the component in question? My initial reaction is that doing so feels a bit cumbersome.
I would suggest you have two options. Firstly you can always return a regular ring response map from component update. By default when you return html represented as hiccup it is rendered and put into a response map. If the component returns a map ctmx
assumes it's already a valid ring response.
You can also use regular ring middleware and check for the HX-Request=true
header. Details. This is not set on initial render. The limitation is that it doesn't know exactly which component it is going to.
I could modify the existing middleware
option to receive both request and response but I wonder if its easier to just return a map directly from the component. What do you think?
Apologies for the slow response!
I could modify the existing middleware option to receive both request and response but I wonder if its easier to just return a map directly from the component. What do you think?
This makes sense. Not sure why this hadn't occurred to me the first time around. I'll give this a shot next time I'm working in that area of my codebase.
Thanks for your help!
@telekid here's a PR to address the issue https://github.com/whamtet/ctmx/pull/28/files
First, thanks for getting back to me regarding my previous question, and for making this library in the first place. I've enjoyed exploring it so far!
I'm following up on a message I dropped in the clojurians #ctmx channel.
Generally, when I see the word
middleware
– especially in aring
context – I think of a function like this:That is, I expect a function that takes a handler and returns a new handler that typically invokes the passed handler with the
req
argument.ctmx
's^{:req middleware}
metadata is confusing, as it doesn't behave as we typically expect middleware to behave;middleware
is rather expected to be something akin to a request transformer, i.e. a simpler function of typereq -> req
.A few thoughts.
To start, I'm wondering if there a reason that you've created ctmx's middleware such that it is capable of transforming the
req
map passed into a component, but cannot transform the response map returned by it? My hunch is that this restriction is intentional, though it isn't immediately clear to me why that might be. (Perhaps you feel the semantics of the interaction betweenctmx
's middleware andring
's middleware stack to be a bit tricky to define, particularly in the case of nested components? Just guessing here.)I ask because component middleware seems like a fairly elegant way to separate view and controller concerns, but this approach is fairly limited if one cannot update headers in the response object, for example.
If this restriction is intentional, then I might consider changing the name from middleware to something else to reduce confusion.
But I should also ask: am I barking up the wrong tree here? Do you recommend a different strategy for making modifications to the response object that extend beyond the
:body
key? Imagine that one is making a login component, for example, where login success should add:user-identity
info to a:session
map on the response object. How would you go about that currently?