Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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))))
like image 516
Dale Avatar asked Jan 22 '12 17:01

Dale


People also ask

How do you split a query string?

The query string is composed of a series of field-value pairs. Within each pair, the field name and value are separated by an equals sign, " = ". The series of pairs is separated by the ampersand, " & " (semicolons " ; " are not recommended by the W3C anymore, see below).

What is parse query string?

The ParseQueryString method uses UTF8 format to parse the query string In the returned NameValueCollection, URL-encoded characters are decoded and multiple occurrences of the same query string parameter are listed as a single entry with a comma separating each value.

Where does the query string store information?

A query string is the portion of a URL where data is passed to a web application and/or back-end database. The reason we need query strings is that the HTTP protocol is stateless by design. For a website to be anything more than a brochure, you need to maintain state (store data).


2 Answers

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.

like image 158
Michał Marczyk Avatar answered Oct 29 '22 22:10

Michał Marczyk


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"
like image 36
rewon Avatar answered Oct 29 '22 23:10

rewon