Reputation: 3638
I am writing a web app using Ring and Compojure, and Friend library for authorization. Recently I've made some changes to the project, and now I am not able to fetch request parameters any more.
What I used to do is this:
; Routes definition
(defroutes app-routes
(POST "/*.do" request
(insert-data (:params request))))
; Middlewares
(def secured-routes
(handler/site
(-> app-routes
wrap-params
(friend/authenticate friend-params-map))))
and form/URL parameters would be parsed into a Clojure map. Right now this does not seem to work, and (:params request)
contains maps of the form
{:* <request-url>}
with a single :*
key. If I try to (println request)
, a get a Clojure map with lots of key-value pairs, among which there are
:body #object[org.eclipse.jetty.server.HttpInputOverHTTP 0x6ef9a9e1 HttpInputOverHTTP@6ef9a9e1]
that seem to contain request data, correct? But how do I fetch those?
Previously I was just using wrap-params
middleware as described above, and it worked.
One approach that works is invoking (body-string request)
in each handler, that will return a stringified version of request body. But it would be great to get an automatically parsed Clojure map for each url handler. Obviously, I'm missing something.
Can someone please advise? I would also be happy to find out more how to debug those kinds of handler issues myself - meaning, debug middleware chains and find out why wrap-params
does not get invoked or is invoked improperly.
Thanks!
UPDATE: per @nberger's comment, i've tried changing secured-routes
definition to this:
(def secured-routes
(-> app-routes
(wrap-defaults site-defaults)
(friend/authenticate friend-params-map)))
but now the login page does not work at all (authentication stopped working). After moving wrap-defaults
after friend/authenticate
as suggested in the comment, Friend complains in big font about Invalid anti-forgery token (???)
Upvotes: 4
Views: 949
Reputation: 3638
I've found the issue. In the front-end code, POST
s to *.do have been modified to send application/json
content-type. Below is the jQuery's ajax call that was used:
$.ajax({
url: '/saveInput.do',
type: 'POST',
contentType: 'application/json; charset=UTF-8',
data: JSON.stringify(formValues),
});
I've modified it to
$.ajax({
url: '/saveInput.do',
type: 'POST',
data: formValues,
});
and it works now. Moreover, original Ajax call with JSON content-type can be preserved by including wrap-json-params
middleware from ring-json, so that routes definition finally becomes:
(def secured-routes
(-> app-routes
(friend/authenticate friend-params-map)
(wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false))
wrap-json-params))
I've opted for the latter. @nberger - thank you for help!
Upvotes: 2