Clojure luminus and multiple identical request parameters

147 views Asked by At

Just playing with Luminus and I have a simple search function

(def filename "/somewhere/on/my/harddrive")
(defn search [request]
  (let [q (-> request :params :q)]
    (layout/render request "results.html" {:data (helpers/match-lines-from-filename q filename)})))

All works very nicely when visiting localhost:3000/search?q=foo. However, when I visit localhost:3000/search?q=foo&q=bar, I get the following error

class clojure.lang.PersistentVector cannot be cast to class java.lang.CharSequence

I know exactly what the problem is, the first URL inserts {:q "foo"} into the param and the latter gives {:q ["foo" "bar"]}. I could lash up a fix with something like this into my controller:

(if (string? q) q (last q))

but as a beginner to Luminus and Clojure I'm not sure if I'm holding it wrong. I've been searching the internet a while for prior art with no success.

I am aware of the Struct library. This seems to get half-way there, but using st/string would give the error "must be a string" rather than just taking the last value.

To be clear, I could probably stop the 500 errors in my own code, but I'm just hoping that somewhere there's a line in the Luminus documentation that caters for just working(TM) with multiple identical keys, with minimal fuss. To compare with other frameworks (info to the best of my knowledge as some frameworks I haven't used in years):

  • Django: Returns the last value provided
  • Rails: Takes the last parameter provided unless the key ends in [], in which case it forces a list.
  • Mojolicious: Provides two separate methods for returning params, one like Django, the other always gives a list (even an empty one)
  • Python urlparse: Always returns a list

Each of these feels more intuitive to me, but if there's something I'm missing please do let me know.

Addendum:

Per @noah-bogart's good suggestion for turning this into a specific question here's an attempt: The default behaviour in Luminus seems to me to give 500 errors via an easily reproducable client mechanism outlined above. Other web frameworks guard against this effectively at no cost to the end-developer, again outlined above. Is there a middleware or namespace within Luminus or the wider ecosystem that offers this functionality?

Post Addendum:

To expand what I wrote above about Django, that framework has a similar process to Mojolicious, whereby you can specify whether you want a list or a single value.

0

There are 0 answers