11

I'm trying to pull a value out of the url query string however I can return what I believe is a map, however when i use the below code, it doesn't process it as expected. Can anyone advise how I access specific values in the returned querystring datastructure?

http://localhost:8080/remservice?foo=bar

(defroutes my-routes
  (GET "/" [] (layout (home-view)))
  (GET "/remservice*" {params :query-params} (str (:parameter params))))
Dale
  • 579
  • 1
  • 7
  • 13
  • Here are two questions. Does this function take a parameter? What is GET? Here is why I'm asking. You should be able to extract what you need from params, but where is params? – octopusgrabbus Jan 22 '12 at 18:45

4 Answers4

21

You'll need to wrap your handler in compojure.handler/api or compojure.handler/site to add appropriate middleware to gain access to :query-params. This used to happen automagically in defroutes, but no longer does. Once you do that, the {params :query-params} destructuring form will cause params to be bound to {"foo" "bar"} when you hit /remservice with foo=bar as the query string.

(Or you could add in wrap-params etc. by hand -- these reside in various ring.middleware.* namespaces; see the code of compojure.handler (link to the relevant file in Compojure 1.0.1) for their names.)

E.g.

(defroutes my-routes
  (GET "/remservice*" {params :query-params}
       (str params)))

(def handler (-> my-routes compojure.handler/api))

; now pass #'handler to run-jetty (if that's what you're using)

If you now hit http://localhost:8080/remservice?foo=bar, you should see {"foo" "bar"} -- the textual representation of your query string parsed into a Clojure map.

Michał Marczyk
  • 83,634
  • 13
  • 201
  • 212
  • Ok I've got it returning a map, however i can't seem to access in the individual entries, e.g. (:foo params) or (get params foo) or (map :foo params) does not return anything. I think thats my main confusion around this map structure returned. – Dale Jan 23 '12 at 12:33
  • 2
    That's because the keys are kept in string form -- you'll need to use `(get params "foo")`. Alternatively, you can use `:params` instead of `:query-params` -- Compojure's `api` adds in the `wrap-keyword-params` middleware, so the `:params` map is "keyified" -- but note that `:params` includes both types of parameters (the other being form parameters; query parameters override form parameters in the `:params` map). – Michał Marczyk Jan 23 '12 at 14:09
  • How do you do something like this: /users/123?sort=desc I have params passed to the vector. – Justin Thomas Dec 07 '15 at 23:24
1

In the default app for compojure 1.2.0, the querystring middleware seems included by default. You can inspect the request as such.

(GET "/" request (str request))

It should have a lot of stuff, including the params key.

{ . . .  :params {:key1 "value1" :key2 "value2} . . . }

As such, you can include a standard Clojure destructuring form to access the query parameters in your response.

(GET "/" {params :params} (str params))

Your page should then look like the following.

{"key1" "value1", "key2" "value2"}

As noted in the comment by Michal above, however, the keys are converted to strings and if you'd like to access them you need to use the get function rather than the more convenient symbol lookups.

(GET "/" {params :params} (get params "key1"))

;;the response body should be "value1"
rewon
  • 573
  • 5
  • 10
0

With compojure 1.6.1 HTTP-request-destructuring works for me in a such way:

  1. add [ring/ring-defaults "0.3.2"] in :dependencies in project.clj (because compojure.handler namespace was deprecated since 1.2 in favor of the [ring-defaults])
  2. add [ring.middleware.defaults :refer :all] in :require in your.routes.namespace
  3. add (def site (wrap-defaults app site-defaults)) in your.routes.namespace, where app is declared via (defroutes app ...
  4. add :ring {:handler your.routes.namespace/site} in project.clj
Dedkov Vadim
  • 426
  • 5
  • 10
-1

I had luck in compojure 1.1.5 not needing a wrapper and being able to use the :as directive

(GET "/tweet/:folder/:detail" [folder detail :as req]
  (twitter-controller/tweet folder detail (-> req :params :oauth_verifier))
Dax Fohl
  • 10,654
  • 6
  • 46
  • 90