Dale
Dale

Reputation: 599

Accessing Compojure query string

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))))

Upvotes: 13

Views: 7800

Answers (4)

Dedkov Vadim
Dedkov Vadim

Reputation: 436

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

Upvotes: 0

rewon
rewon

Reputation: 593

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"

Upvotes: 1

Dax Fohl
Dax Fohl

Reputation: 10781

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))

Upvotes: -1

Michał Marczyk
Michał Marczyk

Reputation: 84341

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.

Upvotes: 21

Related Questions