@weavejester In response to https://clojurians.slack.com/archives/C8NUSGWG6/p1787873729166829?thread_ts=1787834980.105349&cid=C8NUSGWG6 The gist is that I some times run into the fact that the ring format has fields that have different meanings depending on if we are in the request or response phase.
If we see the whole Ring process a chain, the app is somewhere in the middle and is wrapped by middleware, then there is some kind of ambiguity:
I.e.
:headers => request headers or response headers
:cookies => cookies from the request, cookies from the app, or cookies added by some middleware.
:sessions => same as cookies, can be incoming our outgoing
In this moment I cannot find a clear case to illustrate when this leads to problems or confusion. This means I have to reflect on what I am saying is correct and not a case of where I was misusing it. But generally I can confess that the whole wrapping of middleware sometimes trips me up, and I especially had this when I was trying to compose with the 3-arity async wrappers. I'm not saying they are wrong, it might be me that is not getting it.
I lately had the feeling I would have less issues when it would be :request/headers, :response/headers etc, or via nesting {:response ... :request ...}. It is actually easy to implement a middleware for this and experiment so I might try that.
how is it ambiguous? the one you get as input is the request, the one returned by the handler is the response they are 2 separate maps
In my mind they are ambiguous. If I look at code and I see (:cookies ..) I need to know if I am working on the response or request
So again I am not saying anything is wrong, just sharing my confusion and trying to elaborate on my confusion as requested by @weavejester And hopefully (or not) I can make my point with a clear example when I find it.
If I were writing Ring from scratch, I'd definitely use namespaced keywords such as :ring.request/headers and :ring.response/headers. In fact, I recently had plans for a "Ring 2.0" with those very changes, amongst others. However, maintaining backward compatibility and supporting two different request/response map formats turned out to be more of a pain than the problem it was attempting to solve. Given that backward compatibility is a priority of Ring, plans for a "2.0" version were shelved.
That all said, usually you give the request and response maps different names which disambiguates them. e.g. (:cookies response) vs. (:cookies request). The only time I can think of that this could be problematic is when dealing with middleware while using destructuring:
(defn wrap-middleware [handler]
(fn [{:keys [cookies] :as request}]
(let [{:keys [cookies] :as response} (handler request)]
...)))
But in that edge case you can name the variables something a little more specific:
(defn wrap-middleware [handler]
(fn [{req-cookies :cookies :as request}]
(let [{resp-cookies :cookies :as response} (handler request)]
...)))Given that backward compatibility is a priority of Ring, plans for a "2.0" version were shelved.Your talk on this is a classic!
Thanks for explaining @weavejester. I understand there will be no change in Ring. That is ok and makes total sense given backwards compatibility. I didn't expect that either. I will get back to this thread when I find the scenario again where I got confused