This question is off the back of a previous question I asked here a few days ago. One of the comments was that I should dispense with the Ring middleware for extracting query parameters and write my own. One alternative that I thought I'd play with was harnessing the existing one to get what I want and I've been doing some digging into the Ring source code. It does almost exactly what I want. If I write out how I understand it works:
- A middleware has the function wrap-params which calls params-request
- params-request adds a
params
map to therequest
map, callsassoc-query-params
- assoc-query-params eventually calls ring.util.codec/form-decode on the incoming query string to turn it into a map
- form-decode uses assoc-conj to merge values into an existing map via reduce
- assoc-conj's docstring says
Associate a key with a value in a map. If the key already exists in the map, a vector of values is associated with the key.
This last function is the one that is problematic in my previous question (TL;DR: I want the map's values to be consistent in class of either a string or a vector). With my object orientated hat on I would have easily solved this by subclassing and overriding the method that I need the behaviour changed. However for Clojure I cannot see how to just replace the one function without having to alter everything up the stack. Is this possible and is it easy, or should I be doing this another way? If it comes to it I could copy the entire middleware library and the codec one, but it seems a bit heavyweight to me.