Using POST URI parameters and body

511 views
Skip to first unread message

Tzach

unread,
Feb 10, 2013, 12:44:20 PM2/10/13
to comp...@googlegroups.com

I’m trying to create  a POST handler which get a key in the URI, and a value in the message body.

This is what I use from ClojureScript (with jayq)

 (let [url “http://localhost:8086/5684ad00-02bc-49d7-9993-957573fd8765”]

    (ajax url {:async true :type "POST" :data “text”)}))

 

This is what I have on the server side:

  (POST "/:guid"  {body :body}

        (str "stored:" (slurp body))

        )

 

And I use   (wrap-params) on the handler.

The request seems to be OK, but I fail to parse the body.

Can I even do that, or should I pass both parameters in body or in req-uri?

 Thanks

James Reeves

unread,
Feb 10, 2013, 12:52:07 PM2/10/13
to Compojure
Could you explain what you mean by "fail to parse the body"?

Have you made sure the content-type of the AJAX request is correct?

You don't seem to do anything with the "guid" parameter. Is that deliberate?

- James


--
You received this message because you are subscribed to the Google Groups "Compojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to compojure+...@googlegroups.com.
To post to this group, send email to comp...@googlegroups.com.
Visit this group at http://groups.google.com/group/compojure?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Tzach

unread,
Feb 10, 2013, 1:14:48 PM2/10/13
to comp...@googlegroups.com, ja...@booleanknot.com
Thanks for the prompt response.

I plan to store the values in a DB with guid as a key, and the body as the value.
Body is pure text (not JSON).
Content-Type:application/x-www-form-urlencoded; charset=UTF-8

I successfully get the param from the URI with
(POST "/:guid"  [guid] ...

What syntax should I use to fetch the body?
I'm probably missing something basic here.

Thanks!

James Reeves

unread,
Feb 10, 2013, 1:25:30 PM2/10/13
to Tzach, Compojure
If the body is pure text, then you have the wrong content-type.

The "application/x-www-form-urlencoded" content type tells Ring that you have a url-encoded form in your request body, and therefore wrap-params will attempt to parse it, consuming the input-stream of the body.

You'll first want to set your content type correctly to "text/plain", and then you can use a route like:

(POST "/:guid" [guid :as {body :body}]
  ...)

See here for more details about destructing in Compojure:

- James

Tzach

unread,
Feb 10, 2013, 3:16:37 PM2/10/13
to comp...@googlegroups.com, Tzach, ja...@booleanknot.com

Thanks James

Works like a charm.

Your help is much appreciated!

Tzach

unread,
Feb 14, 2013, 1:00:57 AM2/14/13
to comp...@googlegroups.com, Tzach, ja...@booleanknot.com
Does any one have an example of using ClojureScript jayq ajax with Compojure REST?
I'm have the following REST server in Clojure:

(defn get-document [id]
  (ring-res/response
   {:intext
    (if-let [input (:intext (db/get-key id))]
      input
      *id-not-found*)
    }))

(defn update-document [id body]
  (let [text (:intext body)]
    (db/put id text)
    {:status 200}))

(def crud-context
  (context "/:id" [id]
           (defroutes api-routes
             (GET    "/" [] (get-document id))
             (PUT    "/" {body :body} (update-document id body))
             (DELETE "/" [] (delete-document id)))))

(defroutes app-routes
  (GET "/" [] (main-page nil))
  crud-context
  (route/not-found "Not Found"))

(def app 
  (-> app-routes
      (wrap-params)
      (jmw/wrap-json-body {:keywords? true})
      (jmw/wrap-json-response)
      (resources/wrap-resource "public")))

This seems to works fine when I test it internally, but update fails when calling it from ClojureScript:
(defn update-document [id body]
  (let [post-uri (str (site) id)]
    (ajax post-uri  {:async true
                     :type "PUT"
;;                     :contentType "application/json"
                     :dataType "json"
                     :data  body
                     })))

(update-document 4444 (clj->js {:intext "good morning"}))

Does return 200, but the JSON param to DB is always nil, regardless of all the permutations I tried.
Probably a stupid mistake, but I'm banging my head on it for 2 days...

Thanks
Tzach

James Reeves

unread,
Feb 14, 2013, 4:48:16 AM2/14/13
to Tzach, Compojure
Try changing the (ajax ...) part to (.log js/console ...). That way you can see exactly what it's passing to the ajax function.

You might also want to search the generated Javascript and see what your update-document code is turned into.

- James

Tzach

unread,
Feb 14, 2013, 10:48:48 AM2/14/13
to comp...@googlegroups.com, Tzach, ja...@booleanknot.com
Thanks James!
I was right all along: it was a stupid mistake :)
My mistake was looking at the :body, when the parameters was available in the form-params

the following combination of client/server works
CLJ server:
(defn get-document [id]
  (ring-res/response
   {:intext
    (if-let [input (:intext (db/get-key id))]
      input
      *id-not-found*)
    }))
 
(defn update-document [id param]
  (let [intext (param "intext")]
    (db/put id intext)
    (ring-res/response (pr-str "stored. key: " id ", val:" intext))))

(defn delete-document [id]
  "TBD"
  )

(def crud-context
  (context "/:id" [id]
           (defroutes api-routes
             (GET    "/" [] (get-document id))
             (PUT    "/" {form-params :form-params} (update-document id form-params))
             (PUT "/" req (ring-res/response (pr-str req)))
             (DELETE "/" [] (delete-document id)))))

(defroutes app-routes
  (GET "/" [] (main-page nil))
  crud-context
  (route/not-found "Not Found"))

(def app 
  (-> app-routes
      (wrap-params)
      (jmw/wrap-json-body {:keywords? true})
      (jmw/wrap-json-response)
      (resources/wrap-resource "public")))

Client in CLJS
(defn update-document [id body]
  (let [post-uri (str (site) id)]
    (ajax post-uri  {:async true
                     :type "PUT"
                     :dataType "json"
                     :data  (clj->js body)
                     })))



(defn get-document [id]
  (let [get-uri (str (site)  id)]
    (log (str "get-document:" get-uri))
    (xhr [:get get-uri] {}
         #(->> %
              js->clj
              ("intext")
              (val $intext)
              ))))

;; working examples:
;; (update-document 4459 {:intext "hello clojure!"})
;; (get-document 4459)
Reply all
Reply to author
Forward
0 new messages